Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

org.apache.camel.InvalidPayloadException: No body available of type error thrown while unMarshalling Jaxb Object

I am sending JAXB Object to Rabbit MQ via Java.

JAXBContext jaxbContext = JAXBContext.newInstance(MyDTO.class);
    Marshaller jaxbMarshaller = jaxbContext.createMarshaller();

    // output pretty printed
    jaxbMarshaller.setProperty(Marshaller.JAXB_FRAGMENT, true);
     java.io.StringWriter sw = new StringWriter();
     jaxbMarshaller.marshal(deliveryrequest, sw);

    ConnectionFactory factory = new ConnectionFactory() ;

    //TODO change the hardcoding to the properties file
    factory.setHost("rabbitmq.host.net");
    factory.setUsername("user");
    factory.setPassword("pass");
    Channel channel ;
    Connection connection;

    Map<String, Object> args = new HashMap<String, Object>(); 
    String haPolicyValue = "all"; 
    args.put("x-ha-policy", haPolicyValue); 


    connection = factory.newConnection();
    channel = connection.createChannel();
    //TODO change the hardcoding to the properties file
    channel.queueDeclare("upload.com.some.queue", true, false, false, args);
    //TODO change the hardcoding to the properties file
    channel.basicPublish("com.some.exchange", "someroutingKey", 
            new AMQP.BasicProperties.Builder().contentType("text/plain")
            .deliveryMode(2).priority(1).userId("guest").build(),
            sw.toString().getBytes());

I am using Camel in different application to read this.

    <camel:route id="myRoute">
        <camel:from uri="RabbitMQEndpoint" />
        <camel:to uri="bean:MyHandler" />
    </camel:route>

Handler is using the Jaxb object redone in camel side

 @Handler
 public void handleRequest(MyDTO dto) throws ParseException {

I am getting the error which I did not expect to get.

Caused by: org.apache.camel.NoTypeConversionAvailableException: No type converter available to convert from type: byte[] to the required type: com.mycompany.MyDTO with value [B@1b8d3e42
at org.apache.camel.impl.converter.BaseTypeConverterRegistry.mandatoryConvertTo(BaseTypeConverterRegistry.java:181)
at org.apache.camel.impl.MessageSupport.getMandatoryBody(MessageSupport.java:99)

Solution is appreciated.

like image 939
R-JANA Avatar asked Dec 29 '25 01:12

R-JANA


2 Answers

Your message body type from rabbit is a byte[], and you want to call a bean which as MyDTO type. You have a type mismatch. And Camel cannot find a type converter that can convert the message body from byte[] to your MyDTO type.

Is the byte[] data from Rabbit in XML format? And do you have JAXB annotations on MyDTO classes, so you could use JAXB to marshal that from xml to Java ?

like image 71
Claus Ibsen Avatar answered Dec 31 '25 00:12

Claus Ibsen


It is Jaxb object. I was under impression that if i move the publisher too Camel. Things will be sorted out.

I changed the publisher to the following.

    @EndpointInject(context = "myContext" , uri = "direct:myRoute")
    private ProducerTemplate sendAMyContext;

And in method I called

     @Override
public MyResponse putMyCall(
        MyRequest myrequest) {

        sendMyContext.sendBody(myrequest);

My camel route is simple one

    <camel:camelContext id="MyContext" autoStartup="true" xmlns="http://camel.apache.org/schema/spring">


    <camel:endpoint id="myQueue" uri="${my.queue.1}" />

        <camel:route>
        <camel:from uri="direct:myRoute"/>
        <camel:to uri="bean:mySendHandler"/>
        <camel:convertBodyTo type="String"></camel:convertBodyTo>
        <camel:to uri="ref:myQueue" />
    </camel:route>

</camel:camelContext>

I added the handler to convert the Jaxb object to string(because of error)

public class MySendHandler {



 @Handler
 public String myDelivery( MyRequest myRequest) throws ParseException, JAXBException {


         JAXBContext jaxbContext = JAXBContext.newInstance(MyRequest.class);
        Marshaller jaxbMarshaller = jaxbContext.createMarshaller();

        // output pretty printed
        jaxbMarshaller.setProperty(Marshaller.JAXB_FRAGMENT, true);
        java.io.StringWriter sw = new StringWriter();
        jaxbMarshaller.marshal(attributedDeliveryRequest, sw);

     return sw.toString();

  }

Still the same error

 [SpringAMQPConsumer.SpringAMQPExecutor-1] WARN  org.springframework.amqp.support.converter.JsonMessageConverter (JsonMessageConverter.java:111) - Could not convert incoming message with content-type [text/plain]
SpringAMQPConsumer.SpringAMQPExecutor-1] ERROR org.apache.camel.processor.DefaultErrorHandler (MarkerIgnoringBase.java:161) - Failed delivery for (MessageId: ID-Con ExchangeId: ID-65455-1380873539452-3-2). 
Exhausted after delivery attempt: 1 caught: org.apache.camel.CamelExecutionException: Exception occurred during execution on the exchange: Exchange[Message: <XML>]
org.apache.camel.CamelExecutionException: Exception occurred during execution on the exchange: Exchange[Message: <xml>
    .....
Caused by: org.apache.camel.InvalidPayloadException: No body available of type: MyDTO but has value: [B@7da255c of type: byte[] on: Message: <xml>
. Caused by: [org.apache.camel.NoTypeConversionAvailableException - No type converter available to convert from type: byte[] to the required type: MyDeliveryDTO with value [B@7da255c]
    at org.apache.camel.impl.MessageSupport.getMandatoryBody(MessageSupport.java:101)
    at org.apache.camel.builder.ExpressionBuilder$38.evaluate(ExpressionBuilder.java:934)
    ... 74 more
Caused by: org.apache.camel.NoTypeConversionAvailableException: No type converter available to convert from type: byte[] to the required type: MyDTO with value [B@7da255c
    at org.apache.camel.impl.converter.BaseTypeConverterRegistry.mandatoryConvertTo(BaseTypeConverterRegistry.java:181)
    at org.apache.camel.impl.MessageSupport.getMandatoryBody(MessageSupport.java:99)
    ... 75 more

My receiving camel route is as below

<camel:route id="processVDelivery">
            <camel:from uri="aVEndpoint" />
            <camel:to uri="bean:myDataHandler" />
        </camel:route>

I added

    <camel:convertBodyTo type="String"></camel:convertBodyTo>

to it and it gave me error that it cannot convert it from string to the object

adding this

    <camel:unmarshal></camel:unmarshal>



-------------------------

Answer to the question will be all your mashaller have to be part of classpath

---------------------------------


    <dependency>
        <groupId>org.codehaus.jackson</groupId>
        <artifactId>jackson-core-asl</artifactId>
        <version>${jackson.version}</version>
    </dependency>
    <dependency>
        <groupId>org.codehaus.jackson</groupId>
        <artifactId>jackson-mapper-asl</artifactId>
        <version>${jackson.version}</version>
    </dependency>
    <dependency>
        <groupId>org.codehaus.jackson</groupId>
        <artifactId>jackson-jaxrs</artifactId>
        <version>${jackson.version}</version>
    </dependency>

------- Also you can the custom marshaller using dataformat

<camel:dataFormats>

                   <camel:jaxb id="name" contextPath="com.something"/>

    </camel:dataFormats

make sure that you keep jaxb.index file in com.something package with the root level Jaxb object name

like image 44
R-JANA Avatar answered Dec 31 '25 00:12

R-JANA



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!