Skip to content

Commit

Permalink
INT-3370: Add BoonJsonObjectMapper
Browse files Browse the repository at this point in the history
JIRA: https://jira.spring.io/browse/INT-3370

* Add `BoonJsonObjectMapper`
* Provide some tests
* Remove deprecations
* Polishing test according removed deprecations
* Change `JsonObjectMapper#populateJavaTypes` to get deal with `payload`, not its `class`,
since we can't (and Jackson's `TypeFactory`, too) determine generic type from `Collection`.
Use `iterators` instead to retrieve the type from the first item.

Conflicts:
	build.gradle
	spring-integration-amqp/src/test/java/org/springframework/integration/amqp/support/DefaultAmqpHeaderMapperTests.java

INT-3370: Polishing according PR comments

* Apply Gary's polishing to the Docs
* Fix `RecipientListRouter` JavaDoc warn
* Fix typo in test name for `UdpUnicastEndToEndTests`
* Fix `RedisQueueOutboundChannelAdapterTests` do not use Jackson 1.x

Final Polish
  • Loading branch information
Artem Bilan authored and garyrussell committed Aug 20, 2014
1 parent cda4a99 commit f84e798
Show file tree
Hide file tree
Showing 32 changed files with 447 additions and 425 deletions.
4 changes: 2 additions & 2 deletions build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,7 @@ subprojects { subproject ->
activeMqVersion = '5.9.0'
aspectjVersion = '1.8.0'
apacheSshdVersion = '0.10.1'
boonVersion = '0.22'
commonsDbcpVersion = '1.4'
commonsIoVersion = '2.4'
commonsNetVersion = '3.3'
Expand All @@ -83,7 +84,6 @@ subprojects { subproject ->
hibernateVersion = '4.2.11.Final'
hsqldbVersion = '2.3.2'
h2Version = '1.3.175'
jacksonVersion = '1.9.13'
jackson2Version = '2.3.2'
javaxActivationVersion = '1.1.1'
javaxMailVersion = '1.4.7'
Expand Down Expand Up @@ -246,9 +246,9 @@ project('spring-integration-core') {
compile "org.springframework.retry:spring-retry:$springRetryVersion"
compile "org.projectreactor:reactor-core:$reactorVersion"
compile("org.projectreactor.spring:reactor-spring-context:$reactorSpringVersion", optional)
compile("org.codehaus.jackson:jackson-mapper-asl:$jacksonVersion", optional)
compile("com.fasterxml.jackson.core:jackson-databind:$jackson2Version", optional)
compile("com.jayway.jsonpath:json-path:$jsonpathVersion", optional)
compile("io.fastjson:boon:$boonVersion", optional)

testCompile ("org.aspectj:aspectjweaver:$aspectjVersion")
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@

import java.util.Map;

import com.rabbitmq.client.Channel;
import org.junit.Test;
import org.mockito.Mockito;
import org.mockito.invocation.InvocationOnMock;
Expand All @@ -41,7 +42,7 @@
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.amqp.rabbit.listener.SimpleMessageListenerContainer;
import org.springframework.amqp.rabbit.support.CorrelationData;
import org.springframework.amqp.support.converter.JsonMessageConverter;
import org.springframework.amqp.support.converter.Jackson2JsonMessageConverter;
import org.springframework.amqp.support.converter.SimpleMessageConverter;
import org.springframework.beans.DirectFieldAccessor;
import org.springframework.beans.factory.BeanFactory;
Expand All @@ -60,8 +61,6 @@
import org.springframework.messaging.PollableChannel;
import org.springframework.messaging.support.GenericMessage;

import com.rabbitmq.client.Channel;

/**
* @author Artem Bilan
* @author Gary Russell
Expand All @@ -85,7 +84,7 @@ public Channel answer(InvocationOnMock invocation) throws Throwable {
container.setAcknowledgeMode(AcknowledgeMode.MANUAL);

AmqpInboundChannelAdapter adapter = new AmqpInboundChannelAdapter(container);
adapter.setMessageConverter(new JsonMessageConverter());
adapter.setMessageConverter(new Jackson2JsonMessageConverter());

PollableChannel channel = new QueueChannel();

Expand Down Expand Up @@ -140,7 +139,8 @@ public Channel answer(InvocationOnMock invocation) throws Throwable {
Object payload = new Foo("bar1");

MessageProperties amqpMessageProperties = new MessageProperties();
org.springframework.amqp.core.Message amqpMessage = new JsonMessageConverter().toMessage(payload, amqpMessageProperties);
org.springframework.amqp.core.Message amqpMessage =
new Jackson2JsonMessageConverter().toMessage(payload, amqpMessageProperties);

ChannelAwareMessageListener listener = (ChannelAwareMessageListener) container.getMessageListener();
listener.onMessage(amqpMessage, null);
Expand Down Expand Up @@ -186,20 +186,22 @@ public Message<?> transform(Message<?> message) {
}));

AmqpInboundGateway gateway = new AmqpInboundGateway(container);
gateway.setMessageConverter(new JsonMessageConverter());
gateway.setMessageConverter(new Jackson2JsonMessageConverter());

gateway.setRequestChannel(channel);
gateway.setBeanFactory(mock(BeanFactory.class));
gateway.afterPropertiesSet();

RabbitTemplate rabbitTemplate = Mockito.spy(TestUtils.getPropertyValue(gateway, "amqpTemplate", RabbitTemplate.class));
RabbitTemplate rabbitTemplate = Mockito.spy(TestUtils.getPropertyValue(gateway, "amqpTemplate",
RabbitTemplate.class));

Mockito.doAnswer(new Answer<Object>() {

@Override
public Object answer(InvocationOnMock invocation) throws Throwable {
org.springframework.amqp.core.Message message = (org.springframework.amqp.core.Message) invocation.getArguments()[2];
Map<String,Object> headers = message.getMessageProperties().getHeaders();
org.springframework.amqp.core.Message message =
(org.springframework.amqp.core.Message) invocation.getArguments()[2];
Map<String, Object> headers = message.getMessageProperties().getHeaders();
assertTrue(headers.containsKey(JsonHeaders.TYPE_ID.replaceFirst(JsonHeaders.PREFIX, "")));
assertNotEquals("foo", headers.get(JsonHeaders.TYPE_ID.replaceFirst(JsonHeaders.PREFIX, "")));
assertFalse(headers.containsKey(JsonHeaders.CONTENT_TYPE_ID.replaceFirst(JsonHeaders.PREFIX, "")));
Expand All @@ -209,9 +211,7 @@ public Object answer(InvocationOnMock invocation) throws Throwable {
assertFalse(headers.containsKey(JsonHeaders.CONTENT_TYPE_ID));
return null;
}
}

).when(rabbitTemplate).send(Mockito.anyString(), Mockito.anyString(),
}).when(rabbitTemplate).send(Mockito.anyString(), Mockito.anyString(),
Mockito.any(org.springframework.amqp.core.Message.class), Mockito.any(CorrelationData.class));

DirectFieldAccessor directFieldAccessor = new DirectFieldAccessor(gateway);
Expand All @@ -222,15 +222,15 @@ public Object answer(InvocationOnMock invocation) throws Throwable {
MessageProperties amqpMessageProperties = new MessageProperties();
amqpMessageProperties.setReplyTo("test");
amqpMessageProperties.setDeliveryTag(123L);
org.springframework.amqp.core.Message amqpMessage = new JsonMessageConverter().toMessage(payload, amqpMessageProperties);
org.springframework.amqp.core.Message amqpMessage =
new Jackson2JsonMessageConverter().toMessage(payload, amqpMessageProperties);

ChannelAwareMessageListener listener = (ChannelAwareMessageListener) container.getMessageListener();
listener.onMessage(amqpMessage, rabbitChannel);

}



public static class Foo {

private String bar;
Expand All @@ -257,11 +257,8 @@ public boolean equals(Object o) {

Foo foo = (Foo) o;

if (bar != null ? !bar.equals(foo.bar) : foo.bar != null) {
return false;
}
return !(bar != null ? !bar.equals(foo.bar) : foo.bar != null);

return true;
}

@Override
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,14 +27,16 @@
import java.util.Set;

import org.junit.Test;

import org.springframework.amqp.core.Message;
import org.springframework.amqp.core.MessageDeliveryMode;
import org.springframework.amqp.core.MessageProperties;
import org.springframework.amqp.support.converter.JsonMessageConverter;
import org.springframework.amqp.support.converter.Jackson2JsonMessageConverter;
import org.springframework.amqp.support.converter.MessageConverter;
import org.springframework.http.MediaType;
import org.springframework.messaging.MessageChannel;
import org.springframework.messaging.MessageHeaders;
import org.springframework.integration.amqp.AmqpHeaders;
import org.springframework.messaging.MessageHeaders;

/**
* @author Mark Fisher
Expand Down Expand Up @@ -198,7 +200,7 @@ public void messageTimestampNotMappedToAmqpProperties() {
@Test // INT-2090
public void jsonTypeIdNotOverwritten() {
DefaultAmqpHeaderMapper headerMapper = new DefaultAmqpHeaderMapper();
JsonMessageConverter converter = new JsonMessageConverter();
MessageConverter converter = new Jackson2JsonMessageConverter();
MessageProperties amqpProperties = new MessageProperties();
converter.toMessage("123", amqpProperties);
Map<String, Object> headerMap = new HashMap<String, Object>();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,22 +19,22 @@
import org.springframework.beans.factory.BeanClassLoaderAware;
import org.springframework.integration.mapping.support.JsonHeaders;
import org.springframework.integration.support.AbstractIntegrationMessageBuilder;
import org.springframework.integration.support.json.JacksonJsonObjectMapperProvider;
import org.springframework.integration.support.json.JsonObjectMapperProvider;
import org.springframework.integration.support.json.JsonObjectMapper;
import org.springframework.integration.transformer.AbstractTransformer;
import org.springframework.messaging.Message;

/**
* Transformer implementation that converts a JSON string payload into an instance of the provided target Class.
* By default this transformer uses {@linkplain JacksonJsonObjectMapperProvider} factory
* By default this transformer uses {@linkplain org.springframework.integration.support.json.JsonObjectMapperProvider} factory
* to get an instance of Jackson 1 or Jackson 2 JSON-processor {@linkplain JsonObjectMapper} implementation
* depending on the jackson-databind or jackson-mapper-asl libs on the classpath.
* Any other {@linkplain JsonObjectMapper} implementation can be provided.
*
* @author Mark Fisher
* @author Artem Bilan
* @see JsonObjectMapper
* @see JacksonJsonObjectMapperProvider
* @see org.springframework.integration.support.json.JsonObjectMapperProvider
* @since 2.0
*/
public class JsonToObjectTransformer extends AbstractTransformer implements BeanClassLoaderAware {
Expand All @@ -57,7 +57,7 @@ public JsonToObjectTransformer(JsonObjectMapper<?, ?> jsonObjectMapper) {

public JsonToObjectTransformer(Class<?> targetClass, JsonObjectMapper<?, ?> jsonObjectMapper) {
this.targetClass = targetClass;
this.jsonObjectMapper = (jsonObjectMapper != null) ? jsonObjectMapper : JacksonJsonObjectMapperProvider.newInstance();
this.jsonObjectMapper = (jsonObjectMapper != null) ? jsonObjectMapper : JsonObjectMapperProvider.newInstance();
}

@Override
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@
package org.springframework.integration.json;

import org.springframework.integration.support.AbstractIntegrationMessageBuilder;
import org.springframework.integration.support.json.JacksonJsonObjectMapperProvider;
import org.springframework.integration.support.json.JsonObjectMapperProvider;
import org.springframework.integration.support.json.JsonObjectMapper;
import org.springframework.integration.transformer.AbstractTransformer;
import org.springframework.messaging.Message;
Expand All @@ -27,7 +27,7 @@

/**
* Transformer implementation that converts a payload instance into a JSON string representation.
* By default this transformer uses {@linkplain JacksonJsonObjectMapperProvider} factory
* By default this transformer uses {@linkplain org.springframework.integration.support.json.JsonObjectMapperProvider} factory
* to get an instance of a Jackson or Jackson 2 JSON-processor {@linkplain JsonObjectMapper} implementation
* depending on the jackson-databind or jackson-mapper-asl libs on the classpath.
* Any other {@linkplain JsonObjectMapper} implementation can be provided.
Expand Down Expand Up @@ -56,15 +56,15 @@ public static enum ResultType {
private volatile boolean contentTypeExplicitlySet = false;

public ObjectToJsonTransformer() {
this(JacksonJsonObjectMapperProvider.newInstance());
this(JsonObjectMapperProvider.newInstance());
}

public ObjectToJsonTransformer(JsonObjectMapper<?, ?> jsonObjectMapper) {
this(jsonObjectMapper, ResultType.STRING);
}

public ObjectToJsonTransformer(ResultType resultType) {
this(JacksonJsonObjectMapperProvider.newInstance(), resultType);
this(JsonObjectMapperProvider.newInstance(), resultType);
}

public ObjectToJsonTransformer(JsonObjectMapper<?, ?> jsonObjectMapper, ResultType resultType) {
Expand Down Expand Up @@ -113,7 +113,7 @@ else if (StringUtils.hasLength(this.contentType)) {
headers.put(MessageHeaders.CONTENT_TYPE, this.contentType);
}

this.jsonObjectMapper.populateJavaTypes(headers, message.getPayload().getClass());
this.jsonObjectMapper.populateJavaTypes(headers, message.getPayload());

messageBuilder.copyHeaders(headers);
return messageBuilder.build();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -104,7 +104,7 @@ public void setRecipients(List<Recipient> recipients) {

/**
* Set the recipients for this router.
* @param recipientMappings, map contains channelName and expression
* @param recipientMappings map contains channelName and expression
*/
@Override
@ManagedAttribute
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,8 @@
* @author Artem Bilan
* @since 3.0
*/
public abstract class AbstractJacksonJsonObjectMapper<N, P, J> implements JsonObjectMapper<N, P>, BeanClassLoaderAware {
public abstract class AbstractJacksonJsonObjectMapper<N, P, J> extends JsonObjectMapperAdapter<N, P>
implements BeanClassLoaderAware {

protected static final Collection<Class<?>> supportedJsonTypes =
Arrays.<Class<?>> asList(String.class, byte[].class, File.class, URL.class, InputStream.class, Reader.class);
Expand Down
Loading

0 comments on commit f84e798

Please sign in to comment.