INT-2874 Fix JSON/JMS Incompatibility
2.2.0 changed ObjectToJsonTransformr to add content-type to simplify AMQP applications. However, in a JMS environment, the DefaultJmsHeaderMapper attempted to map (and failed) to map the header, emitting a warning log entry. JMS does not allow '-' in property names. Add code such that: 1. If the ObjectToJsonTransformer is configured to use a content-type of an empty String (after trimming), suppress the addition of the header to the output message. For consistency, if the inbound message already has a content type header, and the transformer is configured with an empty String, remove the header. 2. Change the DefaultJmsHeaderMapper to map the MessageHeaders.CONTENT_TYPE header (content-type) to/from a JMS compliant property name (content_type). INT-2874 PR Comments Move constant to JmsHeaderMapper interface and rename. Fix failing test (explicit set content-type to ""). INT-2874 Documentation Updates Add docbook and schema documentation clarifying the behavior of the transformer with respect to setting the `content-type` header. INT-2874 Polishing - Remove Header Removal After further discussion, we decided to not remove an existing header, if 'content-type' is set to "". This is because there was no way to handle the case of NOT adding a header when none present, while retaining a header if it was already present. added test for empty content-type attrib and no existing header (while merging)
This commit is contained in:
committed by
Mark Fisher
parent
ed3cfe0271
commit
3902c96a20
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2012 the original author or authors.
|
||||
* Copyright 2002-2013 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.
|
||||
@@ -18,13 +18,13 @@ package org.springframework.integration.json;
|
||||
import java.io.StringWriter;
|
||||
|
||||
import org.codehaus.jackson.map.ObjectMapper;
|
||||
|
||||
import org.springframework.integration.Message;
|
||||
import org.springframework.integration.MessageHeaders;
|
||||
import org.springframework.integration.support.MessageBuilder;
|
||||
import org.springframework.integration.transformer.AbstractTransformer;
|
||||
import org.springframework.util.Assert;
|
||||
import org.springframework.util.LinkedCaseInsensitiveMap;
|
||||
import org.springframework.util.StringUtils;
|
||||
|
||||
/**
|
||||
* Transformer implementation that converts a payload instance into a JSON string representation.
|
||||
@@ -32,6 +32,7 @@ import org.springframework.util.LinkedCaseInsensitiveMap;
|
||||
* @author Mark Fisher
|
||||
* @author James Carr
|
||||
* @author Oleg Zhurakousky
|
||||
* @author Gary Russell
|
||||
* @since 2.0
|
||||
*/
|
||||
public class ObjectToJsonTransformer extends AbstractTransformer {
|
||||
@@ -61,7 +62,7 @@ public class ObjectToJsonTransformer extends AbstractTransformer {
|
||||
// only null assertion is needed since "" is a valid value
|
||||
Assert.notNull(contentType, "'contentType' must not be null");
|
||||
this.contentTypeExplicitlySet = true;
|
||||
this.contentType = contentType;
|
||||
this.contentType = contentType.trim();
|
||||
}
|
||||
|
||||
private String transformPayload(Object payload) throws Exception {
|
||||
@@ -80,11 +81,13 @@ public class ObjectToJsonTransformer extends AbstractTransformer {
|
||||
|
||||
if (headers.containsKey(MessageHeaders.CONTENT_TYPE)) {
|
||||
if (this.contentTypeExplicitlySet){
|
||||
// override
|
||||
headers.put(MessageHeaders.CONTENT_TYPE, this.contentType);
|
||||
// override, unless empty
|
||||
if (StringUtils.hasLength(this.contentType)) {
|
||||
headers.put(MessageHeaders.CONTENT_TYPE, this.contentType);
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
else if (StringUtils.hasLength(this.contentType)) {
|
||||
headers.put(MessageHeaders.CONTENT_TYPE, this.contentType);
|
||||
}
|
||||
messageBuilder.copyHeaders(headers);
|
||||
|
||||
@@ -2106,11 +2106,17 @@
|
||||
</xsd:choice>
|
||||
<xsd:attribute name="content-type" use="optional">
|
||||
<xsd:annotation>
|
||||
<xsd:documentation>
|
||||
Allows you to set 'content-type' Message header. In the case that a content-type header is already present,
|
||||
we will only override that value IF this attribute is explicitely set with
|
||||
content-type value (e.g., content-type="text/xml")
|
||||
</xsd:documentation>
|
||||
<xsd:documentation><![CDATA[
|
||||
Allows you to set the 'content-type' Message header. When a 'content-type' header is already present
|
||||
on the input message, the transformer will only override that value IF this attribute is explicitly set
|
||||
(e.g., content-type="text/x-json").
|
||||
If this attribute is omitted, the transformer will set the 'content-type' header to "application/json",
|
||||
when there is no existing 'content-type' header on the input message.
|
||||
Setting the attribute to an empty string ("")
|
||||
will suppress setting the header to the default value,
|
||||
but will not remove the header, if present on the input message. If you wish to remove an existing
|
||||
header, use a <header-filter/> before or after the transformer.
|
||||
]]></xsd:documentation>
|
||||
</xsd:annotation>
|
||||
</xsd:attribute>
|
||||
<xsd:attribute name="object-mapper" use="optional">
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2010 the original author or authors.
|
||||
* Copyright 2002-2013 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,6 +17,7 @@
|
||||
package org.springframework.integration.json;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertFalse;
|
||||
import static org.junit.Assert.assertNotNull;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
|
||||
@@ -31,6 +32,7 @@ import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.context.ApplicationContext;
|
||||
import org.springframework.integration.Message;
|
||||
import org.springframework.integration.MessageChannel;
|
||||
import org.springframework.integration.MessageHeaders;
|
||||
import org.springframework.integration.channel.QueueChannel;
|
||||
import org.springframework.integration.support.MessageBuilder;
|
||||
import org.springframework.integration.test.util.TestUtils;
|
||||
@@ -40,12 +42,13 @@ import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
|
||||
/**
|
||||
* @author Mark Fisher
|
||||
* @author Oleg Zhurakousky
|
||||
* @author Gary Russell
|
||||
* @since 2.0
|
||||
*/
|
||||
@ContextConfiguration
|
||||
@RunWith(SpringJUnit4ClassRunner.class)
|
||||
public class ObjectToJsonTransformerParserTests {
|
||||
|
||||
|
||||
@Autowired
|
||||
private volatile ApplicationContext context;
|
||||
|
||||
@@ -56,11 +59,15 @@ public class ObjectToJsonTransformerParserTests {
|
||||
private volatile MessageChannel customObjectMapperInput;
|
||||
|
||||
@Test
|
||||
public void testContextType(){
|
||||
ObjectToJsonTransformer transformer =
|
||||
public void testContentType(){
|
||||
ObjectToJsonTransformer transformer =
|
||||
TestUtils.getPropertyValue(context.getBean("defaultTransformer"), "handler.transformer", ObjectToJsonTransformer.class);
|
||||
assertEquals("application/json", TestUtils.getPropertyValue(transformer, "contentType"));
|
||||
|
||||
Message<?> transformed = transformer.transform(MessageBuilder.withPayload("foo").build());
|
||||
assertTrue(transformed.getHeaders().containsKey(MessageHeaders.CONTENT_TYPE));
|
||||
assertEquals("application/json", transformed.getHeaders().get(MessageHeaders.CONTENT_TYPE));
|
||||
|
||||
transformer =
|
||||
TestUtils.getPropertyValue(context.getBean("customTransformer"), "handler.transformer", ObjectToJsonTransformer.class);
|
||||
assertEquals("application/json", TestUtils.getPropertyValue(transformer, "contentType"));
|
||||
@@ -69,6 +76,13 @@ public class ObjectToJsonTransformerParserTests {
|
||||
TestUtils.getPropertyValue(context.getBean("emptyContentTypeTransformer"), "handler.transformer", ObjectToJsonTransformer.class);
|
||||
assertEquals("", TestUtils.getPropertyValue(transformer, "contentType"));
|
||||
|
||||
transformed = transformer.transform(MessageBuilder.withPayload("foo").build());
|
||||
assertFalse(transformed.getHeaders().containsKey(MessageHeaders.CONTENT_TYPE));
|
||||
|
||||
transformed = transformer.transform(MessageBuilder.withPayload("foo").setHeader(MessageHeaders.CONTENT_TYPE, "foo").build());
|
||||
assertNotNull(transformed.getHeaders().get(MessageHeaders.CONTENT_TYPE));
|
||||
assertEquals("foo", transformed.getHeaders().get(MessageHeaders.CONTENT_TYPE));
|
||||
|
||||
transformer =
|
||||
TestUtils.getPropertyValue(context.getBean("overridenContentTypeTransformer"), "handler.transformer", ObjectToJsonTransformer.class);
|
||||
assertEquals("text/xml", TestUtils.getPropertyValue(transformer, "contentType"));
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2012 the original author or authors.
|
||||
* Copyright 2002-2013 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,24 +16,25 @@
|
||||
|
||||
package org.springframework.integration.json;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertFalse;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
|
||||
import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
import org.codehaus.jackson.JsonGenerator.Feature;
|
||||
import org.codehaus.jackson.map.ObjectMapper;
|
||||
import org.junit.Test;
|
||||
|
||||
import org.springframework.integration.Message;
|
||||
import org.springframework.integration.MessageHeaders;
|
||||
import org.springframework.integration.message.GenericMessage;
|
||||
import org.springframework.integration.support.MessageBuilder;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
|
||||
/**
|
||||
* @author Mark Fisher
|
||||
* @author Oleg Zhurakousky
|
||||
* @author Gary Russell
|
||||
* @since 2.0
|
||||
*/
|
||||
public class ObjectToJsonTransformerTests {
|
||||
@@ -71,13 +72,22 @@ public class ObjectToJsonTransformerTests {
|
||||
|
||||
@Test
|
||||
public void withProvidedContentTypeAsEmptyString() throws Exception {
|
||||
ObjectToJsonTransformer transformer = new ObjectToJsonTransformer();
|
||||
transformer.setContentType("");
|
||||
Message<?> message = MessageBuilder.withPayload("foo").build();
|
||||
Message<?> result = transformer.transform(message);
|
||||
assertFalse(result.getHeaders().containsKey(MessageHeaders.CONTENT_TYPE));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void withProvidedContentTypeAsEmptyStringDoesNotOverride() throws Exception {
|
||||
ObjectToJsonTransformer transformer = new ObjectToJsonTransformer();
|
||||
transformer.setContentType("");
|
||||
Message<?> message = MessageBuilder.withPayload("foo").setHeader(MessageHeaders.CONTENT_TYPE, "text/xml").build();
|
||||
Message<?> result = transformer.transform(message);
|
||||
assertEquals("", result.getHeaders().get(MessageHeaders.CONTENT_TYPE));
|
||||
assertEquals("text/xml", result.getHeaders().get(MessageHeaders.CONTENT_TYPE));
|
||||
}
|
||||
|
||||
|
||||
@Test(expected=IllegalArgumentException.class)
|
||||
public void withProvidedContentTypeAsNull() throws Exception {
|
||||
ObjectToJsonTransformer transformer = new ObjectToJsonTransformer();
|
||||
|
||||
Reference in New Issue
Block a user