Browse Source

Message converters are configurable

pull/1111/head
Rossen Stoyanchev 9 years ago
parent
commit
a163938758
  1. 50
      spring-web-reactive/src/main/java/org/springframework/web/reactive/result/method/annotation/RequestMappingHandlerAdapter.java
  2. 1
      spring-web-reactive/src/main/java/org/springframework/web/reactive/result/method/annotation/SessionAttributeMethodArgumentResolver.java
  3. 1
      spring-web-reactive/src/main/java/org/springframework/web/reactive/result/view/freemarker/FreeMarkerView.java
  4. 9
      spring-web-reactive/src/test/java/org/springframework/web/reactive/DispatcherHandlerErrorTests.java
  5. 21
      spring-web-reactive/src/test/java/org/springframework/web/reactive/result/method/annotation/RequestMappingIntegrationTests.java

50
spring-web-reactive/src/main/java/org/springframework/web/reactive/result/method/annotation/RequestMappingHandlerAdapter.java

@ -17,9 +17,7 @@
package org.springframework.web.reactive.result.method.annotation; package org.springframework.web.reactive.result.method.annotation;
import java.lang.reflect.Method; import java.lang.reflect.Method;
import java.nio.ByteBuffer;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Arrays;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ConcurrentHashMap;
@ -34,16 +32,9 @@ import org.springframework.beans.factory.BeanFactoryAware;
import org.springframework.beans.factory.InitializingBean; import org.springframework.beans.factory.InitializingBean;
import org.springframework.beans.factory.config.ConfigurableBeanFactory; import org.springframework.beans.factory.config.ConfigurableBeanFactory;
import org.springframework.core.codec.support.ByteBufferDecoder; import org.springframework.core.codec.support.ByteBufferDecoder;
import org.springframework.core.codec.support.ByteBufferEncoder;
import org.springframework.core.codec.support.JacksonJsonDecoder;
import org.springframework.core.codec.support.JacksonJsonEncoder;
import org.springframework.core.codec.support.Jaxb2Decoder;
import org.springframework.core.codec.support.Jaxb2Encoder;
import org.springframework.core.codec.support.JsonObjectDecoder;
import org.springframework.core.codec.support.StringDecoder; import org.springframework.core.codec.support.StringDecoder;
import org.springframework.core.codec.support.StringEncoder;
import org.springframework.core.convert.ConversionService; import org.springframework.core.convert.ConversionService;
import org.springframework.core.convert.support.DefaultConversionService; import org.springframework.format.support.DefaultFormattingConversionService;
import org.springframework.http.converter.reactive.CodecHttpMessageConverter; import org.springframework.http.converter.reactive.CodecHttpMessageConverter;
import org.springframework.http.converter.reactive.HttpMessageConverter; import org.springframework.http.converter.reactive.HttpMessageConverter;
import org.springframework.ui.ExtendedModelMap; import org.springframework.ui.ExtendedModelMap;
@ -68,13 +59,20 @@ public class RequestMappingHandlerAdapter implements HandlerAdapter, BeanFactory
private final List<HandlerMethodArgumentResolver> argumentResolvers = new ArrayList<>(); private final List<HandlerMethodArgumentResolver> argumentResolvers = new ArrayList<>();
private ConversionService conversionService = new DefaultConversionService(); private final List<HttpMessageConverter<?>> messageConverters = new ArrayList<>();
private final Map<Class<?>, ExceptionHandlerMethodResolver> exceptionHandlerCache = private ConversionService conversionService = new DefaultFormattingConversionService();
new ConcurrentHashMap<>(64);
private ConfigurableBeanFactory beanFactory; private ConfigurableBeanFactory beanFactory;
private final Map<Class<?>, ExceptionHandlerMethodResolver> exceptionHandlerCache = new ConcurrentHashMap<>(64);
public RequestMappingHandlerAdapter() {
this.messageConverters.add(new CodecHttpMessageConverter<>(new ByteBufferDecoder()));
this.messageConverters.add(new CodecHttpMessageConverter<>(new StringDecoder()));
}
/** /**
@ -93,6 +91,18 @@ public class RequestMappingHandlerAdapter implements HandlerAdapter, BeanFactory
return this.argumentResolvers; return this.argumentResolvers;
} }
public void setMessageConverters(List<HttpMessageConverter<?>> messageConverters) {
this.messageConverters.clear();
this.messageConverters.addAll(messageConverters);
}
/**
* Provide the message converters to use for argument resolution.
*/
public List<HttpMessageConverter<?>> getMessageConverters() {
return this.messageConverters;
}
public void setConversionService(ConversionService conversionService) { public void setConversionService(ConversionService conversionService) {
this.conversionService = conversionService; this.conversionService = conversionService;
} }
@ -121,12 +131,12 @@ public class RequestMappingHandlerAdapter implements HandlerAdapter, BeanFactory
public void afterPropertiesSet() throws Exception { public void afterPropertiesSet() throws Exception {
if (ObjectUtils.isEmpty(this.argumentResolvers)) { if (ObjectUtils.isEmpty(this.argumentResolvers)) {
List<HttpMessageConverter<?>> converters = Arrays.asList( // List<HttpMessageConverter<?>> converters = Arrays.asList(
new CodecHttpMessageConverter<ByteBuffer>(new ByteBufferEncoder(), new ByteBufferDecoder()), // new CodecHttpMessageConverter<ByteBuffer>(new ByteBufferEncoder(), new ByteBufferDecoder()),
new CodecHttpMessageConverter<String>(new StringEncoder(), new StringDecoder()), // new CodecHttpMessageConverter<String>(new StringEncoder(), new StringDecoder()),
new CodecHttpMessageConverter<Object>(new Jaxb2Encoder(), new Jaxb2Decoder()), // new CodecHttpMessageConverter<Object>(new Jaxb2Encoder(), new Jaxb2Decoder()),
new CodecHttpMessageConverter<Object>(new JacksonJsonEncoder(), // new CodecHttpMessageConverter<Object>(new JacksonJsonEncoder(),
new JacksonJsonDecoder(new JsonObjectDecoder()))); // new JacksonJsonDecoder(new JsonObjectDecoder())));
// Annotation-based argument resolution // Annotation-based argument resolution
ConversionService cs = getConversionService(); ConversionService cs = getConversionService();
@ -134,7 +144,7 @@ public class RequestMappingHandlerAdapter implements HandlerAdapter, BeanFactory
this.argumentResolvers.add(new RequestParamMapMethodArgumentResolver()); this.argumentResolvers.add(new RequestParamMapMethodArgumentResolver());
this.argumentResolvers.add(new PathVariableMethodArgumentResolver(cs, getBeanFactory())); this.argumentResolvers.add(new PathVariableMethodArgumentResolver(cs, getBeanFactory()));
this.argumentResolvers.add(new PathVariableMapMethodArgumentResolver()); this.argumentResolvers.add(new PathVariableMapMethodArgumentResolver());
this.argumentResolvers.add(new RequestBodyArgumentResolver(converters, cs)); this.argumentResolvers.add(new RequestBodyArgumentResolver(getMessageConverters(), cs));
this.argumentResolvers.add(new RequestHeaderMethodArgumentResolver(cs, getBeanFactory())); this.argumentResolvers.add(new RequestHeaderMethodArgumentResolver(cs, getBeanFactory()));
this.argumentResolvers.add(new RequestHeaderMapMethodArgumentResolver()); this.argumentResolvers.add(new RequestHeaderMapMethodArgumentResolver());
this.argumentResolvers.add(new CookieValueMethodArgumentResolver(cs, getBeanFactory())); this.argumentResolvers.add(new CookieValueMethodArgumentResolver(cs, getBeanFactory()));

1
spring-web-reactive/src/main/java/org/springframework/web/reactive/result/method/annotation/SessionAttributeMethodArgumentResolver.java

@ -48,7 +48,6 @@ public class SessionAttributeMethodArgumentResolver extends AbstractNamedValueMe
return parameter.hasParameterAnnotation(SessionAttribute.class); return parameter.hasParameterAnnotation(SessionAttribute.class);
} }
@Override @Override
protected NamedValueInfo createNamedValueInfo(MethodParameter parameter) { protected NamedValueInfo createNamedValueInfo(MethodParameter parameter) {
SessionAttribute annot = parameter.getParameterAnnotation(SessionAttribute.class); SessionAttribute annot = parameter.getParameterAnnotation(SessionAttribute.class);

1
spring-web-reactive/src/main/java/org/springframework/web/reactive/result/view/freemarker/FreeMarkerView.java

@ -166,6 +166,7 @@ public class FreeMarkerView extends AbstractUrlBasedView {
Locale locale = Locale.getDefault(); // TODO Locale locale = Locale.getDefault(); // TODO
DataBuffer dataBuffer = exchange.getResponse().bufferFactory().allocateBuffer(); DataBuffer dataBuffer = exchange.getResponse().bufferFactory().allocateBuffer();
try { try {
// TODO: pass charset
Writer writer = new OutputStreamWriter(dataBuffer.asOutputStream()); Writer writer = new OutputStreamWriter(dataBuffer.asOutputStream());
getTemplate(locale).process(freeMarkerModel, writer); getTemplate(locale).process(freeMarkerModel, writer);
} }

9
spring-web-reactive/src/test/java/org/springframework/web/reactive/DispatcherHandlerErrorTests.java

@ -32,6 +32,7 @@ import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.Configuration;
import org.springframework.core.codec.support.StringDecoder; import org.springframework.core.codec.support.StringDecoder;
import org.springframework.core.codec.support.StringEncoder; import org.springframework.core.codec.support.StringEncoder;
import org.springframework.core.convert.ConversionService;
import org.springframework.core.convert.support.DefaultConversionService; import org.springframework.core.convert.support.DefaultConversionService;
import org.springframework.core.io.buffer.DataBuffer; import org.springframework.core.io.buffer.DataBuffer;
import org.springframework.core.io.buffer.DefaultDataBufferFactory; import org.springframework.core.io.buffer.DefaultDataBufferFactory;
@ -230,11 +231,9 @@ public class DispatcherHandlerErrorTests {
@Bean @Bean
public ResponseBodyResultHandler resultHandler() { public ResponseBodyResultHandler resultHandler() {
List<HttpMessageConverter<?>> converters = Collections.singletonList( HttpMessageConverter<String> converter = new CodecHttpMessageConverter<>(new StringEncoder());
new CodecHttpMessageConverter<>(new StringEncoder(), ConversionService conversionService = new DefaultConversionService();
new StringDecoder())); return new ResponseBodyResultHandler(Collections.singletonList(converter), conversionService);
return new ResponseBodyResultHandler(converters,
new DefaultConversionService());
} }
@Bean @Bean

21
spring-web-reactive/src/test/java/org/springframework/web/reactive/result/method/annotation/RequestMappingIntegrationTests.java

@ -44,6 +44,9 @@ import org.springframework.core.codec.support.ByteBufferDecoder;
import org.springframework.core.codec.support.ByteBufferEncoder; import org.springframework.core.codec.support.ByteBufferEncoder;
import org.springframework.core.codec.support.JacksonJsonDecoder; import org.springframework.core.codec.support.JacksonJsonDecoder;
import org.springframework.core.codec.support.JacksonJsonEncoder; import org.springframework.core.codec.support.JacksonJsonEncoder;
import org.springframework.core.codec.support.Jaxb2Decoder;
import org.springframework.core.codec.support.Jaxb2Encoder;
import org.springframework.core.codec.support.JsonObjectDecoder;
import org.springframework.core.codec.support.StringDecoder; import org.springframework.core.codec.support.StringDecoder;
import org.springframework.core.codec.support.StringEncoder; import org.springframework.core.codec.support.StringEncoder;
import org.springframework.core.convert.ConversionService; import org.springframework.core.convert.ConversionService;
@ -392,10 +395,20 @@ public class RequestMappingIntegrationTests extends AbstractHttpHandlerIntegrati
@Bean @Bean
public RequestMappingHandlerAdapter handlerAdapter() { public RequestMappingHandlerAdapter handlerAdapter() {
RequestMappingHandlerAdapter handlerAdapter = new RequestMappingHandlerAdapter(); RequestMappingHandlerAdapter handlerAdapter = new RequestMappingHandlerAdapter();
handlerAdapter.setMessageConverters(getDefaultMessageConverters());
handlerAdapter.setConversionService(conversionService()); handlerAdapter.setConversionService(conversionService());
return handlerAdapter; return handlerAdapter;
} }
private List<HttpMessageConverter<?>> getDefaultMessageConverters() {
return Arrays.asList(
new CodecHttpMessageConverter<>(new ByteBufferEncoder(), new ByteBufferDecoder()),
new CodecHttpMessageConverter<>(new StringEncoder(), new StringDecoder()),
new CodecHttpMessageConverter<>(new Jaxb2Encoder(), new Jaxb2Decoder()),
new CodecHttpMessageConverter<>(new JacksonJsonEncoder(),
new JacksonJsonDecoder(new JsonObjectDecoder())));
}
@Bean @Bean
public ConversionService conversionService() { public ConversionService conversionService() {
// TODO: test failures with DefaultConversionService // TODO: test failures with DefaultConversionService
@ -407,11 +420,9 @@ public class RequestMappingIntegrationTests extends AbstractHttpHandlerIntegrati
@Bean @Bean
public ResponseBodyResultHandler responseBodyResultHandler() { public ResponseBodyResultHandler responseBodyResultHandler() {
List<HttpMessageConverter<?>> converters = Arrays.asList( List<HttpMessageConverter<?>> converters = new ArrayList<>();
new ResourceHttpMessageConverter(), converters.add(new ResourceHttpMessageConverter());
new CodecHttpMessageConverter<>(new ByteBufferEncoder(), new ByteBufferDecoder()), converters.addAll(getDefaultMessageConverters());
new CodecHttpMessageConverter<>(new StringEncoder(), new StringDecoder()),
new CodecHttpMessageConverter<>(new JacksonJsonEncoder(), new JacksonJsonDecoder()));
return new ResponseBodyResultHandler(converters, conversionService()); return new ResponseBodyResultHandler(converters, conversionService());
} }

Loading…
Cancel
Save