diff --git a/src/main/java/org/springframework/hateoas/ResourceAssembler.java b/src/main/java/org/springframework/hateoas/ResourceAssembler.java index 60dfbd61..64a092a2 100755 --- a/src/main/java/org/springframework/hateoas/ResourceAssembler.java +++ b/src/main/java/org/springframework/hateoas/ResourceAssembler.java @@ -20,7 +20,7 @@ import java.util.List; /** * Interface for components that convert a domain type into a {@link ResourceSupport}. - * + * * @author Oliver Gierke * @author Greg Turnquist */ @@ -28,21 +28,21 @@ public interface ResourceAssembler { /** * Converts the given entity into a {@code D}, which extends {@link ResourceSupport}. - * + * * @param entity * @return */ D toResource(T entity); /** - * Converts an {@link Iterable} or {@code T}s into an {@link Iterable} of {@link ResourceSupport} and wraps - * them in a {@link Resources} instance. - * + * Converts an {@link Iterable} or {@code T}s into an {@link Iterable} of {@link ResourceSupport} and wraps them in a + * {@link Resources} instance. + * * @param entities must not be {@literal null}. * @return {@link Resources} containing {@code D}. */ default Resources toResources(Iterable entities) { - + List resources = new ArrayList<>(); for (T entity : entities) { resources.add(toResource(entity)); diff --git a/src/main/java/org/springframework/hateoas/collectionjson/CollectionJsonConfigurationProvider.java b/src/main/java/org/springframework/hateoas/collectionjson/CollectionJsonConfigurationProvider.java new file mode 100644 index 00000000..6475576c --- /dev/null +++ b/src/main/java/org/springframework/hateoas/collectionjson/CollectionJsonConfigurationProvider.java @@ -0,0 +1,47 @@ +/* + * Copyright 2019 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.springframework.hateoas.collectionjson; + +import java.util.Collection; + +import org.springframework.hateoas.MediaTypes; +import org.springframework.hateoas.config.HypermediaMappingInformation; +import org.springframework.hateoas.config.MediaTypeConfigurationProvider; +import org.springframework.http.MediaType; + +/** + * @author Oliver Gierke + */ +class CollectionJsonConfigurationProvider implements MediaTypeConfigurationProvider { + + /* + * (non-Javadoc) + * @see org.springframework.hateoas.config.MediaTypeConfigurationProvider#getConfiguration() + */ + @Override + public Class getConfiguration() { + return CollectionJsonMediaTypeConfiguration.class; + } + + /* + * (non-Javadoc) + * @see org.springframework.hateoas.config.MediaTypeConfigurationProvider#supportsAny(java.util.Collection) + */ + @Override + public boolean supportsAny(Collection mediaTypes) { + return mediaTypes.contains(MediaTypes.COLLECTION_JSON); + } +} diff --git a/src/main/java/org/springframework/hateoas/collectionjson/CollectionJsonConfigurer.java b/src/main/java/org/springframework/hateoas/collectionjson/CollectionJsonMediaTypeConfiguration.java similarity index 61% rename from src/main/java/org/springframework/hateoas/collectionjson/CollectionJsonConfigurer.java rename to src/main/java/org/springframework/hateoas/collectionjson/CollectionJsonMediaTypeConfiguration.java index d69b50c0..f0f9aa02 100644 --- a/src/main/java/org/springframework/hateoas/collectionjson/CollectionJsonConfigurer.java +++ b/src/main/java/org/springframework/hateoas/collectionjson/CollectionJsonMediaTypeConfiguration.java @@ -21,43 +21,40 @@ import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.hateoas.LinkDiscoverer; import org.springframework.hateoas.config.EnableHypermediaSupport.HypermediaType; -import org.springframework.hateoas.config.Hypermedia; +import org.springframework.hateoas.config.HypermediaMappingInformation; import org.springframework.http.MediaType; -import com.fasterxml.jackson.databind.DeserializationFeature; -import com.fasterxml.jackson.databind.ObjectMapper; +import com.fasterxml.jackson.databind.Module; /** + * Configuration setup for Collection/JSON. + * * @author Greg Turnquist + * @author Oliver Drotbohm */ @Configuration -public class CollectionJsonConfigurer { - - @Bean - Hypermedia collectionJsonBean() { - - return new Hypermedia() { - @Override - public List getMediaTypes() { - return HypermediaType.COLLECTION_JSON.getMediaTypes(); - } - - @Override - public ObjectMapper createObjectMapper(ObjectMapper mapper) { - - ObjectMapper mapper1 = mapper.copy(); - - mapper1.disable(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES); - mapper1.registerModule(new Jackson2CollectionJsonModule()); - - return mapper1; - } - }; - } +class CollectionJsonMediaTypeConfiguration implements HypermediaMappingInformation { @Bean LinkDiscoverer linkDiscoverer() { return new CollectionJsonLinkDiscoverer(); } + /* + * (non-Javadoc) + * @see org.springframework.hateoas.config.HypermediaMappingInformation#getMediaTypes() + */ + @Override + public List getMediaTypes() { + return HypermediaType.COLLECTION_JSON.getMediaTypes(); + } + + /* + * (non-Javadoc) + * @see org.springframework.hateoas.config.HypermediaMappingInformation#getJacksonModule() + */ + @Override + public Module getJacksonModule() { + return new Jackson2CollectionJsonModule(); + } } diff --git a/src/main/java/org/springframework/hateoas/collectionjson/Jackson2CollectionJsonModule.java b/src/main/java/org/springframework/hateoas/collectionjson/Jackson2CollectionJsonModule.java index 7942b3e5..d4aa6b3d 100644 --- a/src/main/java/org/springframework/hateoas/collectionjson/Jackson2CollectionJsonModule.java +++ b/src/main/java/org/springframework/hateoas/collectionjson/Jackson2CollectionJsonModule.java @@ -1,5 +1,5 @@ /* - * Copyright 2015 the original author or authors. + * Copyright 2015-2019 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -63,8 +63,9 @@ import com.fasterxml.jackson.databind.type.TypeFactory; * in Collection+JSON compatible JSON. * * @author Greg Turnquist + * @author Oliver Drotbohm */ -public class Jackson2CollectionJsonModule extends SimpleModule { +class Jackson2CollectionJsonModule extends SimpleModule { private static final long serialVersionUID = -6540574644565592709L; diff --git a/src/main/java/org/springframework/hateoas/config/EnableHypermediaSupport.java b/src/main/java/org/springframework/hateoas/config/EnableHypermediaSupport.java index 2ad80fe6..fb4ced14 100644 --- a/src/main/java/org/springframework/hateoas/config/EnableHypermediaSupport.java +++ b/src/main/java/org/springframework/hateoas/config/EnableHypermediaSupport.java @@ -22,20 +22,15 @@ import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; import java.util.Arrays; import java.util.List; -import java.util.Optional; import org.springframework.context.ApplicationContext; import org.springframework.context.annotation.Import; import org.springframework.hateoas.MediaTypes; -import org.springframework.hateoas.collectionjson.CollectionJsonConfigurer; -import org.springframework.hateoas.hal.HalConfigurer; -import org.springframework.hateoas.hal.forms.HalFormsConfigurer; -import org.springframework.hateoas.uber.UberConfigurer; import org.springframework.http.MediaType; /** * Activates hypermedia support in the {@link ApplicationContext}. Will register infrastructure beans to support all - * appropriate web stacks based on selected {@link Hypermedia}-type as well as the classpath. + * appropriate web stacks based on selected {@link HypermediaMappingInformation}-type as well as the classpath. * * @author Oliver Gierke * @author Greg Turnquist @@ -44,7 +39,7 @@ import org.springframework.http.MediaType; @Target(ElementType.TYPE) @Documented @EnableEntityLinks -@Import({ HypermediaSupportBeanDefinitionRegistrar.class, HateoasConfiguration.class, WebStackImportSelector.class }) +@Import({ HypermediaConfigurationImportSelector.class, HateoasConfiguration.class, WebStackImportSelector.class }) public @interface EnableHypermediaSupport { /** @@ -60,7 +55,7 @@ public @interface EnableHypermediaSupport { * @author Oliver Gierke * @author Greg Turnquist */ - enum HypermediaType implements Hypermedia { + enum HypermediaType { /** * HAL - Hypermedia Application Language. @@ -68,47 +63,37 @@ public @interface EnableHypermediaSupport { * @see http://stateless.co/hal_specification.html * @see http://tools.ietf.org/html/draft-kelly-json-hal-05 */ - HAL(HalConfigurer.class, MediaTypes.HAL_JSON, MediaTypes.HAL_JSON_UTF8), + HAL(MediaTypes.HAL_JSON, MediaTypes.HAL_JSON_UTF8), /** * HAL-FORMS - Independent, backward-compatible extension of the HAL designed to add runtime FORM support * * @see https://rwcbook.github.io/hal-forms/ */ - HAL_FORMS(HalFormsConfigurer.class, MediaTypes.HAL_FORMS_JSON), + HAL_FORMS(MediaTypes.HAL_FORMS_JSON), /** * Collection+JSON * * @see http://amundsen.com/media-types/collection/format/ */ - COLLECTION_JSON(CollectionJsonConfigurer.class, MediaTypes.COLLECTION_JSON), + COLLECTION_JSON(MediaTypes.COLLECTION_JSON), /** * UBER Hypermedia * * @see http://uberhypermedia.org/ */ - UBER(UberConfigurer.class, MediaTypes.UBER_JSON); + UBER(MediaTypes.UBER_JSON); - private final Class configurer; private final List mediaTypes; - HypermediaType(Class configurer, MediaType... mediaTypes) { - - this.configurer = configurer; + HypermediaType(MediaType... mediaTypes) { this.mediaTypes = Arrays.asList(mediaTypes); } - @Override public List getMediaTypes() { return this.mediaTypes; } - - @Override - public Optional> configurer() { - return Optional.ofNullable(this.configurer); - } - } } diff --git a/src/main/java/org/springframework/hateoas/config/EntityLinksConfiguration.java b/src/main/java/org/springframework/hateoas/config/EntityLinksConfiguration.java index 3520ef99..3292fad4 100644 --- a/src/main/java/org/springframework/hateoas/config/EntityLinksConfiguration.java +++ b/src/main/java/org/springframework/hateoas/config/EntityLinksConfiguration.java @@ -15,6 +15,7 @@ */ package org.springframework.hateoas.config; +import org.springframework.beans.factory.ObjectProvider; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.DependsOn; @@ -54,17 +55,12 @@ class EntityLinksConfiguration { } @Bean - ControllerEntityLinksFactoryBean controllerEntityLinks(WebMvcLinkBuilderFactory controllerLinkBuilderFactory) { + ControllerEntityLinksFactoryBean controllerEntityLinks(ObjectProvider linkBuilderFactory) { ControllerEntityLinksFactoryBean factory = new ControllerEntityLinksFactoryBean(); factory.setAnnotation(Controller.class); - factory.setLinkBuilderFactory(controllerLinkBuilderFactory); + factory.setLinkBuilderFactory(linkBuilderFactory.getIfAvailable(WebMvcLinkBuilderFactory::new)); return factory; } - - @Bean - WebMvcLinkBuilderFactory webMvcLinkBuilderFactoryBean() { - return new WebMvcLinkBuilderFactory(); - } } diff --git a/src/main/java/org/springframework/hateoas/config/Hypermedia.java b/src/main/java/org/springframework/hateoas/config/Hypermedia.java deleted file mode 100644 index 1b671e54..00000000 --- a/src/main/java/org/springframework/hateoas/config/Hypermedia.java +++ /dev/null @@ -1,55 +0,0 @@ -/* - * Copyright 2019 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.springframework.hateoas.config; - -import java.util.List; -import java.util.Optional; - -import org.springframework.http.MediaType; -import org.springframework.util.MimeType; - -import com.fasterxml.jackson.databind.ObjectMapper; - -/** - * Interface for registering custom hypermedia handlers. - * - * @author Greg Turnquist - */ -public interface Hypermedia { - - /** - * {@link MediaType}s this hypermedia can handle. - */ - List getMediaTypes(); - - /** - * Convert list of {@link MediaType}s into an array of {@link MimeType}s to support various Spring constructors. - */ - default MimeType[] getMimeTypes() { - return getMediaTypes().toArray(new MimeType[0]); - } - - /** - * Create an {@link ObjectMapper} and register custom serializers and deserializers for the supported media types. - */ - default ObjectMapper createObjectMapper(ObjectMapper mapper) { - return mapper.copy(); - } - - default Optional> configurer() { - return Optional.empty(); - } -} diff --git a/src/main/java/org/springframework/hateoas/config/HypermediaConfigurationImportSelector.java b/src/main/java/org/springframework/hateoas/config/HypermediaConfigurationImportSelector.java new file mode 100644 index 00000000..81b32cb6 --- /dev/null +++ b/src/main/java/org/springframework/hateoas/config/HypermediaConfigurationImportSelector.java @@ -0,0 +1,65 @@ +/* + * Copyright 2019 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.springframework.hateoas.config; + +import java.util.Arrays; +import java.util.Collection; +import java.util.Map; +import java.util.stream.Collectors; + +import org.springframework.context.annotation.ImportSelector; +import org.springframework.core.io.support.SpringFactoriesLoader; +import org.springframework.core.type.AnnotationMetadata; +import org.springframework.hateoas.config.EnableHypermediaSupport.HypermediaType; +import org.springframework.http.MediaType; + +/** + * {@link ImportSelector} that looks up configuration classes from all {@link MediaTypeConfigurationProvider} + * implementations listed in {@code META-INF/spring.factories}. + * + * @author Oliver Drotbohm + */ +class HypermediaConfigurationImportSelector implements ImportSelector { + + /* + * (non-Javadoc) + * @see org.springframework.context.annotation.ImportSelector#selectImports(org.springframework.core.type.AnnotationMetadata) + */ + @Override + public String[] selectImports(AnnotationMetadata metadata) { + + Map attributes = metadata.getAnnotationAttributes(EnableHypermediaSupport.class.getName()); + + Collection types = Arrays.stream((HypermediaType[]) attributes.get("type")) // + .flatMap(it -> it.getMediaTypes().stream()) // + .collect(Collectors.toList()); + + Collection configurationProviders = SpringFactoriesLoader.loadFactories( + MediaTypeConfigurationProvider.class, HypermediaConfigurationImportSelector.class.getClassLoader()); + + // No additional filtering needed. + if (types.isEmpty()) { + return configurationProviders.toArray(new String[configurationProviders.size()]); + } + + // Filter the ones supporting the given media types + return configurationProviders.stream() // + .filter(it -> it.supportsAny(types)) // + .map(MediaTypeConfigurationProvider::getConfiguration) // + .map(Class::getName) // + .toArray(String[]::new); + } +} diff --git a/src/main/java/org/springframework/hateoas/config/HypermediaMappingInformation.java b/src/main/java/org/springframework/hateoas/config/HypermediaMappingInformation.java new file mode 100644 index 00000000..830774c5 --- /dev/null +++ b/src/main/java/org/springframework/hateoas/config/HypermediaMappingInformation.java @@ -0,0 +1,69 @@ +/* + * Copyright 2019 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.springframework.hateoas.config; + +import java.util.List; +import java.util.Optional; + +import org.springframework.http.MediaType; + +import com.fasterxml.jackson.databind.DeserializationFeature; +import com.fasterxml.jackson.databind.Module; +import com.fasterxml.jackson.databind.ObjectMapper; + +/** + * Interface for registering custom hypermedia handlers. + * + * @author Greg Turnquist + * @author Oliver Drotbohm + */ +public interface HypermediaMappingInformation { + + /** + * All {@link MediaType}s this hypermedia can handle. + * + * @return + */ + List getMediaTypes(); + + /** + * Configure an {@link ObjectMapper} and register custom serializers and deserializers for the supported media types. + * If all you want to do is register a Jackson {@link Module}, prefer implementing {@link #getJacksonModule()}. + * + * @return + * @see #getJacksonModule() + */ + default ObjectMapper configureObjectMapper(ObjectMapper mapper) { + + mapper.disable(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES); + + Optional.ofNullable(getJacksonModule()).ifPresent(mapper::registerModule); + + return mapper; + } + + /** + * Optionally return the Jackson {@link Module} to be used to customize the serialization of representation models. + * Override this if there's nothing but the module to be done to setup the {@link ObjectMapper}. For more advanced + * needs, see {@link #configureObjectMapper(ObjectMapper)}. + * + * @return + * @see #configureObjectMapper(ObjectMapper) + */ + default Module getJacksonModule() { + return null; + } +} diff --git a/src/main/java/org/springframework/hateoas/config/HypermediaSupportBeanDefinitionRegistrar.java b/src/main/java/org/springframework/hateoas/config/HypermediaSupportBeanDefinitionRegistrar.java deleted file mode 100644 index 8fc393bc..00000000 --- a/src/main/java/org/springframework/hateoas/config/HypermediaSupportBeanDefinitionRegistrar.java +++ /dev/null @@ -1,96 +0,0 @@ -/* - * Copyright 2013-2019 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.springframework.hateoas.config; - -import static org.springframework.beans.factory.support.BeanDefinitionBuilder.*; -import static org.springframework.beans.factory.support.BeanDefinitionReaderUtils.*; - -import java.util.Arrays; -import java.util.Collection; -import java.util.Map; - -import org.springframework.beans.factory.config.BeanDefinitionHolder; -import org.springframework.beans.factory.support.AbstractBeanDefinition; -import org.springframework.beans.factory.support.BeanDefinitionBuilder; -import org.springframework.beans.factory.support.BeanDefinitionReaderUtils; -import org.springframework.beans.factory.support.BeanDefinitionRegistry; -import org.springframework.context.annotation.Configuration; -import org.springframework.context.annotation.ImportBeanDefinitionRegistrar; -import org.springframework.core.type.AnnotationMetadata; -import org.springframework.hateoas.EntityLinks; -import org.springframework.hateoas.config.EnableHypermediaSupport.HypermediaType; -import org.springframework.util.Assert; -import org.springframework.util.ClassUtils; - -/** - * {@link ImportBeanDefinitionRegistrar} implementation to activate hypermedia support based on the configured - * hypermedia type. Activates {@link EntityLinks} support as well (essentially as if {@link EnableEntityLinks} was - * activated as well). - * - * @author Oliver Gierke - * @author Greg Turnquist - */ -class HypermediaSupportBeanDefinitionRegistrar implements ImportBeanDefinitionRegistrar { - - private static final boolean JSONPATH_PRESENT = ClassUtils.isPresent("com.jayway.jsonpath.JsonPath", null); - - /* - * (non-Javadoc) - * @see org.springframework.context.annotation.ImportBeanDefinitionRegistrar#registerBeanDefinitions(org.springframework.core.type.AnnotationMetadata, org.springframework.beans.factory.support.BeanDefinitionRegistry) - */ - @Override - public void registerBeanDefinitions(AnnotationMetadata metadata, BeanDefinitionRegistry registry) { - - Map attributes = metadata.getAnnotationAttributes(EnableHypermediaSupport.class.getName()); - Collection types = Arrays.asList((HypermediaType[]) attributes.get("type")); - - /* - * Register all the {@link HypermediaType}s as individual beans, so they can be gathered as needed into a - * collection using the application context. - */ - for (HypermediaType type : types) { - - type.configurer().ifPresent(clazz -> { - - Assert.isTrue(clazz.isAnnotationPresent(Configuration.class), - clazz + " must have Spring's @Configuration annotation!"); - - BeanDefinitionBuilder hypermediaTypeBeanDefinition = genericBeanDefinition(clazz); - registerSourcedBeanDefinition(hypermediaTypeBeanDefinition, metadata, registry); - }); - } - - } - - private static String registerSourcedBeanDefinition(BeanDefinitionBuilder builder, AnnotationMetadata metadata, - BeanDefinitionRegistry registry) { - - AbstractBeanDefinition beanDefinition = builder.getBeanDefinition(); - String generateBeanName = BeanDefinitionReaderUtils.generateBeanName(beanDefinition, registry); - return registerSourcedBeanDefinition(builder, metadata, registry, generateBeanName); - } - - private static String registerSourcedBeanDefinition(BeanDefinitionBuilder builder, AnnotationMetadata metadata, - BeanDefinitionRegistry registry, String name) { - - AbstractBeanDefinition beanDefinition = builder.getBeanDefinition(); - beanDefinition.setSource(metadata); - - BeanDefinitionHolder holder = new BeanDefinitionHolder(beanDefinition, name); - registerBeanDefinition(holder, registry); - return name; - } -} diff --git a/src/main/java/org/springframework/hateoas/config/MediaTypeConfigurationProvider.java b/src/main/java/org/springframework/hateoas/config/MediaTypeConfigurationProvider.java new file mode 100644 index 00000000..d34b2068 --- /dev/null +++ b/src/main/java/org/springframework/hateoas/config/MediaTypeConfigurationProvider.java @@ -0,0 +1,45 @@ +/* + * Copyright 2019 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.springframework.hateoas.config; + +import java.util.Collection; + +import org.springframework.http.MediaType; + +/** + * SPI to register a media type configuration provider. + * + * @author Oliver Drotbohm + * @see HypermediaMappingInformation + */ +public interface MediaTypeConfigurationProvider { + + /** + * Returns the primary Spring configuration class to be bootstrapped for the given media type. + * + * @return + */ + Class getConfiguration(); + + /** + * Returns whether the provider supports any of the given {@link MediaType}s. Used to select the providers to be + * included into a configuration setup in case the media types to be enabled are explicitly defined. + * + * @param mediaTypes will never be {@literal null}. + * @return + */ + boolean supportsAny(Collection mediaTypes); +} diff --git a/src/main/java/org/springframework/hateoas/config/mvc/HypermediaRestTemplateBeanPostProcessor.java b/src/main/java/org/springframework/hateoas/config/mvc/HypermediaRestTemplateBeanPostProcessor.java deleted file mode 100644 index e552d34a..00000000 --- a/src/main/java/org/springframework/hateoas/config/mvc/HypermediaRestTemplateBeanPostProcessor.java +++ /dev/null @@ -1,49 +0,0 @@ -/* - * Copyright 2018-2019 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.springframework.hateoas.config.mvc; - -import lombok.RequiredArgsConstructor; - -import org.springframework.beans.BeansException; -import org.springframework.beans.factory.config.BeanPostProcessor; -import org.springframework.web.client.RestTemplate; - -/** - * {@link BeanPostProcessor} to register hypermedia support with {@link RestTemplate} instances found in the - * application context. - * - * @author Oliver Gierke - * @author Greg Turnquist - */ -@RequiredArgsConstructor -public class HypermediaRestTemplateBeanPostProcessor implements BeanPostProcessor { - - private final HypermediaWebMvcConfigurer configurer; - - /* - * (non-Javadoc) - * @see org.springframework.beans.factory.config.BeanPostProcessor#postProcessBeforeInitialization(java.lang.Object, java.lang.String) - */ - @Override - public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException { - - if (bean instanceof RestTemplate) { - this.configurer.extendMessageConverters(((RestTemplate) bean).getMessageConverters()); - } - - return bean; - } -} diff --git a/src/main/java/org/springframework/hateoas/config/mvc/HypermediaWebMvcConfigurer.java b/src/main/java/org/springframework/hateoas/config/mvc/HypermediaWebMvcConfigurer.java deleted file mode 100644 index 7743c03d..00000000 --- a/src/main/java/org/springframework/hateoas/config/mvc/HypermediaWebMvcConfigurer.java +++ /dev/null @@ -1,56 +0,0 @@ -/* - * Copyright 2018-2019 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.springframework.hateoas.config.mvc; - -import lombok.RequiredArgsConstructor; - -import java.util.Collection; -import java.util.List; - -import org.springframework.context.annotation.Configuration; -import org.springframework.hateoas.ResourceSupport; -import org.springframework.hateoas.config.Hypermedia; -import org.springframework.hateoas.mvc.TypeConstrainedMappingJackson2HttpMessageConverter; -import org.springframework.http.converter.HttpMessageConverter; -import org.springframework.web.servlet.config.annotation.WebMvcConfigurer; - -import com.fasterxml.jackson.databind.ObjectMapper; - -/** - * @author Oliver Gierke - * @author Greg Turnquist - */ -@Configuration -@RequiredArgsConstructor -public class HypermediaWebMvcConfigurer implements WebMvcConfigurer { - - private final ObjectMapper mapper; - private final Collection hypermediaTypes; - - /* - * (non-Javadoc) - * @see org.springframework.web.servlet.config.annotation.WebMvcConfigurer#extendMessageConverters(java.util.List) - */ - @Override - public void extendMessageConverters(List> converters) { - - this.hypermediaTypes.forEach(hypermedia -> { - - converters.add(0, new TypeConstrainedMappingJackson2HttpMessageConverter( - ResourceSupport.class, hypermedia.getMediaTypes(), hypermedia.createObjectMapper(this.mapper))); - }); - } -} diff --git a/src/main/java/org/springframework/hateoas/config/mvc/WebMvcHateoasConfiguration.java b/src/main/java/org/springframework/hateoas/config/mvc/WebMvcHateoasConfiguration.java index e6292e17..cbd601a3 100644 --- a/src/main/java/org/springframework/hateoas/config/mvc/WebMvcHateoasConfiguration.java +++ b/src/main/java/org/springframework/hateoas/config/mvc/WebMvcHateoasConfiguration.java @@ -15,16 +15,25 @@ */ package org.springframework.hateoas.config.mvc; -import java.util.Collection; +import lombok.RequiredArgsConstructor; +import java.util.Collection; +import java.util.List; +import java.util.stream.Collectors; + +import org.springframework.beans.BeansException; import org.springframework.beans.factory.ObjectProvider; +import org.springframework.beans.factory.config.BeanPostProcessor; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; -import org.springframework.hateoas.config.Hypermedia; -import org.springframework.hateoas.core.DelegatingRelProvider; -import org.springframework.hateoas.hal.CurieProvider; -import org.springframework.hateoas.hal.HalConfiguration; -import org.springframework.hateoas.hal.forms.HalFormsConfiguration; +import org.springframework.hateoas.ResourceSupport; +import org.springframework.hateoas.config.HypermediaMappingInformation; +import org.springframework.hateoas.mvc.TypeConstrainedMappingJackson2HttpMessageConverter; +import org.springframework.hateoas.mvc.UriComponentsContributor; +import org.springframework.hateoas.mvc.WebMvcLinkBuilderFactory; +import org.springframework.http.converter.HttpMessageConverter; +import org.springframework.web.client.RestTemplate; +import org.springframework.web.servlet.config.annotation.WebMvcConfigurer; import com.fasterxml.jackson.databind.ObjectMapper; @@ -34,13 +43,11 @@ import com.fasterxml.jackson.databind.ObjectMapper; * @author Greg Turnquist */ @Configuration -public class WebMvcHateoasConfiguration { +class WebMvcHateoasConfiguration { @Bean HypermediaWebMvcConfigurer hypermediaWebMvcConfigurer(ObjectProvider mapper, -// DelegatingRelProvider relProvider, ObjectProvider curieProvider, -// ObjectProvider halConfiguration, ObjectProvider halFormsConfiguration, - Collection hypermediaTypes) { + Collection hypermediaTypes) { return new HypermediaWebMvcConfigurer(mapper.getIfAvailable(ObjectMapper::new), hypermediaTypes); } @@ -49,4 +56,67 @@ public class WebMvcHateoasConfiguration { HypermediaRestTemplateBeanPostProcessor restTemplateBeanPostProcessor(HypermediaWebMvcConfigurer configurer) { return new HypermediaRestTemplateBeanPostProcessor(configurer); } + + @Bean + WebMvcLinkBuilderFactory webMvcLinkBuilderFactory(ObjectProvider contributors) { + + WebMvcLinkBuilderFactory factory = new WebMvcLinkBuilderFactory(); + factory.setUriComponentsContributors(contributors.stream().collect(Collectors.toList())); + + return factory; + } + + /** + * @author Oliver Gierke + * @author Greg Turnquist + */ + @RequiredArgsConstructor + static class HypermediaWebMvcConfigurer implements WebMvcConfigurer { + + private final ObjectMapper mapper; + private final Collection hypermediaTypes; + + /* + * (non-Javadoc) + * @see org.springframework.web.servlet.config.annotation.WebMvcConfigurer#extendMessageConverters(java.util.List) + */ + @Override + public void extendMessageConverters(List> converters) { + + this.hypermediaTypes.forEach(hypermedia -> { + + converters.add(0, new TypeConstrainedMappingJackson2HttpMessageConverter(ResourceSupport.class, + hypermedia.getMediaTypes(), hypermedia.configureObjectMapper(mapper.copy()))); + }); + } + } + + /** + * {@link BeanPostProcessor} to register hypermedia support with {@link RestTemplate} instances found in the + * application context. + * + * @author Oliver Gierke + * @author Greg Turnquist + */ + @RequiredArgsConstructor + static class HypermediaRestTemplateBeanPostProcessor implements BeanPostProcessor { + + private final HypermediaWebMvcConfigurer configurer; + + /* + * (non-Javadoc) + * @see org.springframework.beans.factory.config.BeanPostProcessor#postProcessBeforeInitialization(java.lang.Object, java.lang.String) + */ + @Override + public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException { + + if (!RestTemplate.class.isInstance(bean)) { + return bean; + } + + configurer.extendMessageConverters(((RestTemplate) bean).getMessageConverters()); + + return bean; + } + } } diff --git a/src/main/java/org/springframework/hateoas/config/reactive/HypermediaWebClientBeanPostProcessor.java b/src/main/java/org/springframework/hateoas/config/reactive/HypermediaWebClientBeanPostProcessor.java deleted file mode 100644 index 1a453cba..00000000 --- a/src/main/java/org/springframework/hateoas/config/reactive/HypermediaWebClientBeanPostProcessor.java +++ /dev/null @@ -1,45 +0,0 @@ -/* - * Copyright 2019 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.springframework.hateoas.config.reactive; - -import lombok.RequiredArgsConstructor; - -import org.springframework.beans.BeansException; -import org.springframework.beans.factory.config.BeanPostProcessor; -import org.springframework.web.reactive.function.client.WebClient; - -/** - * {@link BeanPostProcessor} to register the proper handlers in {@link WebClient} instances found in the - * application context. - * - * @author Greg Turnquist - * @since 1.0 - */ -@RequiredArgsConstructor -public class HypermediaWebClientBeanPostProcessor implements BeanPostProcessor { - - private final WebClientConfigurer configurer; - - @Override - public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException { - - if (bean instanceof WebClient) { - return this.configurer.registerHypermediaTypes((WebClient) bean); - } - - return bean; - } -} diff --git a/src/main/java/org/springframework/hateoas/config/reactive/HypermediaWebFluxConfigurer.java b/src/main/java/org/springframework/hateoas/config/reactive/HypermediaWebFluxConfigurer.java deleted file mode 100644 index 96bafbc2..00000000 --- a/src/main/java/org/springframework/hateoas/config/reactive/HypermediaWebFluxConfigurer.java +++ /dev/null @@ -1,72 +0,0 @@ -/* - * Copyright 2019 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.springframework.hateoas.config.reactive; - -import lombok.RequiredArgsConstructor; - -import java.util.Collection; - -import org.springframework.context.annotation.Configuration; -import org.springframework.core.codec.CharSequenceEncoder; -import org.springframework.core.codec.StringDecoder; -import org.springframework.hateoas.config.Hypermedia; -import org.springframework.http.codec.CodecConfigurer; -import org.springframework.http.codec.ServerCodecConfigurer; -import org.springframework.http.codec.json.Jackson2JsonDecoder; -import org.springframework.http.codec.json.Jackson2JsonEncoder; -import org.springframework.web.reactive.config.WebFluxConfigurer; - -import com.fasterxml.jackson.databind.ObjectMapper; - -/** - * {@link WebFluxConfigurer} to register hypermedia-aware {@link org.springframework.core.codec.Encoder}s and - * {@link org.springframework.core.codec.Decoder}s that will render hypermedia for WebFlux controllers. - * - * @author Greg Turnquist - * @since 1.0 - */ -@Configuration -@RequiredArgsConstructor -public class HypermediaWebFluxConfigurer implements WebFluxConfigurer { - - private final ObjectMapper mapper; - private final Collection hypermediaTypes; - - /** - * Configure custom HTTP message readers and writers or override built-in ones. - *

- * The configured readers and writers will be used for both annotated controllers and functional endpoints. - * - * @param configurer the configurer to use - */ - @Override - public void configureHttpMessageCodecs(ServerCodecConfigurer configurer) { - - CodecConfigurer.CustomCodecs customCodecs = configurer.customCodecs(); - - this.hypermediaTypes.forEach(hypermedia -> { - - ObjectMapper objectMapper = hypermedia.createObjectMapper(this.mapper); - customCodecs.encoder(new Jackson2JsonEncoder(objectMapper, hypermedia.getMimeTypes())); - customCodecs.decoder(new Jackson2JsonDecoder(objectMapper, hypermedia.getMimeTypes())); - }); - - customCodecs.encoder(CharSequenceEncoder.allMimeTypes()); - customCodecs.decoder(StringDecoder.allMimeTypes()); - - configurer.registerDefaults(false); - } -} diff --git a/src/main/java/org/springframework/hateoas/config/reactive/WebClientConfigurer.java b/src/main/java/org/springframework/hateoas/config/reactive/WebClientConfigurer.java index 156193dd..e30818c6 100644 --- a/src/main/java/org/springframework/hateoas/config/reactive/WebClientConfigurer.java +++ b/src/main/java/org/springframework/hateoas/config/reactive/WebClientConfigurer.java @@ -1,18 +1,3 @@ -/* - * Copyright 2019 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ package org.springframework.hateoas.config.reactive; import lombok.RequiredArgsConstructor; @@ -27,7 +12,7 @@ import org.springframework.core.codec.Decoder; import org.springframework.core.codec.Encoder; import org.springframework.core.codec.StringDecoder; import org.springframework.hateoas.config.EnableHypermediaSupport.HypermediaType; -import org.springframework.hateoas.config.Hypermedia; +import org.springframework.hateoas.config.HypermediaMappingInformation; import org.springframework.http.codec.json.Jackson2JsonDecoder; import org.springframework.http.codec.json.Jackson2JsonEncoder; import org.springframework.util.MimeType; @@ -47,11 +32,11 @@ import com.fasterxml.jackson.databind.ObjectMapper; public class WebClientConfigurer { private final ObjectMapper mapper; - private final Collection hypermediaTypes; + private final Collection hypermediaTypes; /** * Return a set of {@link ExchangeStrategies} driven by registered {@link HypermediaType}s. - * + * * @return a collection of {@link Encoder}s and {@link Decoder} assembled into a {@link ExchangeStrategies}. */ public ExchangeStrategies hypermediaExchangeStrategies() { @@ -61,10 +46,11 @@ public class WebClientConfigurer { this.hypermediaTypes.forEach(hypermedia -> { - ObjectMapper objectMapper = hypermedia.createObjectMapper(this.mapper); + ObjectMapper objectMapper = hypermedia.configureObjectMapper(this.mapper.copy()); + MimeType[] mimeTypes = hypermedia.getMediaTypes().toArray(new MimeType[0]); - encoders.add(new Jackson2JsonEncoder(objectMapper, hypermedia.getMediaTypes().toArray(new MimeType[]{}))); - decoders.add(new Jackson2JsonDecoder(objectMapper, hypermedia.getMediaTypes().toArray(new MimeType[]{}))); + encoders.add(new Jackson2JsonEncoder(objectMapper, mimeTypes)); + decoders.add(new Jackson2JsonDecoder(objectMapper, mimeTypes)); }); encoders.add(CharSequenceEncoder.allMimeTypes()); @@ -86,7 +72,6 @@ public class WebClientConfigurer { * @return mutated webClient with hypermedia support. */ public WebClient registerHypermediaTypes(WebClient webClient) { - return webClient.mutate().exchangeStrategies(hypermediaExchangeStrategies()).build(); } } diff --git a/src/main/java/org/springframework/hateoas/config/reactive/WebFluxHateoasConfiguration.java b/src/main/java/org/springframework/hateoas/config/reactive/WebFluxHateoasConfiguration.java index dcf15838..d93f0670 100644 --- a/src/main/java/org/springframework/hateoas/config/reactive/WebFluxHateoasConfiguration.java +++ b/src/main/java/org/springframework/hateoas/config/reactive/WebFluxHateoasConfiguration.java @@ -15,17 +15,26 @@ */ package org.springframework.hateoas.config.reactive; +import lombok.RequiredArgsConstructor; + import java.util.Collection; +import org.springframework.beans.BeansException; import org.springframework.beans.factory.ObjectProvider; +import org.springframework.beans.factory.config.BeanPostProcessor; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; -import org.springframework.hateoas.config.Hypermedia; -import org.springframework.hateoas.core.DelegatingRelProvider; -import org.springframework.hateoas.hal.CurieProvider; -import org.springframework.hateoas.hal.HalConfiguration; -import org.springframework.hateoas.hal.forms.HalFormsConfiguration; +import org.springframework.core.codec.CharSequenceEncoder; +import org.springframework.core.codec.StringDecoder; +import org.springframework.hateoas.config.HypermediaMappingInformation; import org.springframework.hateoas.reactive.HypermediaWebFilter; +import org.springframework.http.codec.CodecConfigurer; +import org.springframework.http.codec.ServerCodecConfigurer; +import org.springframework.http.codec.json.Jackson2JsonDecoder; +import org.springframework.http.codec.json.Jackson2JsonEncoder; +import org.springframework.util.MimeType; +import org.springframework.web.reactive.config.WebFluxConfigurer; +import org.springframework.web.reactive.function.client.WebClient; import com.fasterxml.jackson.databind.ObjectMapper; @@ -36,12 +45,11 @@ import com.fasterxml.jackson.databind.ObjectMapper; * @since 1.0 */ @Configuration -public class WebFluxHateoasConfiguration { +class WebFluxHateoasConfiguration { @Bean WebClientConfigurer webClientConfigurer(ObjectProvider mapper, - Collection hypermediaTypes) { - + Collection hypermediaTypes) { return new WebClientConfigurer(mapper.getIfAvailable(ObjectMapper::new), hypermediaTypes); } @@ -52,7 +60,7 @@ public class WebFluxHateoasConfiguration { @Bean HypermediaWebFluxConfigurer hypermediaWebFluxConfigurer(ObjectProvider mapper, - Collection hypermediaTypes) { + Collection hypermediaTypes) { return new HypermediaWebFluxConfigurer(mapper.getIfAvailable(ObjectMapper::new), hypermediaTypes); } @@ -65,4 +73,73 @@ public class WebFluxHateoasConfiguration { HypermediaWebFilter hypermediaWebFilter() { return new HypermediaWebFilter(); } + + /** + * {@link BeanPostProcessor} to register the proper handlers in {@link WebClient} instances found in the application + * context. + * + * @author Greg Turnquist + * @since 1.0 + */ + @RequiredArgsConstructor + static class HypermediaWebClientBeanPostProcessor implements BeanPostProcessor { + + private final WebClientConfigurer configurer; + + /* + * (non-Javadoc) + * @see org.springframework.beans.factory.config.BeanPostProcessor#postProcessBeforeInitialization(java.lang.Object, java.lang.String) + */ + @Override + public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException { + + if (bean instanceof WebClient) { + return this.configurer.registerHypermediaTypes((WebClient) bean); + } + + return bean; + } + } + + /** + * {@link WebFluxConfigurer} to register hypermedia-aware {@link org.springframework.core.codec.Encoder}s and + * {@link org.springframework.core.codec.Decoder}s that will render hypermedia for WebFlux controllers. + * + * @author Greg Turnquist + * @since 1.0 + */ + @RequiredArgsConstructor + static class HypermediaWebFluxConfigurer implements WebFluxConfigurer { + + private final ObjectMapper mapper; + private final Collection hypermediaTypes; + + /** + * Configure custom HTTP message readers and writers or override built-in ones. + *

+ * The configured readers and writers will be used for both annotated controllers and functional endpoints. + * + * @param configurer the configurer to use + */ + @Override + public void configureHttpMessageCodecs(ServerCodecConfigurer configurer) { + + CodecConfigurer.CustomCodecs customCodecs = configurer.customCodecs(); + + this.hypermediaTypes.forEach(hypermedia -> { + + MimeType[] mimeTypes = hypermedia.getMediaTypes().toArray(new MimeType[0]); + + ObjectMapper objectMapper = hypermedia.configureObjectMapper(this.mapper.copy()); + customCodecs.encoder(new Jackson2JsonEncoder(objectMapper, mimeTypes)); + customCodecs.decoder(new Jackson2JsonDecoder(objectMapper, mimeTypes)); + }); + + customCodecs.encoder(CharSequenceEncoder.allMimeTypes()); + customCodecs.decoder(StringDecoder.allMimeTypes()); + + configurer.registerDefaults(false); + } + } + } diff --git a/src/main/java/org/springframework/hateoas/hal/HalConfigurationProvider.java b/src/main/java/org/springframework/hateoas/hal/HalConfigurationProvider.java new file mode 100644 index 00000000..be3ca1ee --- /dev/null +++ b/src/main/java/org/springframework/hateoas/hal/HalConfigurationProvider.java @@ -0,0 +1,49 @@ +/* + * Copyright 2019 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.springframework.hateoas.hal; + +import java.util.Collection; + +import org.springframework.hateoas.MediaTypes; +import org.springframework.hateoas.config.HypermediaMappingInformation; +import org.springframework.hateoas.config.MediaTypeConfigurationProvider; +import org.springframework.http.MediaType; + +/** + * {@link MediaTypeConfigurationProvider} for HAL. + * + * @author Oliver Drotbohm + */ +class HalConfigurationProvider implements MediaTypeConfigurationProvider { + + /* + * (non-Javadoc) + * @see org.springframework.hateoas.config.HyperMediaTypeProvider#getConfiguration() + */ + @Override + public Class getConfiguration() { + return HalMediaTypeConfiguration.class; + } + + /* + * (non-Javadoc) + * @see org.springframework.hateoas.config.HyperMediaTypeProvider#supportsAny(java.util.Collection) + */ + @Override + public boolean supportsAny(Collection mediaTypes) { + return mediaTypes.contains(MediaTypes.HAL_JSON); + } +} diff --git a/src/main/java/org/springframework/hateoas/hal/HalConfigurer.java b/src/main/java/org/springframework/hateoas/hal/HalConfigurer.java deleted file mode 100644 index 567fc5a3..00000000 --- a/src/main/java/org/springframework/hateoas/hal/HalConfigurer.java +++ /dev/null @@ -1,71 +0,0 @@ -/* - * Copyright 2019 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.springframework.hateoas.hal; - -import java.util.List; - -import org.springframework.beans.factory.ObjectProvider; -import org.springframework.context.annotation.Bean; -import org.springframework.context.annotation.Configuration; -import org.springframework.context.support.MessageSourceAccessor; -import org.springframework.hateoas.LinkDiscoverer; -import org.springframework.hateoas.config.EnableHypermediaSupport.HypermediaType; -import org.springframework.hateoas.config.Hypermedia; -import org.springframework.hateoas.core.DelegatingRelProvider; -import org.springframework.http.MediaType; - -import com.fasterxml.jackson.databind.DeserializationFeature; -import com.fasterxml.jackson.databind.ObjectMapper; - -/** - * @author Greg Turnquist - */ -@Configuration -public class HalConfigurer { - - @Bean - Hypermedia halBean(DelegatingRelProvider relProvider, - ObjectProvider curieProvider, - ObjectProvider halConfiguration, - MessageSourceAccessor messageSourceAccessor) { - - return new Hypermedia() { - @Override - public List getMediaTypes() { - return HypermediaType.HAL.getMediaTypes(); - } - - @Override - public ObjectMapper createObjectMapper(ObjectMapper mapper) { - - ObjectMapper mapper1 = mapper.copy(); - - mapper1.disable(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES); - mapper1.registerModule(new Jackson2HalModule()); - mapper1.setHandlerInstantiator( - new Jackson2HalModule.HalHandlerInstantiator(relProvider, curieProvider.getIfAvailable(), messageSourceAccessor, halConfiguration.getIfAvailable(HalConfiguration::new))); - - return mapper1; - } - }; - } - - @Bean - LinkDiscoverer linkDiscoverer() { - return new HalLinkDiscoverer(); - } - -} diff --git a/src/main/java/org/springframework/hateoas/hal/HalMediaTypeConfiguration.java b/src/main/java/org/springframework/hateoas/hal/HalMediaTypeConfiguration.java new file mode 100644 index 00000000..ee36f9f3 --- /dev/null +++ b/src/main/java/org/springframework/hateoas/hal/HalMediaTypeConfiguration.java @@ -0,0 +1,78 @@ +/* + * Copyright 2019 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.springframework.hateoas.hal; + +import lombok.RequiredArgsConstructor; + +import java.util.List; + +import org.springframework.beans.factory.ObjectProvider; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.context.support.MessageSourceAccessor; +import org.springframework.hateoas.LinkDiscoverer; +import org.springframework.hateoas.RelProvider; +import org.springframework.hateoas.config.EnableHypermediaSupport.HypermediaType; +import org.springframework.hateoas.config.HypermediaMappingInformation; +import org.springframework.http.MediaType; + +import com.fasterxml.jackson.databind.DeserializationFeature; +import com.fasterxml.jackson.databind.ObjectMapper; + +/** + * Spring configuration to set up HAL support. + * + * @author Greg Turnquist + * @author Oliver Drotbohm + */ +@Configuration +@RequiredArgsConstructor +public class HalMediaTypeConfiguration implements HypermediaMappingInformation { + + private final RelProvider relProvider; + private final ObjectProvider curieProvider; + private final ObjectProvider halConfiguration; + private final MessageSourceAccessor messageSourceAccessor; + + @Bean + LinkDiscoverer linkDiscoverer() { + return new HalLinkDiscoverer(); + } + + /* + * (non-Javadoc) + * @see org.springframework.hateoas.config.HypermediaMappingInformation#getMediaTypes() + */ + @Override + public List getMediaTypes() { + return HypermediaType.HAL.getMediaTypes(); + } + + /* + * (non-Javadoc) + * @see org.springframework.hateoas.config.HypermediaMappingInformation#configureObjectMapper(com.fasterxml.jackson.databind.ObjectMapper) + */ + @Override + public ObjectMapper configureObjectMapper(ObjectMapper mapper) { + + mapper.disable(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES); + mapper.registerModule(new Jackson2HalModule()); + mapper.setHandlerInstantiator(new Jackson2HalModule.HalHandlerInstantiator(relProvider, + curieProvider.getIfAvailable(), messageSourceAccessor, halConfiguration.getIfAvailable(HalConfiguration::new))); + + return mapper; + } +} diff --git a/src/main/java/org/springframework/hateoas/hal/Jackson2HalModule.java b/src/main/java/org/springframework/hateoas/hal/Jackson2HalModule.java index f022848d..828eb1ee 100644 --- a/src/main/java/org/springframework/hateoas/hal/Jackson2HalModule.java +++ b/src/main/java/org/springframework/hateoas/hal/Jackson2HalModule.java @@ -428,8 +428,8 @@ public class Jackson2HalModule extends SimpleModule { HalLink halLink = HalLink.class.cast(firstElement); - if (list.size() == 1 - && halConfiguration.getSingleLinkRenderModeFor(halLink.getLink().getRel()).equals(RenderSingleLinks.AS_SINGLE)) { + if (list.size() == 1 && halConfiguration.getSingleLinkRenderModeFor(halLink.getLink().getRel()) + .equals(RenderSingleLinks.AS_SINGLE)) { serializeContents(halLink, jgen, provider); diff --git a/src/main/java/org/springframework/hateoas/hal/forms/HalFormsConfiguration.java b/src/main/java/org/springframework/hateoas/hal/forms/HalFormsConfiguration.java index d22b5808..a9952aae 100644 --- a/src/main/java/org/springframework/hateoas/hal/forms/HalFormsConfiguration.java +++ b/src/main/java/org/springframework/hateoas/hal/forms/HalFormsConfiguration.java @@ -29,7 +29,7 @@ import org.springframework.hateoas.hal.HalConfiguration; */ @NoArgsConstructor @AllArgsConstructor(access = AccessLevel.PRIVATE) -public class HalFormsConfiguration { +class HalFormsConfiguration { private @Wither @Getter RenderSingleLinks renderSingleLinks = RenderSingleLinks.AS_SINGLE; @@ -48,7 +48,7 @@ public class HalFormsConfiguration { /** * Translate a {@link HalFormsConfiguration} into a {@link HalConfiguration}. - * + * * @return */ public HalConfiguration toHalConfiguration() { diff --git a/src/main/java/org/springframework/hateoas/hal/forms/HalFormsConfigurationProvider.java b/src/main/java/org/springframework/hateoas/hal/forms/HalFormsConfigurationProvider.java new file mode 100644 index 00000000..1afafacf --- /dev/null +++ b/src/main/java/org/springframework/hateoas/hal/forms/HalFormsConfigurationProvider.java @@ -0,0 +1,49 @@ +/* + * Copyright 2019 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.springframework.hateoas.hal.forms; + +import java.util.Collection; + +import org.springframework.hateoas.MediaTypes; +import org.springframework.hateoas.config.HypermediaMappingInformation; +import org.springframework.hateoas.config.MediaTypeConfigurationProvider; +import org.springframework.http.MediaType; + +/** + * {@link MediaTypeConfigurationProvider} for HAL Forms. + * + * @author Oliver Drotbohm + */ +class HalFormsConfigurationProvider implements MediaTypeConfigurationProvider { + + /* + * (non-Javadoc) + * @see org.springframework.hateoas.config.MediaTypeConfigurationProvider#getConfiguration() + */ + @Override + public Class getConfiguration() { + return HalFormsMediaTypeConfiguration.class; + } + + /* + * (non-Javadoc) + * @see org.springframework.hateoas.config.MediaTypeConfigurationProvider#supportsAny(java.util.Collection) + */ + @Override + public boolean supportsAny(Collection mediaTypes) { + return mediaTypes.contains(MediaTypes.HAL_FORMS_JSON); + } +} diff --git a/src/main/java/org/springframework/hateoas/hal/forms/HalFormsConfigurer.java b/src/main/java/org/springframework/hateoas/hal/forms/HalFormsConfigurer.java deleted file mode 100644 index 5b6fc1b9..00000000 --- a/src/main/java/org/springframework/hateoas/hal/forms/HalFormsConfigurer.java +++ /dev/null @@ -1,71 +0,0 @@ -/* - * Copyright 2019 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.springframework.hateoas.hal.forms; - -import java.util.List; - -import org.springframework.beans.factory.ObjectProvider; -import org.springframework.context.annotation.Bean; -import org.springframework.context.annotation.Configuration; -import org.springframework.context.support.MessageSourceAccessor; -import org.springframework.hateoas.LinkDiscoverer; -import org.springframework.hateoas.config.EnableHypermediaSupport.HypermediaType; -import org.springframework.hateoas.config.Hypermedia; -import org.springframework.hateoas.core.DelegatingRelProvider; -import org.springframework.hateoas.hal.CurieProvider; -import org.springframework.http.MediaType; - -import com.fasterxml.jackson.databind.DeserializationFeature; -import com.fasterxml.jackson.databind.ObjectMapper; - -/** - * @author Greg Turnquist - */ -@Configuration -public class HalFormsConfigurer { - - @Bean - Hypermedia halFormsBean(DelegatingRelProvider relProvider, - ObjectProvider curieProvider, - ObjectProvider halFormsConfiguration, - MessageSourceAccessor messageSourceAccessor) { - - return new Hypermedia() { - @Override - public List getMediaTypes() { - return HypermediaType.HAL_FORMS.getMediaTypes(); - } - - @Override - public ObjectMapper createObjectMapper(ObjectMapper mapper) { - - ObjectMapper mapper1 = mapper.copy(); - - mapper1.disable(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES); - mapper1.registerModule(new Jackson2HalFormsModule()); - mapper1.setHandlerInstantiator(new Jackson2HalFormsModule.HalFormsHandlerInstantiator(relProvider, curieProvider.getIfAvailable(), messageSourceAccessor, - true, halFormsConfiguration.getIfAvailable(HalFormsConfiguration::new))); - - return mapper1; - } - }; - } - - @Bean LinkDiscoverer linkDiscoverer() { - return new HalFormsLinkDiscoverer(); - } - -} diff --git a/src/main/java/org/springframework/hateoas/hal/forms/HalFormsMediaTypeConfiguration.java b/src/main/java/org/springframework/hateoas/hal/forms/HalFormsMediaTypeConfiguration.java new file mode 100644 index 00000000..1f2d7f6d --- /dev/null +++ b/src/main/java/org/springframework/hateoas/hal/forms/HalFormsMediaTypeConfiguration.java @@ -0,0 +1,83 @@ +/* + * Copyright 2019 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.springframework.hateoas.hal.forms; + +import lombok.RequiredArgsConstructor; + +import java.util.List; + +import org.springframework.beans.factory.ObjectProvider; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.context.support.MessageSourceAccessor; +import org.springframework.hateoas.LinkDiscoverer; +import org.springframework.hateoas.config.EnableHypermediaSupport.HypermediaType; +import org.springframework.hateoas.config.HypermediaMappingInformation; +import org.springframework.hateoas.core.DelegatingRelProvider; +import org.springframework.hateoas.hal.CurieProvider; +import org.springframework.http.MediaType; + +import com.fasterxml.jackson.databind.DeserializationFeature; +import com.fasterxml.jackson.databind.ObjectMapper; + +/** + * Spring configuration for HAL Forms support. + * + * @author Greg Turnquist + * @author Oliver Drotbohm + */ +@Configuration +@RequiredArgsConstructor +class HalFormsMediaTypeConfiguration implements HypermediaMappingInformation { + + private final DelegatingRelProvider relProvider; + private final ObjectProvider curieProvider; + private final ObjectProvider halFormsConfiguration; + private final MessageSourceAccessor messageSourceAccessor; + + @Bean + LinkDiscoverer linkDiscoverer() { + return new HalFormsLinkDiscoverer(); + } + + /* + * (non-Javadoc) + * @see org.springframework.hateoas.config.HypermediaMappingInformation#getMediaTypes() + */ + @Override + public List getMediaTypes() { + return HypermediaType.HAL_FORMS.getMediaTypes(); + } + + /* + * (non-Javadoc) + * @see org.springframework.hateoas.config.HypermediaMappingInformation#configureObjectMapper(com.fasterxml.jackson.databind.ObjectMapper) + */ + @Override + public ObjectMapper configureObjectMapper(ObjectMapper mapper) { + + ObjectMapper mapper1 = mapper.copy(); + + mapper1.disable(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES); + mapper1.registerModule(new Jackson2HalFormsModule()); + mapper1.setHandlerInstantiator( + new Jackson2HalFormsModule.HalFormsHandlerInstantiator(relProvider, curieProvider.getIfAvailable(), + messageSourceAccessor, true, halFormsConfiguration.getIfAvailable(HalFormsConfiguration::new))); + + return mapper1; + } + +} diff --git a/src/main/java/org/springframework/hateoas/hal/forms/Jackson2HalFormsModule.java b/src/main/java/org/springframework/hateoas/hal/forms/Jackson2HalFormsModule.java index ae7b811d..fd0513e8 100644 --- a/src/main/java/org/springframework/hateoas/hal/forms/Jackson2HalFormsModule.java +++ b/src/main/java/org/springframework/hateoas/hal/forms/Jackson2HalFormsModule.java @@ -71,7 +71,7 @@ import com.fasterxml.jackson.databind.type.TypeFactory; * @author Greg Turnquist * @author Oliver Gierke */ -public class Jackson2HalFormsModule extends SimpleModule { +class Jackson2HalFormsModule extends SimpleModule { private static final long serialVersionUID = -4496351128468451196L; diff --git a/src/main/java/org/springframework/hateoas/uber/UberAffordanceModelFactory.java b/src/main/java/org/springframework/hateoas/uber/UberAffordanceModelFactory.java index 649af54b..dad58b9b 100644 --- a/src/main/java/org/springframework/hateoas/uber/UberAffordanceModelFactory.java +++ b/src/main/java/org/springframework/hateoas/uber/UberAffordanceModelFactory.java @@ -34,7 +34,7 @@ import org.springframework.http.MediaType; * @author Greg Turnquist * @author Oliver Drotbohm */ -public class UberAffordanceModelFactory implements AffordanceModelFactory { +class UberAffordanceModelFactory implements AffordanceModelFactory { private final @Getter MediaType mediaType = MediaTypes.UBER_JSON; diff --git a/src/main/java/org/springframework/hateoas/uber/UberConfigurer.java b/src/main/java/org/springframework/hateoas/uber/UberMediaTypeConfiguration.java similarity index 61% rename from src/main/java/org/springframework/hateoas/uber/UberConfigurer.java rename to src/main/java/org/springframework/hateoas/uber/UberMediaTypeConfiguration.java index 8e3196ef..c1820981 100644 --- a/src/main/java/org/springframework/hateoas/uber/UberConfigurer.java +++ b/src/main/java/org/springframework/hateoas/uber/UberMediaTypeConfiguration.java @@ -21,43 +21,40 @@ import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.hateoas.LinkDiscoverer; import org.springframework.hateoas.config.EnableHypermediaSupport.HypermediaType; -import org.springframework.hateoas.config.Hypermedia; +import org.springframework.hateoas.config.HypermediaMappingInformation; import org.springframework.http.MediaType; -import com.fasterxml.jackson.databind.DeserializationFeature; -import com.fasterxml.jackson.databind.ObjectMapper; +import com.fasterxml.jackson.databind.Module; /** + * Spring configuration for Uber media type support. + * * @author Greg Turnquist + * @author Oliver Drotbohm */ @Configuration -public class UberConfigurer { - - @Bean - Hypermedia uberBean() { - - return new Hypermedia() { - @Override - public List getMediaTypes() { - return HypermediaType.UBER.getMediaTypes(); - } - - @Override - public ObjectMapper createObjectMapper(ObjectMapper mapper) { - - ObjectMapper mapper1 = mapper.copy(); - - mapper1.disable(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES); - mapper1.registerModule(new Jackson2UberModule()); - - return mapper1; - } - }; - } +class UberMediaTypeConfiguration implements HypermediaMappingInformation { @Bean LinkDiscoverer linkDiscoverer() { return new UberLinkDiscoverer(); } + /* + * (non-Javadoc) + * @see org.springframework.hateoas.config.HypermediaMappingInformation#getMediaTypes() + */ + @Override + public List getMediaTypes() { + return HypermediaType.UBER.getMediaTypes(); + } + + /* + * (non-Javadoc) + * @see org.springframework.hateoas.config.HypermediaMappingInformation#getJacksonModule() + */ + @Override + public Module getJacksonModule() { + return new Jackson2UberModule(); + } } diff --git a/src/main/java/org/springframework/hateoas/uber/UberMediaTypeConfigurationProvider.java b/src/main/java/org/springframework/hateoas/uber/UberMediaTypeConfigurationProvider.java new file mode 100644 index 00000000..3c8e1151 --- /dev/null +++ b/src/main/java/org/springframework/hateoas/uber/UberMediaTypeConfigurationProvider.java @@ -0,0 +1,49 @@ +/* + * Copyright 2019 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.springframework.hateoas.uber; + +import java.util.Collection; + +import org.springframework.hateoas.MediaTypes; +import org.springframework.hateoas.config.HypermediaMappingInformation; +import org.springframework.hateoas.config.MediaTypeConfigurationProvider; +import org.springframework.http.MediaType; + +/** + * {@link MediaTypeConfigurationProvider} for Uber. + * + * @author Oliver Drotbohm + */ +class UberMediaTypeConfigurationProvider implements MediaTypeConfigurationProvider { + + /* + * (non-Javadoc) + * @see org.springframework.hateoas.config.MediaTypeConfigurationProvider#getConfiguration() + */ + @Override + public Class getConfiguration() { + return UberMediaTypeConfiguration.class; + } + + /* + * (non-Javadoc) + * @see org.springframework.hateoas.config.MediaTypeConfigurationProvider#supportsAny(java.util.Collection) + */ + @Override + public boolean supportsAny(Collection mediaTypes) { + return mediaTypes.contains(MediaTypes.UBER_JSON); + } +} diff --git a/src/main/resources/META-INF/spring.factories b/src/main/resources/META-INF/spring.factories index e6bfa01d..57b9750c 100644 --- a/src/main/resources/META-INF/spring.factories +++ b/src/main/resources/META-INF/spring.factories @@ -1 +1,7 @@ org.springframework.hateoas.AffordanceModelFactory=org.springframework.hateoas.hal.forms.HalFormsAffordanceModelFactory,org.springframework.hateoas.collectionjson.CollectionJsonAffordanceModelFactory,org.springframework.hateoas.uber.UberAffordanceModelFactory + +org.springframework.hateoas.config.MediaTypeConfigurationProvider=\ +org.springframework.hateoas.collectionjson.CollectionJsonConfigurationProvider,\ +org.springframework.hateoas.hal.HalConfigurationProvider,\ +org.springframework.hateoas.hal.forms.HalFormsConfigurationProvider,\ +org.springframework.hateoas.uber.UberConfigurationProvider diff --git a/src/test/java/org/springframework/hateoas/collectionjson/CollectionJsonSpecTest.java b/src/test/java/org/springframework/hateoas/collectionjson/CollectionJsonSpecTest.java index dc630f70..5111a5e3 100644 --- a/src/test/java/org/springframework/hateoas/collectionjson/CollectionJsonSpecTest.java +++ b/src/test/java/org/springframework/hateoas/collectionjson/CollectionJsonSpecTest.java @@ -1,5 +1,5 @@ /* - * Copyright 2018 the original author or authors. + * Copyright 2018-2019 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -25,8 +25,6 @@ import java.util.List; import org.junit.Before; import org.junit.Test; -import org.springframework.context.support.MessageSourceAccessor; -import org.springframework.context.support.ReloadableResourceBundleMessageSource; import org.springframework.core.io.ClassPathResource; import org.springframework.hateoas.IanaLinkRelations; import org.springframework.hateoas.Link; @@ -211,7 +209,7 @@ public class CollectionJsonSpecTest { String specBasedJson = MappingUtils.read(new ClassPathResource("spec-part7-adjusted.json", getClass())); Resource resource = mapper.readValue(specBasedJson, - mapper.getTypeFactory().constructParametricType(Resource.class, Employee.class)); + mapper.getTypeFactory().constructParametricType(Resource.class, Employee.class)); assertThat(resource.getContent()).isEqualTo(new Employee("W. Chandry", "developer")); assertThat(resource.getLinks()).isEmpty(); diff --git a/src/test/java/org/springframework/hateoas/collectionjson/CollectionJsonWebMvcIntegrationTest.java b/src/test/java/org/springframework/hateoas/collectionjson/CollectionJsonWebMvcIntegrationTest.java index e7901c21..6faad7a5 100644 --- a/src/test/java/org/springframework/hateoas/collectionjson/CollectionJsonWebMvcIntegrationTest.java +++ b/src/test/java/org/springframework/hateoas/collectionjson/CollectionJsonWebMvcIntegrationTest.java @@ -1,5 +1,5 @@ /* - * Copyright 2017 the original author or authors. + * Copyright 2017-2019 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -17,7 +17,7 @@ package org.springframework.hateoas.collectionjson; import static org.hamcrest.CoreMatchers.*; import static org.hamcrest.collection.IsCollectionWithSize.*; -import static org.springframework.hateoas.mvc.ControllerLinkBuilder.*; +import static org.springframework.hateoas.mvc.WebMvcLinkBuilder.*; import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.*; import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.*; import static org.springframework.test.web.servlet.setup.MockMvcBuilders.*; diff --git a/src/test/java/org/springframework/hateoas/config/EnableHypermediaSupportIntegrationTest.java b/src/test/java/org/springframework/hateoas/config/EnableHypermediaSupportIntegrationTest.java index 6d345d82..7c20ef79 100755 --- a/src/test/java/org/springframework/hateoas/config/EnableHypermediaSupportIntegrationTest.java +++ b/src/test/java/org/springframework/hateoas/config/EnableHypermediaSupportIntegrationTest.java @@ -44,7 +44,6 @@ import org.springframework.hateoas.core.DelegatingEntityLinks; import org.springframework.hateoas.core.DelegatingRelProvider; import org.springframework.hateoas.hal.HalConfiguration; import org.springframework.hateoas.hal.HalLinkDiscoverer; -import org.springframework.hateoas.hal.forms.HalFormsConfiguration; import org.springframework.hateoas.hal.forms.HalFormsLinkDiscoverer; import org.springframework.hateoas.mvc.TypeConstrainedMappingJackson2HttpMessageConverter; import org.springframework.hateoas.uber.UberLinkDiscoverer; @@ -633,12 +632,6 @@ public class EnableHypermediaSupportIntegrationTest { public RestTemplate restTemplate() { return new RestTemplate(); } - - @Bean - public HalFormsConfiguration halFormsConfiguration() { - return new HalFormsConfiguration(); - } - } @Configuration diff --git a/src/test/java/org/springframework/hateoas/config/mvc/CustomHypermediaWebMvcTest.java b/src/test/java/org/springframework/hateoas/config/mvc/CustomHypermediaWebMvcTest.java index 4f75be42..bfaf2c7e 100644 --- a/src/test/java/org/springframework/hateoas/config/mvc/CustomHypermediaWebMvcTest.java +++ b/src/test/java/org/springframework/hateoas/config/mvc/CustomHypermediaWebMvcTest.java @@ -16,11 +16,10 @@ package org.springframework.hateoas.config.mvc; import static org.assertj.core.api.AssertionsForClassTypes.*; -import static org.springframework.hateoas.mvc.ControllerLinkBuilder.*; +import static org.springframework.hateoas.mvc.WebMvcLinkBuilder.*; import static org.springframework.hateoas.support.CustomHypermediaType.*; import static org.springframework.hateoas.support.MappingUtils.*; import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.*; -import static org.springframework.test.web.servlet.result.MockMvcResultHandlers.*; import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.*; import static org.springframework.test.web.servlet.setup.MockMvcBuilders.*; @@ -67,9 +66,11 @@ public class CustomHypermediaWebMvcTest { @Test // #833 public void getUsingCustomMediaType() throws Exception { - String results = this.mockMvc.perform(get("/employees/1").accept(FRODO_MEDIATYPE)) - .andExpect(header().string(HttpHeaders.CONTENT_TYPE, FRODO_MEDIATYPE.toString() + ";charset=UTF-8")) - .andDo(print()).andReturn().getResponse().getContentAsString(); + String results = this.mockMvc.perform(get("/employees/1").accept(FRODO_MEDIATYPE)) // + .andExpect(header().string(HttpHeaders.CONTENT_TYPE, FRODO_MEDIATYPE.toString() + ";charset=UTF-8")) // + .andReturn() // + .getResponse() // + .getContentAsString(); assertThat(results).isEqualTo(read(new ClassPathResource("frodo.json", getClass()))); } diff --git a/src/test/java/org/springframework/hateoas/core/ControllerEntityLinksFactoryBeanUnitTest.java b/src/test/java/org/springframework/hateoas/core/ControllerEntityLinksFactoryBeanUnitTest.java index 2460c1e4..949f9682 100755 --- a/src/test/java/org/springframework/hateoas/core/ControllerEntityLinksFactoryBeanUnitTest.java +++ b/src/test/java/org/springframework/hateoas/core/ControllerEntityLinksFactoryBeanUnitTest.java @@ -1,5 +1,5 @@ /* - * Copyright 2012-2015 the original author or authors. + * Copyright 2012-2019 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -24,12 +24,12 @@ import org.springframework.context.ConfigurableApplicationContext; import org.springframework.context.support.GenericApplicationContext; import org.springframework.hateoas.core.ControllerEntityLinksUnitTest.Person; import org.springframework.hateoas.core.ControllerEntityLinksUnitTest.SampleController; -import org.springframework.hateoas.mvc.ControllerLinkBuilderFactory; +import org.springframework.hateoas.mvc.WebMvcLinkBuilderFactory; import org.springframework.stereotype.Controller; /** * Unit tests for {@link ControllerEntityLinksFactoryBean}. - * + * * @author Oliver Gierke */ public class ControllerEntityLinksFactoryBeanUnitTest { @@ -55,7 +55,7 @@ public class ControllerEntityLinksFactoryBeanUnitTest { ControllerEntityLinksFactoryBean builder = new ControllerEntityLinksFactoryBean(); builder.setAnnotation(Controller.class); - builder.setLinkBuilderFactory(new ControllerLinkBuilderFactory()); + builder.setLinkBuilderFactory(new WebMvcLinkBuilderFactory()); builder.setApplicationContext(context); builder.afterPropertiesSet(); diff --git a/src/test/java/org/springframework/hateoas/core/ControllerEntityLinksUnitTest.java b/src/test/java/org/springframework/hateoas/core/ControllerEntityLinksUnitTest.java index d3a59145..dfb2ce63 100755 --- a/src/test/java/org/springframework/hateoas/core/ControllerEntityLinksUnitTest.java +++ b/src/test/java/org/springframework/hateoas/core/ControllerEntityLinksUnitTest.java @@ -18,8 +18,9 @@ package org.springframework.hateoas.core; import static java.util.Collections.*; import static org.assertj.core.api.Assertions.*; import static org.mockito.ArgumentMatchers.*; +import static org.mockito.ArgumentMatchers.eq; import static org.mockito.Mockito.*; -import static org.springframework.hateoas.mvc.ControllerLinkBuilder.*; +import static org.springframework.hateoas.mvc.WebMvcLinkBuilder.*; import java.util.Arrays; @@ -37,7 +38,7 @@ import org.springframework.web.bind.annotation.RequestMapping; /** * Unit tests for {@link ControllerEntityLinks}. - * + * * @author Oliver Gierke */ @RunWith(MockitoJUnitRunner.class) diff --git a/src/test/java/org/springframework/hateoas/hal/RenderHypermediaForDefaultAcceptHeadersTest.java b/src/test/java/org/springframework/hateoas/hal/RenderHypermediaForDefaultAcceptHeadersTest.java index c2c2d3c1..048d853f 100644 --- a/src/test/java/org/springframework/hateoas/hal/RenderHypermediaForDefaultAcceptHeadersTest.java +++ b/src/test/java/org/springframework/hateoas/hal/RenderHypermediaForDefaultAcceptHeadersTest.java @@ -1,5 +1,5 @@ /* - * Copyright 2018 the original author or authors. + * Copyright 2018-2019 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -15,7 +15,7 @@ */ package org.springframework.hateoas.hal; -import static org.springframework.hateoas.mvc.ControllerLinkBuilder.*; +import static org.springframework.hateoas.mvc.WebMvcLinkBuilder.*; import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.*; import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.*; import static org.springframework.test.web.servlet.setup.MockMvcBuilders.*; diff --git a/src/test/java/org/springframework/hateoas/hal/forms/HalFormsValidationIntegrationTest.java b/src/test/java/org/springframework/hateoas/hal/forms/HalFormsValidationIntegrationTest.java index fc0665a2..de4dff1f 100644 --- a/src/test/java/org/springframework/hateoas/hal/forms/HalFormsValidationIntegrationTest.java +++ b/src/test/java/org/springframework/hateoas/hal/forms/HalFormsValidationIntegrationTest.java @@ -17,7 +17,7 @@ package org.springframework.hateoas.hal.forms; import static org.hamcrest.CoreMatchers.*; import static org.junit.Assert.*; -import static org.springframework.hateoas.mvc.ControllerLinkBuilder.*; +import static org.springframework.hateoas.mvc.WebMvcLinkBuilder.*; import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.*; import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.*; import static org.springframework.test.web.servlet.setup.MockMvcBuilders.*; diff --git a/src/test/java/org/springframework/hateoas/hal/forms/HalFormsWebMvcIntegrationTest.java b/src/test/java/org/springframework/hateoas/hal/forms/HalFormsWebMvcIntegrationTest.java index 01db57fa..ec96d251 100644 --- a/src/test/java/org/springframework/hateoas/hal/forms/HalFormsWebMvcIntegrationTest.java +++ b/src/test/java/org/springframework/hateoas/hal/forms/HalFormsWebMvcIntegrationTest.java @@ -1,5 +1,5 @@ /* - * Copyright 2017 the original author or authors. + * Copyright 2017-2019 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -28,8 +28,6 @@ import org.springframework.beans.factory.annotation.Autowired; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.core.io.ClassPathResource; -import org.springframework.hateoas.IanaLinkRelations; -import org.springframework.hateoas.Link; import org.springframework.hateoas.MediaTypes; import org.springframework.hateoas.config.EnableHypermediaSupport; import org.springframework.hateoas.config.EnableHypermediaSupport.HypermediaType; diff --git a/src/test/java/org/springframework/hateoas/mvc/WebMvcLinkBuilderFactoryUnitTest.java b/src/test/java/org/springframework/hateoas/mvc/WebMvcLinkBuilderFactoryUnitTest.java index 6a318361..5126e64e 100644 --- a/src/test/java/org/springframework/hateoas/mvc/WebMvcLinkBuilderFactoryUnitTest.java +++ b/src/test/java/org/springframework/hateoas/mvc/WebMvcLinkBuilderFactoryUnitTest.java @@ -32,9 +32,9 @@ import org.springframework.format.annotation.DateTimeFormat.ISO; import org.springframework.hateoas.IanaLinkRelations; import org.springframework.hateoas.Link; import org.springframework.hateoas.TestUtils; -import org.springframework.hateoas.mvc.ControllerLinkBuilderUnitTest.ControllerWithMethods; -import org.springframework.hateoas.mvc.ControllerLinkBuilderUnitTest.PersonControllerImpl; -import org.springframework.hateoas.mvc.ControllerLinkBuilderUnitTest.PersonsAddressesController; +import org.springframework.hateoas.mvc.WebMvcLinkBuilderUnitTest.ControllerWithMethods; +import org.springframework.hateoas.mvc.WebMvcLinkBuilderUnitTest.PersonControllerImpl; +import org.springframework.hateoas.mvc.WebMvcLinkBuilderUnitTest.PersonsAddressesController; import org.springframework.http.HttpEntity; import org.springframework.util.LinkedMultiValueMap; import org.springframework.util.MultiValueMap; diff --git a/src/test/java/org/springframework/hateoas/support/CustomHypermediaType.java b/src/test/java/org/springframework/hateoas/support/CustomHypermediaType.java index 9b95ab5e..5bba1bbd 100644 --- a/src/test/java/org/springframework/hateoas/support/CustomHypermediaType.java +++ b/src/test/java/org/springframework/hateoas/support/CustomHypermediaType.java @@ -18,7 +18,7 @@ package org.springframework.hateoas.support; import java.util.Collections; import java.util.List; -import org.springframework.hateoas.config.Hypermedia; +import org.springframework.hateoas.config.HypermediaMappingInformation; import org.springframework.http.MediaType; import com.fasterxml.jackson.databind.DeserializationFeature; @@ -28,7 +28,7 @@ import com.fasterxml.jackson.databind.SerializationFeature; /** * @author Greg Turnquist */ -public class CustomHypermediaType implements Hypermedia { +public class CustomHypermediaType implements HypermediaMappingInformation { public static final MediaType FRODO_MEDIATYPE = MediaType.parseMediaType("application/frodo+json"); @@ -41,16 +41,15 @@ public class CustomHypermediaType implements Hypermedia { } /** - * Copy the incoming {@link ObjectMapper} and change it's output format along with disabling failure on - * unknown properties. + * Copy the incoming {@link ObjectMapper} and change it's output format along with disabling failure on unknown + * properties. */ @Override - public ObjectMapper createObjectMapper(ObjectMapper mapper) { + public ObjectMapper configureObjectMapper(ObjectMapper mapper) { - ObjectMapper objectMapper = mapper.copy(); - objectMapper.disable(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES); - objectMapper.enable(SerializationFeature.INDENT_OUTPUT); + mapper.disable(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES); + mapper.enable(SerializationFeature.INDENT_OUTPUT); - return objectMapper; + return mapper; } } diff --git a/src/test/java/org/springframework/hateoas/uber/UberWebMvcIntegrationTest.java b/src/test/java/org/springframework/hateoas/uber/UberWebMvcIntegrationTest.java index b555bb00..0db0cfd7 100644 --- a/src/test/java/org/springframework/hateoas/uber/UberWebMvcIntegrationTest.java +++ b/src/test/java/org/springframework/hateoas/uber/UberWebMvcIntegrationTest.java @@ -22,9 +22,6 @@ import static org.springframework.test.web.servlet.request.MockMvcRequestBuilder import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.*; import static org.springframework.test.web.servlet.setup.MockMvcBuilders.*; -import java.util.Map; -import java.util.TreeMap; - import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; @@ -32,12 +29,9 @@ import org.springframework.beans.factory.annotation.Autowired; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.core.io.ClassPathResource; -import org.springframework.hateoas.IanaLinkRelations; -import org.springframework.hateoas.Link; import org.springframework.hateoas.MediaTypes; import org.springframework.hateoas.config.EnableHypermediaSupport; import org.springframework.hateoas.config.EnableHypermediaSupport.HypermediaType; -import org.springframework.hateoas.support.Employee; import org.springframework.hateoas.support.WebMvcEmployeeController; import org.springframework.http.HttpHeaders; import org.springframework.test.context.ContextConfiguration;