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 <[email protected]>:
> 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 <[email protected]>:
>
> 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 <[email protected]>:
>>
>> 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 <[email protected]>
>>> 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: [email protected]
>>> 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
>>>
>>
>>
>