Tyler Van Gorder
Tyler Van Gorder

Reputation: 463

Spring Integration - AMQP Inferred Types In Java DSL?

I have been working on a "paved road" for setting up asynchronous messaging between two micro services using AMQP. We want to promote the use of separate domain objects for each service, which means that each service must define their own copy of any objects passed across the queue.

We are using Jackson2JsonMessageConverter on both the producer and the consumer side and we are using the Java DSL to wire the flows to/from the queues.

I am sure there is a way to do this, but it is escaping me: I want the consumer side to ignore the __TypeID__ header that is passed from the producer, as the consumer may have a different representation of that event (and it will likely be in in a different java package).

It appears there was work done such that if using the annotation @RabbitListener, an inferredArgumentTypeargument is derived and will override the header information. This is exactly what I would like to do, but I would like to use the Java DSL to do it. I have not yet found a clean way in which to do this and maybe I am just missing something obvious. It seems it would be fairly straight forward to derive the type when using the following DSL:

return IntegrationFlows
        .from(
                Amqp.inboundAdapter(factory, queueRemoteTaskStatus())
                        .concurrentConsumers(10)
                        .errorHandler(errorHandler)
                        .messageConverter(messageConverter)
        )
        .channel(channelRemoteTaskStatusIn())
        .handle(listener, "handleRemoteTaskStatus")
        .get();

However, this results in a ClassNotFound exception. The only way I have found to get around this, so far, is to set a custom message converter, which requires explicit definition of the type.

public class ForcedTypeJsonMessageConverter extends Jackson2JsonMessageConverter {

    ForcedTypeJsonMessageConverter(final Class<?> forcedType) {
        setClassMapper(new ClassMapper() {

            @Override
            public void fromClass(Class<?> clazz, MessageProperties properties) {
                    //this class is only used for inbound marshalling.
            }

            @Override
            public Class<?> toClass(MessageProperties properties) {
                return forcedType;
            }
        });
    }
}

I would really like this to be derived, so the developer does not have to really deal with this.

Is there an easier way to do this?

Upvotes: 1

Views: 657

Answers (1)

Gary Russell
Gary Russell

Reputation: 174664

The simplest way is to configure the Jackson converter's DefaultJackson2JavaTypeMapper with TypeIdMapping (setIdClassMapping()).

On the sending system, map foo:com.one.Foo and on the receiving system map foo:com.two.Foo.

Then, the __TypeId__ header gets foo and the receiving system will map it to its representation of a Foo.

EDIT

Another option would be to add an afterReceiveMessagePostProcessor to the inbound channel adapter's listener container - it could change the __TypeId__ header.

Upvotes: 1

Related Questions