getOriginalMessage()

classic Classic list List threaded Threaded
7 messages Options
Reply | Threaded
Open this post in threaded view
|

getOriginalMessage()

Bengt Rodehav
I'm using Camel 2.12.1.

For error handling purposes I need access to the original message but I'm
having problems with that.

In my error handler I do this:

  Message originalMessage =
theExchange.getUnitOfWork().getOriginalInMessage();
  System.out.println(originalMessage); // 1
  System.out.println("Body: " + originalMessage.getBody()); // 2
  System.out.println("Body as string: " +
originalMessage.getBody(String.class)); // 3

The output at "1" is:

TradeSet.xml

The output at "2" is:

Body:
GenericFile[C:\dev\karaf\connect-sts\head\apache-karaf2.3.4\bin\..\..\..\common\data\interfaces\ts2so\TradeSet.xml]

The output at "3" is:

Body as string: null

I can reproduce this problem with a simple route that just uses the file
component. Something like this:

from("file:in").process(new Processor() {
  public void process(Exchange theExchange) {
  Message originalMessage =
theExchange.getUnitOfWork().getOriginalInMessage();
  System.out.println(originalMessage); // 1
  System.out.println("Body: " + originalMessage.getBody()); // 2
  System.out.println("Body as string: " +
originalMessage.getBody(String.class)); // 3
  }
});


Thus it seems like I can access the original message but I can't get the
actual body content - at least not as a string. In my case the file
contains an xml document that I need to get hold of. Is this a known bug or
have I misunderstood the purpose with the getOriginalMessage() method?

/Bengt
Reply | Threaded
Open this post in threaded view
|

Re: getOriginalMessage()

Claus Ibsen-2
Hi

No its streams playing tricks on you
http://camel.apache.org/why-is-my-message-body-empty.html

So you get the body 2 times (at #2 and #3) and the 2nd time its empty.

On Wed, Mar 12, 2014 at 4:29 PM, Bengt Rodehav <[hidden email]> wrote:

> I'm using Camel 2.12.1.
>
> For error handling purposes I need access to the original message but I'm
> having problems with that.
>
> In my error handler I do this:
>
>   Message originalMessage =
> theExchange.getUnitOfWork().getOriginalInMessage();
>   System.out.println(originalMessage); // 1
>   System.out.println("Body: " + originalMessage.getBody()); // 2
>   System.out.println("Body as string: " +
> originalMessage.getBody(String.class)); // 3
>
> The output at "1" is:
>
> TradeSet.xml
>
> The output at "2" is:
>
> Body:
> GenericFile[C:\dev\karaf\connect-sts\head\apache-karaf2.3.4\bin\..\..\..\common\data\interfaces\ts2so\TradeSet.xml]
>
> The output at "3" is:
>
> Body as string: null
>
> I can reproduce this problem with a simple route that just uses the file
> component. Something like this:
>
> from("file:in").process(new Processor() {
>   public void process(Exchange theExchange) {
>   Message originalMessage =
> theExchange.getUnitOfWork().getOriginalInMessage();
>   System.out.println(originalMessage); // 1
>   System.out.println("Body: " + originalMessage.getBody()); // 2
>   System.out.println("Body as string: " +
> originalMessage.getBody(String.class)); // 3
>   }
> });
>
>
> Thus it seems like I can access the original message but I can't get the
> actual body content - at least not as a string. In my case the file
> contains an xml document that I need to get hold of. Is this a known bug or
> have I misunderstood the purpose with the getOriginalMessage() method?
>
> /Bengt



--
Claus Ibsen
-----------------
Red Hat, Inc.
Email: [hidden email]
Twitter: davsclaus
Blog: http://davsclaus.com
Author of Camel in Action: http://www.manning.com/ibsen
Make your Camel applications look hawt, try: http://hawt.io
Reply | Threaded
Open this post in threaded view
|

Re: getOriginalMessage()

Bengt Rodehav
Thanks for your reply Claus.

I changed my code to:

from("file:in").streamcaching().process(new Processor() {
  public void process(Exchange theExchange) {
  Message originalMessage =
theExchange.getUnitOfWork().getOriginalInMessage();
  System.out.println(originalMessage); // 1
  System.out.println("Body: " + originalMessage.getBody()); // 2
  System.out.println("Body as string: " +
originalMessage.getBody(String.class)); // 3
  }
});

Unfortunately this makes no difference - I get the same result.

Also, if I skip Step #2 above I still get "Body as string: null"  at step
#3 so I don't think I'm reeading the body twice.

/Bengt



2014-03-12 16:34 GMT+01:00 Claus Ibsen <[hidden email]>:

> Hi
>
> No its streams playing tricks on you
> http://camel.apache.org/why-is-my-message-body-empty.html
>
> So you get the body 2 times (at #2 and #3) and the 2nd time its empty.
>
> On Wed, Mar 12, 2014 at 4:29 PM, Bengt Rodehav <[hidden email]> wrote:
> > I'm using Camel 2.12.1.
> >
> > For error handling purposes I need access to the original message but I'm
> > having problems with that.
> >
> > In my error handler I do this:
> >
> >   Message originalMessage =
> > theExchange.getUnitOfWork().getOriginalInMessage();
> >   System.out.println(originalMessage); // 1
> >   System.out.println("Body: " + originalMessage.getBody()); // 2
> >   System.out.println("Body as string: " +
> > originalMessage.getBody(String.class)); // 3
> >
> > The output at "1" is:
> >
> > TradeSet.xml
> >
> > The output at "2" is:
> >
> > Body:
> >
> GenericFile[C:\dev\karaf\connect-sts\head\apache-karaf2.3.4\bin\..\..\..\common\data\interfaces\ts2so\TradeSet.xml]
> >
> > The output at "3" is:
> >
> > Body as string: null
> >
> > I can reproduce this problem with a simple route that just uses the file
> > component. Something like this:
> >
> > from("file:in").process(new Processor() {
> >   public void process(Exchange theExchange) {
> >   Message originalMessage =
> > theExchange.getUnitOfWork().getOriginalInMessage();
> >   System.out.println(originalMessage); // 1
> >   System.out.println("Body: " + originalMessage.getBody()); // 2
> >   System.out.println("Body as string: " +
> > originalMessage.getBody(String.class)); // 3
> >   }
> > });
> >
> >
> > Thus it seems like I can access the original message but I can't get the
> > actual body content - at least not as a string. In my case the file
> > contains an xml document that I need to get hold of. Is this a known bug
> or
> > have I misunderstood the purpose with the getOriginalMessage() method?
> >
> > /Bengt
>
>
>
> --
> Claus Ibsen
> -----------------
> Red Hat, Inc.
> Email: [hidden email]
> Twitter: davsclaus
> Blog: http://davsclaus.com
> Author of Camel in Action: http://www.manning.com/ibsen
> Make your Camel applications look hawt, try: http://hawt.io
>
Reply | Threaded
Open this post in threaded view
|

Re: getOriginalMessage()

Bengt Rodehav
I did the following:

- Downloaded the zip file for Camel 2.12.3 (binary distribution)

- Added two java files to the example project "camel-example-ftp". The
files are called MyFileClient.java and MyFileClientRouteBuilder.java. Their
contents is embedded at the end of this mail.

- I started MyFileClient and dropped a file in the "target/in" directory.

- I get the exact same result as I described in my earlier post. I cannot
access the body contents of the original message.

Is this as designed or is it a bug (or have I misunderstood)?

/Bengt

*MyFileClient.java*
package org.apache.camel.example.ftp;

import org.apache.camel.main.Main;

public final class MyFileClient {

private MyFileClient() {
}

public static void main(String[] args) throws Exception {
Main main = new Main();
main.addRouteBuilder(new MyFileClientRouteBuilder());
main.enableHangupSupport();
main.run();
}
}


*MyFileClientRouteBuilder.java*
package org.apache.camel.example.ftp;

import org.apache.camel.Exchange;
import org.apache.camel.Message;
import org.apache.camel.Processor;
import org.apache.camel.builder.RouteBuilder;

public class MyFileClientRouteBuilder extends RouteBuilder {

@Override
public void configure() throws Exception {
// lets shutdown faster in case of in-flight messages stack up
getContext().getShutdownStrategy().setTimeout(10);

from("file:target/in").streamCaching().process(new Processor() {
  public void process(Exchange theExchange) {
  Message originalMessage =
theExchange.getUnitOfWork().getOriginalInMessage();
  System.out.println("Original message: " + originalMessage);
  System.out.println("Original body: " + originalMessage.getBody());
  System.out.println("Original body as string: " +
originalMessage.getBody(String.class));

  Message message = theExchange.getIn();
  System.out.println("Message: " + message);
  System.out.println("Body: " + message.getBody());
  System.out.println("Body as string: " + message.getBody(String.class));
  }
});
}
}



2014-03-12 16:51 GMT+01:00 Bengt Rodehav <[hidden email]>:

> Thanks for your reply Claus.
>
> I changed my code to:
>
> from("file:in").streamcaching().process(new Processor() {
>   public void process(Exchange theExchange) {
>   Message originalMessage =
> theExchange.getUnitOfWork().getOriginalInMessage();
>   System.out.println(originalMessage); // 1
>   System.out.println("Body: " + originalMessage.getBody()); // 2
>   System.out.println("Body as string: " +
> originalMessage.getBody(String.class)); // 3
>   }
> });
>
> Unfortunately this makes no difference - I get the same result.
>
> Also, if I skip Step #2 above I still get "Body as string: null"  at step
> #3 so I don't think I'm reeading the body twice.
>
> /Bengt
>
>
>
> 2014-03-12 16:34 GMT+01:00 Claus Ibsen <[hidden email]>:
>
> Hi
>>
>> No its streams playing tricks on you
>> http://camel.apache.org/why-is-my-message-body-empty.html
>>
>> So you get the body 2 times (at #2 and #3) and the 2nd time its empty.
>>
>> On Wed, Mar 12, 2014 at 4:29 PM, Bengt Rodehav <[hidden email]> wrote:
>> > I'm using Camel 2.12.1.
>> >
>> > For error handling purposes I need access to the original message but
>> I'm
>> > having problems with that.
>> >
>> > In my error handler I do this:
>> >
>> >   Message originalMessage =
>> > theExchange.getUnitOfWork().getOriginalInMessage();
>> >   System.out.println(originalMessage); // 1
>> >   System.out.println("Body: " + originalMessage.getBody()); // 2
>> >   System.out.println("Body as string: " +
>> > originalMessage.getBody(String.class)); // 3
>> >
>> > The output at "1" is:
>> >
>> > TradeSet.xml
>> >
>> > The output at "2" is:
>> >
>> > Body:
>> >
>> GenericFile[C:\dev\karaf\connect-sts\head\apache-karaf2.3.4\bin\..\..\..\common\data\interfaces\ts2so\TradeSet.xml]
>> >
>> > The output at "3" is:
>> >
>> > Body as string: null
>> >
>> > I can reproduce this problem with a simple route that just uses the file
>> > component. Something like this:
>> >
>> > from("file:in").process(new Processor() {
>> >   public void process(Exchange theExchange) {
>> >   Message originalMessage =
>> > theExchange.getUnitOfWork().getOriginalInMessage();
>> >   System.out.println(originalMessage); // 1
>> >   System.out.println("Body: " + originalMessage.getBody()); // 2
>> >   System.out.println("Body as string: " +
>> > originalMessage.getBody(String.class)); // 3
>> >   }
>> > });
>> >
>> >
>> > Thus it seems like I can access the original message but I can't get the
>> > actual body content - at least not as a string. In my case the file
>> > contains an xml document that I need to get hold of. Is this a known
>> bug or
>> > have I misunderstood the purpose with the getOriginalMessage() method?
>> >
>> > /Bengt
>>
>>
>>
>> --
>> Claus Ibsen
>> -----------------
>> Red Hat, Inc.
>> Email: [hidden email]
>> Twitter: davsclaus
>> Blog: http://davsclaus.com
>> Author of Camel in Action: http://www.manning.com/ibsen
>> Make your Camel applications look hawt, try: http://hawt.io
>>
>
>
Reply | Threaded
Open this post in threaded view
|

Re: getOriginalMessage()

Bengt Rodehav
I've now done some debugging to see what actually happens. It turns out
that both the variable "message" and the variable "originalMessage" are of
type GenericFileMessage. It turns out that the "message" has an exchange
set to its "exchange" property while the "originalMessage" does not (i e
originalMessage.getExchange() returns null).

This makes all the difference when looking at the base class
"MessageSupport". The type conversion ends up in the method
MessageSupport.getBody() method and it looks like this:

    protected <T> T getBody(Class<T> type, Object body) {
        // eager same instance type test to avoid the overhead of invoking
the type converter
        // if already same type
        if (type.isInstance(body)) {
            return type.cast(body);
        }

        Exchange e = getExchange();
        if (e != null) {
            TypeConverter converter = e.getContext().getTypeConverter();

            // lets first try converting the body itself first
            // as for some types like InputStream v Reader its more
efficient to do the transformation
            // from the body itself as its got efficient implementations of
them, before trying the message
            T answer = converter.convertTo(type, e, body);
            if (answer != null) {
                return answer;
            }

            // fallback and try the message itself (e.g. used in camel-http)
            answer = converter.tryConvertTo(type, e, this);
            if (answer != null) {
                return answer;
            }
        }

        // not possible to convert
        return null;
    }

Thus, since now exchange is attached to the message this method always
returns null.

If I change my code snippet to:

...
Message originalMessage =
theExchange.getUnitOfWork().getOriginalInMessage();
GenericFileMessage gfm =
(GenericFileMessage)originalMessage;gfm.setExchange(theExchange);
...

Then everything works. However, this is not a possible workaround for me. I
need this code to be generic and I can only access the Message interface.

I'm not sure if it's by design that the originalMessage is not attached to
an exchange or not. I guess it could be. But then how can I, in a generic
way, convert the body to a string?

/Bengt



2014-03-12 19:06 GMT+01:00 Bengt Rodehav <[hidden email]>:

> I did the following:
>
> - Downloaded the zip file for Camel 2.12.3 (binary distribution)
>
> - Added two java files to the example project "camel-example-ftp". The
> files are called MyFileClient.java and MyFileClientRouteBuilder.java. Their
> contents is embedded at the end of this mail.
>
> - I started MyFileClient and dropped a file in the "target/in" directory.
>
> - I get the exact same result as I described in my earlier post. I cannot
> access the body contents of the original message.
>
> Is this as designed or is it a bug (or have I misunderstood)?
>
> /Bengt
>
> *MyFileClient.java*
> package org.apache.camel.example.ftp;
>
> import org.apache.camel.main.Main;
>
> public final class MyFileClient {
>
> private MyFileClient() {
>  }
>
> public static void main(String[] args) throws Exception {
> Main main = new Main();
>  main.addRouteBuilder(new MyFileClientRouteBuilder());
> main.enableHangupSupport();
> main.run();
>  }
> }
>
>
> *MyFileClientRouteBuilder.java*
> package org.apache.camel.example.ftp;
>
> import org.apache.camel.Exchange;
> import org.apache.camel.Message;
> import org.apache.camel.Processor;
> import org.apache.camel.builder.RouteBuilder;
>
> public class MyFileClientRouteBuilder extends RouteBuilder {
>
> @Override
> public void configure() throws Exception {
> // lets shutdown faster in case of in-flight messages stack up
>  getContext().getShutdownStrategy().setTimeout(10);
>
> from("file:target/in").streamCaching().process(new Processor() {
>   public void process(Exchange theExchange) {
>   Message originalMessage =
> theExchange.getUnitOfWork().getOriginalInMessage();
>   System.out.println("Original message: " + originalMessage);
>   System.out.println("Original body: " + originalMessage.getBody());
>   System.out.println("Original body as string: " +
> originalMessage.getBody(String.class));
>
>   Message message = theExchange.getIn();
>   System.out.println("Message: " + message);
>   System.out.println("Body: " + message.getBody());
>   System.out.println("Body as string: " + message.getBody(String.class));
>   }
> });
>  }
> }
>
>
>
> 2014-03-12 16:51 GMT+01:00 Bengt Rodehav <[hidden email]>:
>
> Thanks for your reply Claus.
>>
>> I changed my code to:
>>
>> from("file:in").streamcaching().process(new Processor() {
>>   public void process(Exchange theExchange) {
>>   Message originalMessage =
>> theExchange.getUnitOfWork().getOriginalInMessage();
>>   System.out.println(originalMessage); // 1
>>   System.out.println("Body: " + originalMessage.getBody()); // 2
>>   System.out.println("Body as string: " +
>> originalMessage.getBody(String.class)); // 3
>>   }
>> });
>>
>> Unfortunately this makes no difference - I get the same result.
>>
>> Also, if I skip Step #2 above I still get "Body as string: null"  at step
>> #3 so I don't think I'm reeading the body twice.
>>
>> /Bengt
>>
>>
>>
>> 2014-03-12 16:34 GMT+01:00 Claus Ibsen <[hidden email]>:
>>
>> Hi
>>>
>>> No its streams playing tricks on you
>>> http://camel.apache.org/why-is-my-message-body-empty.html
>>>
>>> So you get the body 2 times (at #2 and #3) and the 2nd time its empty.
>>>
>>> On Wed, Mar 12, 2014 at 4:29 PM, Bengt Rodehav <[hidden email]>
>>> wrote:
>>> > I'm using Camel 2.12.1.
>>> >
>>> > For error handling purposes I need access to the original message but
>>> I'm
>>> > having problems with that.
>>> >
>>> > In my error handler I do this:
>>> >
>>> >   Message originalMessage =
>>> > theExchange.getUnitOfWork().getOriginalInMessage();
>>> >   System.out.println(originalMessage); // 1
>>> >   System.out.println("Body: " + originalMessage.getBody()); // 2
>>> >   System.out.println("Body as string: " +
>>> > originalMessage.getBody(String.class)); // 3
>>> >
>>> > The output at "1" is:
>>> >
>>> > TradeSet.xml
>>> >
>>> > The output at "2" is:
>>> >
>>> > Body:
>>> >
>>> GenericFile[C:\dev\karaf\connect-sts\head\apache-karaf2.3.4\bin\..\..\..\common\data\interfaces\ts2so\TradeSet.xml]
>>> >
>>> > The output at "3" is:
>>> >
>>> > Body as string: null
>>> >
>>> > I can reproduce this problem with a simple route that just uses the
>>> file
>>> > component. Something like this:
>>> >
>>> > from("file:in").process(new Processor() {
>>> >   public void process(Exchange theExchange) {
>>> >   Message originalMessage =
>>> > theExchange.getUnitOfWork().getOriginalInMessage();
>>> >   System.out.println(originalMessage); // 1
>>> >   System.out.println("Body: " + originalMessage.getBody()); // 2
>>> >   System.out.println("Body as string: " +
>>> > originalMessage.getBody(String.class)); // 3
>>> >   }
>>> > });
>>> >
>>> >
>>> > Thus it seems like I can access the original message but I can't get
>>> the
>>> > actual body content - at least not as a string. In my case the file
>>> > contains an xml document that I need to get hold of. Is this a known
>>> bug or
>>> > have I misunderstood the purpose with the getOriginalMessage() method?
>>> >
>>> > /Bengt
>>>
>>>
>>>
>>> --
>>> Claus Ibsen
>>> -----------------
>>> Red Hat, Inc.
>>> Email: [hidden email]
>>> Twitter: davsclaus
>>> Blog: http://davsclaus.com
>>> Author of Camel in Action: http://www.manning.com/ibsen
>>> Make your Camel applications look hawt, try: http://hawt.io
>>>
>>
>>
>
Reply | Threaded
Open this post in threaded view
|

Re: getOriginalMessage()

Bengt Rodehav
BTW, while debugging I noticed another difference between the current
message (retrieved by the getIn() method) and the original message. When
comparing the message headers, the original message lacks the header
"breadcrumbId". This probably isn't related but it seems strange that it is
omitted.

Note that the value of "breadcrumbId" seems to be the same as the messageId
which in turn is the same for the current message and the original message.

/Bengt


2014-03-12 20:49 GMT+01:00 Bengt Rodehav <[hidden email]>:

> I've now done some debugging to see what actually happens. It turns out
> that both the variable "message" and the variable "originalMessage" are of
> type GenericFileMessage. It turns out that the "message" has an exchange
> set to its "exchange" property while the "originalMessage" does not (i e
> originalMessage.getExchange() returns null).
>
> This makes all the difference when looking at the base class
> "MessageSupport". The type conversion ends up in the method
> MessageSupport.getBody() method and it looks like this:
>
>     protected <T> T getBody(Class<T> type, Object body) {
>         // eager same instance type test to avoid the overhead of invoking
> the type converter
>         // if already same type
>         if (type.isInstance(body)) {
>             return type.cast(body);
>         }
>
>         Exchange e = getExchange();
>         if (e != null) {
>             TypeConverter converter = e.getContext().getTypeConverter();
>
>             // lets first try converting the body itself first
>             // as for some types like InputStream v Reader its more
> efficient to do the transformation
>             // from the body itself as its got efficient implementations
> of them, before trying the message
>             T answer = converter.convertTo(type, e, body);
>             if (answer != null) {
>                 return answer;
>             }
>
>             // fallback and try the message itself (e.g. used in
> camel-http)
>             answer = converter.tryConvertTo(type, e, this);
>             if (answer != null) {
>                 return answer;
>             }
>         }
>
>         // not possible to convert
>         return null;
>     }
>
> Thus, since now exchange is attached to the message this method always
> returns null.
>
> If I change my code snippet to:
>
> ...
> Message originalMessage =
> theExchange.getUnitOfWork().getOriginalInMessage();
> GenericFileMessage gfm =
> (GenericFileMessage)originalMessage;gfm.setExchange(theExchange);
> ...
>
> Then everything works. However, this is not a possible workaround for me.
> I need this code to be generic and I can only access the Message interface.
>
> I'm not sure if it's by design that the originalMessage is not attached to
> an exchange or not. I guess it could be. But then how can I, in a generic
> way, convert the body to a string?
>
> /Bengt
>
>
>
> 2014-03-12 19:06 GMT+01:00 Bengt Rodehav <[hidden email]>:
>
> I did the following:
>>
>> - Downloaded the zip file for Camel 2.12.3 (binary distribution)
>>
>> - Added two java files to the example project "camel-example-ftp". The
>> files are called MyFileClient.java and MyFileClientRouteBuilder.java. Their
>> contents is embedded at the end of this mail.
>>
>> - I started MyFileClient and dropped a file in the "target/in" directory.
>>
>> - I get the exact same result as I described in my earlier post. I cannot
>> access the body contents of the original message.
>>
>> Is this as designed or is it a bug (or have I misunderstood)?
>>
>> /Bengt
>>
>> *MyFileClient.java*
>> package org.apache.camel.example.ftp;
>>
>> import org.apache.camel.main.Main;
>>
>> public final class MyFileClient {
>>
>> private MyFileClient() {
>>  }
>>
>> public static void main(String[] args) throws Exception {
>> Main main = new Main();
>>  main.addRouteBuilder(new MyFileClientRouteBuilder());
>> main.enableHangupSupport();
>> main.run();
>>  }
>> }
>>
>>
>> *MyFileClientRouteBuilder.java*
>> package org.apache.camel.example.ftp;
>>
>> import org.apache.camel.Exchange;
>> import org.apache.camel.Message;
>> import org.apache.camel.Processor;
>> import org.apache.camel.builder.RouteBuilder;
>>
>> public class MyFileClientRouteBuilder extends RouteBuilder {
>>
>> @Override
>> public void configure() throws Exception {
>> // lets shutdown faster in case of in-flight messages stack up
>>  getContext().getShutdownStrategy().setTimeout(10);
>>
>> from("file:target/in").streamCaching().process(new Processor() {
>>    public void process(Exchange theExchange) {
>>   Message originalMessage =
>> theExchange.getUnitOfWork().getOriginalInMessage();
>>   System.out.println("Original message: " + originalMessage);
>>   System.out.println("Original body: " + originalMessage.getBody());
>>   System.out.println("Original body as string: " +
>> originalMessage.getBody(String.class));
>>
>>   Message message = theExchange.getIn();
>>   System.out.println("Message: " + message);
>>   System.out.println("Body: " + message.getBody());
>>   System.out.println("Body as string: " + message.getBody(String.class));
>>   }
>> });
>>  }
>> }
>>
>>
>>
>> 2014-03-12 16:51 GMT+01:00 Bengt Rodehav <[hidden email]>:
>>
>> Thanks for your reply Claus.
>>>
>>> I changed my code to:
>>>
>>> from("file:in").streamcaching().process(new Processor() {
>>>   public void process(Exchange theExchange) {
>>>   Message originalMessage =
>>> theExchange.getUnitOfWork().getOriginalInMessage();
>>>   System.out.println(originalMessage); // 1
>>>   System.out.println("Body: " + originalMessage.getBody()); // 2
>>>   System.out.println("Body as string: " +
>>> originalMessage.getBody(String.class)); // 3
>>>   }
>>> });
>>>
>>> Unfortunately this makes no difference - I get the same result.
>>>
>>> Also, if I skip Step #2 above I still get "Body as string: null"  at
>>> step #3 so I don't think I'm reeading the body twice.
>>>
>>> /Bengt
>>>
>>>
>>>
>>> 2014-03-12 16:34 GMT+01:00 Claus Ibsen <[hidden email]>:
>>>
>>> Hi
>>>>
>>>> No its streams playing tricks on you
>>>> http://camel.apache.org/why-is-my-message-body-empty.html
>>>>
>>>> So you get the body 2 times (at #2 and #3) and the 2nd time its empty.
>>>>
>>>> On Wed, Mar 12, 2014 at 4:29 PM, Bengt Rodehav <[hidden email]>
>>>> wrote:
>>>> > I'm using Camel 2.12.1.
>>>> >
>>>> > For error handling purposes I need access to the original message but
>>>> I'm
>>>> > having problems with that.
>>>> >
>>>> > In my error handler I do this:
>>>> >
>>>> >   Message originalMessage =
>>>> > theExchange.getUnitOfWork().getOriginalInMessage();
>>>> >   System.out.println(originalMessage); // 1
>>>> >   System.out.println("Body: " + originalMessage.getBody()); // 2
>>>> >   System.out.println("Body as string: " +
>>>> > originalMessage.getBody(String.class)); // 3
>>>> >
>>>> > The output at "1" is:
>>>> >
>>>> > TradeSet.xml
>>>> >
>>>> > The output at "2" is:
>>>> >
>>>> > Body:
>>>> >
>>>> GenericFile[C:\dev\karaf\connect-sts\head\apache-karaf2.3.4\bin\..\..\..\common\data\interfaces\ts2so\TradeSet.xml]
>>>> >
>>>> > The output at "3" is:
>>>> >
>>>> > Body as string: null
>>>> >
>>>> > I can reproduce this problem with a simple route that just uses the
>>>> file
>>>> > component. Something like this:
>>>> >
>>>> > from("file:in").process(new Processor() {
>>>> >   public void process(Exchange theExchange) {
>>>> >   Message originalMessage =
>>>> > theExchange.getUnitOfWork().getOriginalInMessage();
>>>> >   System.out.println(originalMessage); // 1
>>>> >   System.out.println("Body: " + originalMessage.getBody()); // 2
>>>> >   System.out.println("Body as string: " +
>>>> > originalMessage.getBody(String.class)); // 3
>>>> >   }
>>>> > });
>>>> >
>>>> >
>>>> > Thus it seems like I can access the original message but I can't get
>>>> the
>>>> > actual body content - at least not as a string. In my case the file
>>>> > contains an xml document that I need to get hold of. Is this a known
>>>> bug or
>>>> > have I misunderstood the purpose with the getOriginalMessage() method?
>>>> >
>>>> > /Bengt
>>>>
>>>>
>>>>
>>>> --
>>>> Claus Ibsen
>>>> -----------------
>>>> Red Hat, Inc.
>>>> Email: [hidden email]
>>>> Twitter: davsclaus
>>>> Blog: http://davsclaus.com
>>>> Author of Camel in Action: http://www.manning.com/ibsen
>>>> Make your Camel applications look hawt, try: http://hawt.io
>>>>
>>>
>>>
>>
>
Reply | Threaded
Open this post in threaded view
|

Re: getOriginalMessage()

Bengt Rodehav
Found a workaround by accessing the type converter registry as follows:

Object body = originalMessage.getBody();
TypeConverterRegistry reg = getContext().getTypeConverterRegistry();
TypeConverter converter = reg.lookup(String.class,body.getClass());
if (converter != null) {
  String str = converter.convertTo(String.class,body);
  System.out.println("Converted: " + str);
}
else {
  System.out.println("No converter found");
}

This seems to work although I still thinks the original message handling is
a bit "fishy".

/Bengt


2014-03-12 21:00 GMT+01:00 Bengt Rodehav <[hidden email]>:

> BTW, while debugging I noticed another difference between the current
> message (retrieved by the getIn() method) and the original message. When
> comparing the message headers, the original message lacks the header
> "breadcrumbId". This probably isn't related but it seems strange that it is
> omitted.
>
> Note that the value of "breadcrumbId" seems to be the same as the
> messageId which in turn is the same for the current message and the
> original message.
>
> /Bengt
>
>
> 2014-03-12 20:49 GMT+01:00 Bengt Rodehav <[hidden email]>:
>
> I've now done some debugging to see what actually happens. It turns out
>> that both the variable "message" and the variable "originalMessage" are of
>> type GenericFileMessage. It turns out that the "message" has an exchange
>> set to its "exchange" property while the "originalMessage" does not (i e
>> originalMessage.getExchange() returns null).
>>
>> This makes all the difference when looking at the base class
>> "MessageSupport". The type conversion ends up in the method
>> MessageSupport.getBody() method and it looks like this:
>>
>>     protected <T> T getBody(Class<T> type, Object body) {
>>         // eager same instance type test to avoid the overhead of
>> invoking the type converter
>>         // if already same type
>>         if (type.isInstance(body)) {
>>             return type.cast(body);
>>         }
>>
>>         Exchange e = getExchange();
>>         if (e != null) {
>>             TypeConverter converter = e.getContext().getTypeConverter();
>>
>>             // lets first try converting the body itself first
>>             // as for some types like InputStream v Reader its more
>> efficient to do the transformation
>>             // from the body itself as its got efficient implementations
>> of them, before trying the message
>>             T answer = converter.convertTo(type, e, body);
>>             if (answer != null) {
>>                 return answer;
>>             }
>>
>>             // fallback and try the message itself (e.g. used in
>> camel-http)
>>             answer = converter.tryConvertTo(type, e, this);
>>             if (answer != null) {
>>                 return answer;
>>             }
>>         }
>>
>>         // not possible to convert
>>         return null;
>>     }
>>
>> Thus, since now exchange is attached to the message this method always
>> returns null.
>>
>> If I change my code snippet to:
>>
>> ...
>> Message originalMessage =
>> theExchange.getUnitOfWork().getOriginalInMessage();
>> GenericFileMessage gfm =
>> (GenericFileMessage)originalMessage;gfm.setExchange(theExchange);
>> ...
>>
>> Then everything works. However, this is not a possible workaround for me.
>> I need this code to be generic and I can only access the Message interface.
>>
>> I'm not sure if it's by design that the originalMessage is not attached
>> to an exchange or not. I guess it could be. But then how can I, in a
>> generic way, convert the body to a string?
>>
>> /Bengt
>>
>>
>>
>> 2014-03-12 19:06 GMT+01:00 Bengt Rodehav <[hidden email]>:
>>
>> I did the following:
>>>
>>> - Downloaded the zip file for Camel 2.12.3 (binary distribution)
>>>
>>> - Added two java files to the example project "camel-example-ftp". The
>>> files are called MyFileClient.java and MyFileClientRouteBuilder.java. Their
>>> contents is embedded at the end of this mail.
>>>
>>> - I started MyFileClient and dropped a file in the "target/in" directory.
>>>
>>> - I get the exact same result as I described in my earlier post. I
>>> cannot access the body contents of the original message.
>>>
>>> Is this as designed or is it a bug (or have I misunderstood)?
>>>
>>> /Bengt
>>>
>>> *MyFileClient.java*
>>> package org.apache.camel.example.ftp;
>>>
>>> import org.apache.camel.main.Main;
>>>
>>> public final class MyFileClient {
>>>
>>> private MyFileClient() {
>>>  }
>>>
>>> public static void main(String[] args) throws Exception {
>>> Main main = new Main();
>>>  main.addRouteBuilder(new MyFileClientRouteBuilder());
>>> main.enableHangupSupport();
>>> main.run();
>>>  }
>>> }
>>>
>>>
>>> *MyFileClientRouteBuilder.java*
>>> package org.apache.camel.example.ftp;
>>>
>>> import org.apache.camel.Exchange;
>>> import org.apache.camel.Message;
>>> import org.apache.camel.Processor;
>>> import org.apache.camel.builder.RouteBuilder;
>>>
>>> public class MyFileClientRouteBuilder extends RouteBuilder {
>>>
>>> @Override
>>> public void configure() throws Exception {
>>> // lets shutdown faster in case of in-flight messages stack up
>>>  getContext().getShutdownStrategy().setTimeout(10);
>>>
>>> from("file:target/in").streamCaching().process(new Processor() {
>>>    public void process(Exchange theExchange) {
>>>   Message originalMessage =
>>> theExchange.getUnitOfWork().getOriginalInMessage();
>>>   System.out.println("Original message: " + originalMessage);
>>>   System.out.println("Original body: " + originalMessage.getBody());
>>>   System.out.println("Original body as string: " +
>>> originalMessage.getBody(String.class));
>>>
>>>   Message message = theExchange.getIn();
>>>   System.out.println("Message: " + message);
>>>   System.out.println("Body: " + message.getBody());
>>>   System.out.println("Body as string: " +
>>> message.getBody(String.class));
>>>   }
>>> });
>>>  }
>>> }
>>>
>>>
>>>
>>> 2014-03-12 16:51 GMT+01:00 Bengt Rodehav <[hidden email]>:
>>>
>>> Thanks for your reply Claus.
>>>>
>>>> I changed my code to:
>>>>
>>>> from("file:in").streamcaching().process(new Processor() {
>>>>   public void process(Exchange theExchange) {
>>>>   Message originalMessage =
>>>> theExchange.getUnitOfWork().getOriginalInMessage();
>>>>   System.out.println(originalMessage); // 1
>>>>   System.out.println("Body: " + originalMessage.getBody()); // 2
>>>>   System.out.println("Body as string: " +
>>>> originalMessage.getBody(String.class)); // 3
>>>>   }
>>>> });
>>>>
>>>> Unfortunately this makes no difference - I get the same result.
>>>>
>>>> Also, if I skip Step #2 above I still get "Body as string: null"  at
>>>> step #3 so I don't think I'm reeading the body twice.
>>>>
>>>> /Bengt
>>>>
>>>>
>>>>
>>>> 2014-03-12 16:34 GMT+01:00 Claus Ibsen <[hidden email]>:
>>>>
>>>> Hi
>>>>>
>>>>> No its streams playing tricks on you
>>>>> http://camel.apache.org/why-is-my-message-body-empty.html
>>>>>
>>>>> So you get the body 2 times (at #2 and #3) and the 2nd time its empty.
>>>>>
>>>>> On Wed, Mar 12, 2014 at 4:29 PM, Bengt Rodehav <[hidden email]>
>>>>> wrote:
>>>>> > I'm using Camel 2.12.1.
>>>>> >
>>>>> > For error handling purposes I need access to the original message
>>>>> but I'm
>>>>> > having problems with that.
>>>>> >
>>>>> > In my error handler I do this:
>>>>> >
>>>>> >   Message originalMessage =
>>>>> > theExchange.getUnitOfWork().getOriginalInMessage();
>>>>> >   System.out.println(originalMessage); // 1
>>>>> >   System.out.println("Body: " + originalMessage.getBody()); // 2
>>>>> >   System.out.println("Body as string: " +
>>>>> > originalMessage.getBody(String.class)); // 3
>>>>> >
>>>>> > The output at "1" is:
>>>>> >
>>>>> > TradeSet.xml
>>>>> >
>>>>> > The output at "2" is:
>>>>> >
>>>>> > Body:
>>>>> >
>>>>> GenericFile[C:\dev\karaf\connect-sts\head\apache-karaf2.3.4\bin\..\..\..\common\data\interfaces\ts2so\TradeSet.xml]
>>>>> >
>>>>> > The output at "3" is:
>>>>> >
>>>>> > Body as string: null
>>>>> >
>>>>> > I can reproduce this problem with a simple route that just uses the
>>>>> file
>>>>> > component. Something like this:
>>>>> >
>>>>> > from("file:in").process(new Processor() {
>>>>> >   public void process(Exchange theExchange) {
>>>>> >   Message originalMessage =
>>>>> > theExchange.getUnitOfWork().getOriginalInMessage();
>>>>> >   System.out.println(originalMessage); // 1
>>>>> >   System.out.println("Body: " + originalMessage.getBody()); // 2
>>>>> >   System.out.println("Body as string: " +
>>>>> > originalMessage.getBody(String.class)); // 3
>>>>> >   }
>>>>> > });
>>>>> >
>>>>> >
>>>>> > Thus it seems like I can access the original message but I can't get
>>>>> the
>>>>> > actual body content - at least not as a string. In my case the file
>>>>> > contains an xml document that I need to get hold of. Is this a known
>>>>> bug or
>>>>> > have I misunderstood the purpose with the getOriginalMessage()
>>>>> method?
>>>>> >
>>>>> > /Bengt
>>>>>
>>>>>
>>>>>
>>>>> --
>>>>> Claus Ibsen
>>>>> -----------------
>>>>> Red Hat, Inc.
>>>>> Email: [hidden email]
>>>>> Twitter: davsclaus
>>>>> Blog: http://davsclaus.com
>>>>> Author of Camel in Action: http://www.manning.com/ibsen
>>>>> Make your Camel applications look hawt, try: http://hawt.io
>>>>>
>>>>
>>>>
>>>
>>
>