ndsurendra ndsurendra - 5 months ago 134
Java Question

Apache Camel: ProducerTemplate not unmarshalling the response

Camel version: 2.15.6

I used the ProducerTemplate to send a http request and get the response like this.

from("direct:getContact")
.process(new Processor() {
@Override
public void process(Exchange exchange) throws Exception {
CamelContext context = exchange.getContext();
ProducerTemplate producerTemplate = context.createProducerTemplate();
Contact contact = producerTemplate.requestBodyAndHeaders(
"http://localhost:8080/api/contact/2345",
null, headers, Contact.class);

logger.info("Contact is: " + new ObjectMapper().writeValueAsString(contact));

exchange.getOut().setBody(contact);

});


I get the contact as null.

When I try to get it as Object like this:

Object contact = producerTemplate.requestBodyAndHeaders(
"http://localhost:8080/api/contact/2345",
null, headers);


logger.info("Contact is: " + new ObjectMapper().writeValueAsString(contact));



com.fasterxml.jackson.databind.JsonMappingException: No serializer
found for class
org.apache.camel.converter.stream.CachedOutputStream$WrappedInputStream
and no properties discovered to create BeanSerializer (to avoid
exception, disable SerializationFeature.FAIL_ON_EMPTY_BEA


NS) )

Why is ProducerTemplate not able to unmarshall the response to the specified object?
How can this be achieved?

Edit

The Fix I observed is as follows:
If I first get the output as string and then deserialize it, it works.

String responseString = producerTemplate.requestBodyAndHeaders(
"http://localhost:8080/api/contact/2345",
null, headers, String.class);

Contact contact = new ObjectMapper().readValue(responseString, Contact.class);

Answer

My Answer is more of an combination of Rafal's to show how you can tie his code back into your solution to get the desired result. Thanks Rafal for setting up the sub route in this sample.

Assumptions: You have the rest API up and available already

Your new Code:

from("direct:getContact")
    .process(new Processor() {
        @Override
        public void process(Exchange exchange) throws Exception {
            CamelContext context = exchange.getContext();
            ProducerTemplate producerTemplate = context.createProducerTemplate();
            //Call another route not the rest endpoint
            Future<Contact> contact = producerTemplate.requestBodyAndHeaders( 
                "direct:RetrieveContactRoute", 
                 null, headers, Contact.class); 

             logger.info("Contact is: " + new ObjectMapper().writeValueAsString(contact.get())); 

             //Set the In Body not the Out Body 
             exchange.getIn().setBody(contact.get());
    }); 

A separate Route

JacksonDataFormat jacksonDataFormat = new JacksonDataFormat();
jacksonDataFormat.setUnmarshalType(Contact.class);

from("direct:RetrieveContactRoute")
    .to("http://localhost:8080/api/contact/2345")
    .unmarshal(jacksonDataFormat);