INT-3142 Allow Merging of HTTP Message Converters
INT-3142: A flag to retain default converters when the user has customized messageconverters for HttpRequestHandlingController, HttpInboundGateway * Introduced a new flag in the base class of HttpRequHttpRequestHandlingController, HttpInboundGateway - registerDefaultConverters * Introduced a new attribute "register-default-converters" for inbound-channel-adapter and inbound-gateway to indicate if the default HttpMessageConverter's need to be registered * Http namespace parser related changes to set the new flag * Added additional tests to test the flag and the namespace parser related changes Changes per feedback from Artem - additional javadoc comments, cleaned up tests Updated: Setting the register-default-converters by default to false now, for backward compatibility reasons Changed adapter name per feedback from Artem Changed adapter name per feedback from Artem Changed attribute name from register-default-converters to merge-with-default-converters INT-3142: Atomic operation for messageConverters 'What's New' polishing Polishing Fix a few comments, error messages, docs, whitespace.
This commit is contained in:
committed by
Gary Russell
parent
a9ec7c8107
commit
bb6aebc587
@@ -47,6 +47,7 @@ import org.w3c.dom.Element;
|
||||
* @author Mark Fisher
|
||||
* @author Oleg Zhurakousky
|
||||
* @author Gary Russell
|
||||
* @author Biju Kunjummen
|
||||
*/
|
||||
public class HttpInboundEndpointParser extends AbstractSingleBeanDefinitionParser {
|
||||
|
||||
@@ -159,6 +160,7 @@ public class HttpInboundEndpointParser extends AbstractSingleBeanDefinitionParse
|
||||
IntegrationNamespaceUtils.setValueIfAttributeDefined(builder, element, "errors-key");
|
||||
IntegrationNamespaceUtils.setValueIfAttributeDefined(builder, element, "error-code");
|
||||
IntegrationNamespaceUtils.setReferenceIfAttributeDefined(builder, element, "message-converters");
|
||||
IntegrationNamespaceUtils.setValueIfAttributeDefined(builder, element, "merge-with-default-converters");
|
||||
|
||||
|
||||
//IntegrationNamespaceUtils.setReferenceIfAttributeDefined(builder, element, "header-mapper");
|
||||
|
||||
@@ -41,6 +41,7 @@ import org.springframework.http.converter.ResourceHttpMessageConverter;
|
||||
import org.springframework.http.converter.StringHttpMessageConverter;
|
||||
import org.springframework.http.converter.feed.AtomFeedHttpMessageConverter;
|
||||
import org.springframework.http.converter.feed.RssChannelHttpMessageConverter;
|
||||
import org.springframework.http.converter.json.MappingJackson2HttpMessageConverter;
|
||||
import org.springframework.http.converter.json.MappingJacksonHttpMessageConverter;
|
||||
import org.springframework.http.converter.xml.Jaxb2RootElementHttpMessageConverter;
|
||||
import org.springframework.http.converter.xml.SourceHttpMessageConverter;
|
||||
@@ -57,6 +58,7 @@ import org.springframework.integration.http.multipart.MultipartHttpInputMessage;
|
||||
import org.springframework.integration.http.support.DefaultHttpHeaderMapper;
|
||||
import org.springframework.integration.mapping.HeaderMapper;
|
||||
import org.springframework.integration.support.MessageBuilder;
|
||||
import org.springframework.integration.support.json.JacksonJsonUtils;
|
||||
import org.springframework.util.AntPathMatcher;
|
||||
import org.springframework.util.Assert;
|
||||
import org.springframework.util.ClassUtils;
|
||||
@@ -95,6 +97,7 @@ import org.springframework.web.util.UrlPathHelper;
|
||||
* @author Oleg Zhurakousky
|
||||
* @author Gary Russell
|
||||
* @author Artem Bilan
|
||||
* @author Biju Kunjummen
|
||||
* @since 2.0
|
||||
*/
|
||||
public abstract class HttpRequestHandlingEndpointSupport extends MessagingGatewaySupport
|
||||
@@ -103,19 +106,21 @@ public abstract class HttpRequestHandlingEndpointSupport extends MessagingGatewa
|
||||
private static final boolean jaxb2Present = ClassUtils.isPresent("javax.xml.bind.Binder",
|
||||
HttpRequestHandlingEndpointSupport.class.getClassLoader());
|
||||
|
||||
private static final boolean jacksonPresent = ClassUtils.isPresent("org.codehaus.jackson.map.ObjectMapper",
|
||||
HttpRequestHandlingEndpointSupport.class.getClassLoader())
|
||||
&& ClassUtils.isPresent("org.codehaus.jackson.JsonGenerator", HttpRequestHandlingEndpointSupport.class
|
||||
.getClassLoader());
|
||||
|
||||
private static boolean romePresent = ClassUtils.isPresent("com.sun.syndication.feed.WireFeed",
|
||||
HttpRequestHandlingEndpointSupport.class.getClassLoader());
|
||||
|
||||
private final List<HttpMessageConverter<?>> defaultMessageConverters = new ArrayList<HttpMessageConverter<?>>();
|
||||
|
||||
private volatile List<HttpMessageConverter<?>> messageConverters = new ArrayList<HttpMessageConverter<?>>();
|
||||
|
||||
private volatile List<HttpMethod> supportedMethods = Arrays.asList(HttpMethod.GET, HttpMethod.POST);
|
||||
|
||||
private volatile Class<?> requestPayloadType = null;
|
||||
|
||||
private volatile List<HttpMessageConverter<?>> messageConverters = new ArrayList<HttpMessageConverter<?>>();
|
||||
private volatile boolean convertersMerged;
|
||||
|
||||
private volatile boolean mergeWithDefaultConverters = false;
|
||||
|
||||
private volatile HeaderMapper<HttpHeaders> headerMapper = DefaultHttpHeaderMapper.inboundMapper();
|
||||
|
||||
@@ -143,25 +148,42 @@ public abstract class HttpRequestHandlingEndpointSupport extends MessagingGatewa
|
||||
this(true);
|
||||
}
|
||||
|
||||
@SuppressWarnings("rawtypes")
|
||||
public HttpRequestHandlingEndpointSupport(boolean expectReply) {
|
||||
this.expectReply = expectReply;
|
||||
this.messageConverters.add(new MultipartAwareFormHttpMessageConverter());
|
||||
this.messageConverters.add(new ByteArrayHttpMessageConverter());
|
||||
this.defaultMessageConverters.add(new MultipartAwareFormHttpMessageConverter());
|
||||
this.defaultMessageConverters.add(new ByteArrayHttpMessageConverter());
|
||||
StringHttpMessageConverter stringHttpMessageConverter = new StringHttpMessageConverter();
|
||||
stringHttpMessageConverter.setWriteAcceptCharset(false);
|
||||
this.messageConverters.add(stringHttpMessageConverter);
|
||||
this.messageConverters.add(new ResourceHttpMessageConverter());
|
||||
this.messageConverters.add(new SourceHttpMessageConverter());
|
||||
this.defaultMessageConverters.add(stringHttpMessageConverter);
|
||||
this.defaultMessageConverters.add(new ResourceHttpMessageConverter());
|
||||
@SuppressWarnings("rawtypes")
|
||||
SourceHttpMessageConverter<?> sourceConverter = new SourceHttpMessageConverter();
|
||||
this.defaultMessageConverters.add(sourceConverter);
|
||||
if (jaxb2Present) {
|
||||
this.messageConverters.add(new Jaxb2RootElementHttpMessageConverter());
|
||||
this.defaultMessageConverters.add(new Jaxb2RootElementHttpMessageConverter());
|
||||
if (logger.isDebugEnabled()) {
|
||||
logger.debug("'Jaxb2RootElementHttpMessageConverter' was added to the 'messageConverters'.");
|
||||
}
|
||||
}
|
||||
if (jacksonPresent) {
|
||||
this.messageConverters.add(new MappingJacksonHttpMessageConverter());
|
||||
if (JacksonJsonUtils.isJackson2Present()) {
|
||||
this.defaultMessageConverters.add(new MappingJackson2HttpMessageConverter());
|
||||
if (logger.isDebugEnabled()) {
|
||||
logger.debug("'MappingJackson2HttpMessageConverter' was added to the 'messageConverters'.");
|
||||
}
|
||||
}
|
||||
else if (JacksonJsonUtils.isJacksonPresent()) {
|
||||
this.defaultMessageConverters.add(new MappingJacksonHttpMessageConverter());
|
||||
if (logger.isDebugEnabled()) {
|
||||
logger.debug("'MappingJacksonHttpMessageConverter' was added to the 'messageConverters'.");
|
||||
}
|
||||
}
|
||||
if (romePresent) {
|
||||
this.messageConverters.add(new AtomFeedHttpMessageConverter());
|
||||
this.messageConverters.add(new RssChannelHttpMessageConverter());
|
||||
this.defaultMessageConverters.add(new AtomFeedHttpMessageConverter());
|
||||
this.defaultMessageConverters.add(new RssChannelHttpMessageConverter());
|
||||
if (logger.isDebugEnabled()) {
|
||||
logger.debug("'AtomFeedHttpMessageConverter' was added to the 'messageConverters'.");
|
||||
logger.debug("'RssChannelHttpMessageConverter' was added to the 'messageConverters'.");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -210,14 +232,28 @@ public abstract class HttpRequestHandlingEndpointSupport extends MessagingGatewa
|
||||
* responses.
|
||||
*/
|
||||
public void setMessageConverters(List<HttpMessageConverter<?>> messageConverters) {
|
||||
Assert.notEmpty(messageConverters, "'messageConverters' must not be empty");
|
||||
this.messageConverters = messageConverters;
|
||||
Assert.noNullElements(messageConverters.toArray(), "'messageConverters' must not contain null entries");
|
||||
List<HttpMessageConverter<?>> localConverters = new ArrayList<HttpMessageConverter<?>>(messageConverters);
|
||||
if (this.mergeWithDefaultConverters) {
|
||||
localConverters.addAll(this.defaultMessageConverters);
|
||||
this.convertersMerged = true;
|
||||
}
|
||||
this.messageConverters = localConverters;
|
||||
}
|
||||
|
||||
protected List<HttpMessageConverter<?>> getMessageConverters() {
|
||||
return this.messageConverters;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Flag which determines if the default converters should be available after
|
||||
* custom converters.
|
||||
*/
|
||||
public void setMergeWithDefaultConverters(boolean mergeWithDefaultConverters) {
|
||||
this.mergeWithDefaultConverters = mergeWithDefaultConverters;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the {@link HeaderMapper} to use when mapping between HTTP headers and MessageHeaders.
|
||||
*/
|
||||
@@ -284,6 +320,8 @@ public abstract class HttpRequestHandlingEndpointSupport extends MessagingGatewa
|
||||
/**
|
||||
* Locates the {@link MultipartResolver} bean based on the default name defined by the
|
||||
* {@link DispatcherServlet#MULTIPART_RESOLVER_BEAN_NAME} constant if available.
|
||||
* Sets up default converters if no converters set, or {@link #setMergeWithDefaultConverters(boolean)}
|
||||
* was called with true after the converters were set.
|
||||
*/
|
||||
@Override
|
||||
protected void onInit() throws Exception {
|
||||
@@ -306,11 +344,12 @@ public abstract class HttpRequestHandlingEndpointSupport extends MessagingGatewa
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (this.messageConverters.size() == 0 || (this.mergeWithDefaultConverters && !this.convertersMerged)) {
|
||||
this.messageConverters.addAll(this.defaultMessageConverters);
|
||||
}
|
||||
this.validateSupportedMethods();
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
protected void doStart() {
|
||||
this.shuttingDown = false;
|
||||
@@ -468,7 +507,7 @@ public abstract class HttpRequestHandlingEndpointSupport extends MessagingGatewa
|
||||
* Prepares an instance of {@link ServletServerHttpRequest} from the raw {@link HttpServletRequest}. Also converts
|
||||
* the request into a multipart request to make multiparts available if necessary. If no multipart resolver is set,
|
||||
* simply returns the existing request.
|
||||
* @param request current HTTP request
|
||||
* @param servletRequest current HTTP request
|
||||
* @return the processed request (multipart wrapper if necessary)
|
||||
* @see MultipartResolver#resolveMultipart
|
||||
*/
|
||||
|
||||
@@ -129,6 +129,17 @@
|
||||
</xsd:documentation>
|
||||
</xsd:annotation>
|
||||
</xsd:attribute>
|
||||
<xsd:attribute name="merge-with-default-converters" type="xsd:boolean" default="false">
|
||||
<xsd:annotation>
|
||||
<xsd:documentation>
|
||||
Flag to indicate if the default converters should be registered after any
|
||||
custom converters. This flag is used only if message-converters
|
||||
are provided, otherwise all default converters will be registered.
|
||||
|
||||
Defaults to "false"
|
||||
</xsd:documentation>
|
||||
</xsd:annotation>
|
||||
</xsd:attribute>
|
||||
<xsd:attribute name="header-mapper" type="xsd:string">
|
||||
<xsd:annotation>
|
||||
<xsd:appinfo>
|
||||
@@ -287,6 +298,17 @@ The String "HTTP_REQUEST_HEADERS" will match against any of the standard HTTP Re
|
||||
</xsd:documentation>
|
||||
</xsd:annotation>
|
||||
</xsd:attribute>
|
||||
<xsd:attribute name="merge-with-default-converters" type="xsd:boolean" default="false">
|
||||
<xsd:annotation>
|
||||
<xsd:documentation>
|
||||
Flag to indicate if the default converters should be registered after any custom
|
||||
converters. This flag is used only if message-converters
|
||||
are provided, otherwise all default converters will be registered.
|
||||
|
||||
Defaults to "false"
|
||||
</xsd:documentation>
|
||||
</xsd:annotation>
|
||||
</xsd:attribute>
|
||||
<xsd:attribute name="header-mapper" type="xsd:string">
|
||||
<xsd:annotation>
|
||||
<xsd:appinfo>
|
||||
|
||||
Reference in New Issue
Block a user