Simplify code that makes hal the default json media type

See gh-25546
pull/25571/head
Andy Wilkinson 4 years ago
parent 5c34db96bd
commit 5863edfdda

@ -1,5 +1,5 @@
/*
* Copyright 2012-2020 the original author or authors.
* Copyright 2012-2021 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.
@ -22,18 +22,21 @@ import org.springframework.boot.autoconfigure.AutoConfigureAfter;
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.boot.autoconfigure.condition.ConditionalOnWebApplication;
import org.springframework.boot.autoconfigure.data.rest.RepositoryRestMvcAutoConfiguration;
import org.springframework.boot.autoconfigure.http.HttpMessageConvertersAutoConfiguration;
import org.springframework.boot.autoconfigure.jackson.JacksonAutoConfiguration;
import org.springframework.boot.autoconfigure.web.servlet.WebMvcAutoConfiguration;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Import;
import org.springframework.hateoas.EntityModel;
import org.springframework.hateoas.client.LinkDiscoverers;
import org.springframework.hateoas.config.EnableHypermediaSupport;
import org.springframework.hateoas.config.EnableHypermediaSupport.HypermediaType;
import org.springframework.hateoas.mediatype.hal.HalConfiguration;
import org.springframework.http.MediaType;
import org.springframework.plugin.core.Plugin;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter;
@ -53,9 +56,17 @@ import org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandl
@AutoConfigureAfter({ WebMvcAutoConfiguration.class, JacksonAutoConfiguration.class,
HttpMessageConvertersAutoConfiguration.class, RepositoryRestMvcAutoConfiguration.class })
@EnableConfigurationProperties(HateoasProperties.class)
@Import(HypermediaHttpMessageConverterConfiguration.class)
public class HypermediaAutoConfiguration {
@Bean
@ConditionalOnMissingBean
@ConditionalOnClass(name = "com.fasterxml.jackson.databind.ObjectMapper")
@ConditionalOnProperty(prefix = "spring.hateoas", name = "use-hal-as-default-json-media-type",
matchIfMissing = true)
HalConfiguration applicationJsonHalConfiguration() {
return new HalConfiguration().withMediaType(MediaType.APPLICATION_JSON);
}
@Configuration(proxyBeanMethods = false)
@ConditionalOnMissingBean(LinkDiscoverers.class)
@ConditionalOnClass(ObjectMapper.class)

@ -1,5 +1,5 @@
/*
* Copyright 2012-2020 the original author or authors.
* Copyright 2012-2021 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.
@ -29,6 +29,7 @@ import org.springframework.beans.factory.config.BeanPostProcessor;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.hateoas.mediatype.hal.HalConfiguration;
import org.springframework.hateoas.server.mvc.TypeConstrainedMappingJackson2HttpMessageConverter;
import org.springframework.http.MediaType;
import org.springframework.http.converter.AbstractHttpMessageConverter;
@ -41,7 +42,9 @@ import org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandl
*
* @author Andy Wilkinson
* @since 1.3.0
* @deprecated since 2.5.0 in favor of a {@link HalConfiguration} bean
*/
@Deprecated
@Configuration(proxyBeanMethods = false)
public class HypermediaHttpMessageConverterConfiguration {

@ -1,5 +1,5 @@
/*
* Copyright 2012-2020 the original author or authors.
* Copyright 2012-2021 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.
@ -29,15 +29,16 @@ import org.springframework.boot.test.context.FilteredClassLoader;
import org.springframework.boot.test.context.runner.WebApplicationContextRunner;
import org.springframework.context.annotation.Configuration;
import org.springframework.hateoas.MediaTypes;
import org.springframework.hateoas.RepresentationModel;
import org.springframework.hateoas.client.LinkDiscoverer;
import org.springframework.hateoas.client.LinkDiscoverers;
import org.springframework.hateoas.config.EnableHypermediaSupport;
import org.springframework.hateoas.config.EnableHypermediaSupport.HypermediaType;
import org.springframework.hateoas.mediatype.hal.HalLinkDiscoverer;
import org.springframework.hateoas.server.EntityLinks;
import org.springframework.hateoas.server.mvc.TypeConstrainedMappingJackson2HttpMessageConverter;
import org.springframework.http.MediaType;
import org.springframework.http.converter.HttpMessageConverter;
import org.springframework.http.converter.json.MappingJackson2HttpMessageConverter;
import org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter;
import static org.assertj.core.api.Assertions.assertThat;
@ -87,28 +88,28 @@ class HypermediaAutoConfigurationTests {
}
@Test
void supportedMediaTypesOfTypeConstrainedConvertersIsCustomized() {
void whenUsingTheDefaultConfigurationThenMappingJacksonConverterCanWriteHateoasTypeAsApplicationJson() {
this.contextRunner.run((context) -> {
RequestMappingHandlerAdapter handlerAdapter = context.getBean(RequestMappingHandlerAdapter.class);
for (HttpMessageConverter<?> converter : handlerAdapter.getMessageConverters()) {
if (converter instanceof TypeConstrainedMappingJackson2HttpMessageConverter) {
assertThat(converter.getSupportedMediaTypes()).contains(MediaType.APPLICATION_JSON,
MediaTypes.HAL_JSON);
}
}
Optional<HttpMessageConverter<?>> mappingJacksonConverter = handlerAdapter.getMessageConverters().stream()
.filter(MappingJackson2HttpMessageConverter.class::isInstance).findFirst();
assertThat(mappingJacksonConverter).isPresent().hasValueSatisfying(
(converter) -> assertThat(converter.canWrite(RepresentationModel.class, MediaType.APPLICATION_JSON))
.isTrue());
});
}
@Test
void customizationOfSupportedMediaTypesCanBeDisabled() {
void whenHalIsNotTheDefaultJsonMediaTypeThenMappingJacksonConverterCannotWriteHateoasTypeAsApplicationJson() {
this.contextRunner.withPropertyValues("spring.hateoas.use-hal-as-default-json-media-type:false")
.run((context) -> {
RequestMappingHandlerAdapter handlerAdapter = context.getBean(RequestMappingHandlerAdapter.class);
for (HttpMessageConverter<?> converter : handlerAdapter.getMessageConverters()) {
if (converter instanceof TypeConstrainedMappingJackson2HttpMessageConverter) {
assertThat(converter.getSupportedMediaTypes()).containsExactly(MediaTypes.HAL_JSON);
}
}
Optional<HttpMessageConverter<?>> mappingJacksonConverter = handlerAdapter.getMessageConverters()
.stream().filter(MappingJackson2HttpMessageConverter.class::isInstance).findFirst();
assertThat(mappingJacksonConverter).isPresent()
.hasValueSatisfying((converter) -> assertThat(
converter.canWrite(RepresentationModel.class, MediaType.APPLICATION_JSON))
.isFalse());
});
}

@ -1,5 +1,5 @@
/*
* Copyright 2012-2019 the original author or authors.
* Copyright 2012-2021 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.
@ -16,6 +16,8 @@
package smoketest.hateoas;
import java.util.Arrays;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
@ -38,8 +40,21 @@ class SampleHateoasApplicationTests {
private TestRestTemplate restTemplate;
@Test
void hasHalLinks() {
ResponseEntity<String> entity = this.restTemplate.getForEntity("/customers/1", String.class);
void hasHalLinksWhenAnythingIsAcceptable() {
HttpHeaders headers = new HttpHeaders();
ResponseEntity<String> entity = this.restTemplate.exchange("/customers/1", HttpMethod.GET,
new HttpEntity<>(headers), String.class);
assertThat(entity.getStatusCode()).isEqualTo(HttpStatus.OK);
assertThat(entity.getBody()).startsWith("{\"id\":1,\"firstName\":\"Oliver\",\"lastName\":\"Gierke\"");
assertThat(entity.getBody()).contains("_links\":{\"self\":{\"href\"");
}
@Test
void hasHalLinksWhenJsonIsAcceptable() {
HttpHeaders headers = new HttpHeaders();
headers.setAccept(Arrays.asList(MediaType.APPLICATION_JSON));
ResponseEntity<String> entity = this.restTemplate.exchange("/customers/1", HttpMethod.GET,
new HttpEntity<>(headers), String.class);
assertThat(entity.getStatusCode()).isEqualTo(HttpStatus.OK);
assertThat(entity.getBody()).startsWith("{\"id\":1,\"firstName\":\"Oliver\",\"lastName\":\"Gierke\"");
assertThat(entity.getBody()).contains("_links\":{\"self\":{\"href\"");

Loading…
Cancel
Save