You are viewing a plain text version of this content. The canonical link for it is here.
Posted to users@camel.apache.org by jduncan <jd...@iqnavigator.com> on 2013/07/29 23:20:12 UTC

Camel route only dealing with headers

I have a route that listens on an ActiveMQ endpoint and only manipulates
exchange headers.  I don't care about the body of the exchange at all. 
Consequently, I don't want to have to
marshal/unmarshal/serialize/deserialize the body at all, but just send it
along to anything downstream.  Particularly, I don't want to try and
deserialize object messages in case I do not have the serialized class in my
classpath.  I have tried adding the mapJmsMessage=false property to my AMQ
consumer, but when I do that a null body gets passed to any downstream
routes.

How can I pass along the original body without touching it at all?

Thanks!
Jared



--
View this message in context: http://camel.465427.n5.nabble.com/Camel-route-only-dealing-with-headers-tp5736452.html
Sent from the Camel - Users mailing list archive at Nabble.com.

Re: Camel route only dealing with headers

Posted by Christian Posta <ch...@gmail.com>.
You may wish to take a look at 'forceSendOriginalMessage' on the camel jms
endpoint... eg:

For example, the following does what you're asking:

from("jms:incoming?mapJmsMessage=false").to("jms:outgoing?forceSendOriginalMessage=true");

May have to play with the config a bit if you have other parts of your
route that manipulates headers, but check to docs and you should be good to
go:

http://camel.apache.org/jms.html


On Mon, Jul 29, 2013 at 3:00 PM, Christian Posta
<ch...@gmail.com>wrote:

> Object message is not a very good way to send payload for various reasons.
>
> Is your use case constrained to scenarios where ObjectMessages are being
> used and cannot be changed? The more versatile choice would otherwise be
> BytesMessage.
>
>
>
>
> On Mon, Jul 29, 2013 at 2:20 PM, jduncan <jd...@iqnavigator.com> wrote:
>
>> I have a route that listens on an ActiveMQ endpoint and only manipulates
>> exchange headers.  I don't care about the body of the exchange at all.
>> Consequently, I don't want to have to
>> marshal/unmarshal/serialize/deserialize the body at all, but just send it
>> along to anything downstream.  Particularly, I don't want to try and
>> deserialize object messages in case I do not have the serialized class in
>> my
>> classpath.  I have tried adding the mapJmsMessage=false property to my AMQ
>> consumer, but when I do that a null body gets passed to any downstream
>> routes.
>>
>> How can I pass along the original body without touching it at all?
>>
>> Thanks!
>> Jared
>>
>>
>>
>> --
>> View this message in context:
>> http://camel.465427.n5.nabble.com/Camel-route-only-dealing-with-headers-tp5736452.html
>> Sent from the Camel - Users mailing list archive at Nabble.com.
>>
>
>
>
> --
> *Christian Posta*
> http://www.christianposta.com/blog
> twitter: @christianposta
>



-- 
*Christian Posta*
http://www.christianposta.com/blog
twitter: @christianposta

Re: Camel route only dealing with headers

Posted by Raul Kripalani <ra...@evosent.com>.
I've quickly skimmed over the relevant source in camel-jms. It looks like
Camel reads the message body lazily, only when required. So
ObjectMessage.getObject() will only be called when the body is actually
required. In AMQ, this is the method that performs the deserialization and
would hypothetically fail with a ClassNotFoundException. So you want to
avoid calling this method by all means ;-)

Bad news is that, even if you don't explicitly read the body in your route,
Camel does manipulate the Exchange under the surface in a way that the
original body may be read at some point. Particularly when dispatching to
your ending JMS producer, where the original body should be sent.

However, there are good news if (a) your consumers can afford processing
BytesMessages instead of ObjectMessages, and (b) you don't mind coupling
your solution to AMQ (which you shouldn't mind doing – as your use case is
quite extraordinary). In that case, create a custom JmsBinding that
overrides the extractBodyFromJms method, and replaces the logic to read the
body from an ObjectMessage.

Instead of deserializing the object, you want to fetch the underlying
byte[]. To do this, cast the message to ActiveMQObjectMessage and call
storeContent() to slurp in the underlying byte[] into memory. Then call
getContent() which returns an AMQ ByteSequence. From this object you can
get access to the underlying byte[].

Quite a hack, but I would give it a shot if I were you ;-)

Regards,

*Raúl Kripalani*
Apache Camel PMC Member & Committer | Enterprise Architect, Open Source
Integration specialist
http://about.me/raulkripalani | http://www.linkedin.com/in/raulkripalani
http://blog.raulkr.net | twitter: @raulvk

On Tue, Jul 30, 2013 at 3:44 PM, jduncan <jd...@iqnavigator.com> wrote:

> Actually that also does not work for object messages.  Camel will still try
> to deserialize the object in the body.
>
>
>
> --
> View this message in context:
> http://camel.465427.n5.nabble.com/Camel-route-only-dealing-with-headers-tp5736452p5736502.html
> Sent from the Camel - Users mailing list archive at Nabble.com.
>

Re: Camel route only dealing with headers

Posted by Christian Posta <ch...@gmail.com>.
The snippet as i posted works as you've asked.

Like I said, if you have other steps, you'll have to consider the spots
where Camel expects to convert the message to an exchange body.

Calling JmsMessage#getBody will cause the JmsBinding to kick in and try to
convert. If you have mapJmsMessage=false, then it won't be mapped:

from JmsBinding#extractBodyFromJms:

            // if we are configured to not map the jms message then return
it as body
            if (endpoint != null &&
!endpoint.getConfiguration().isMapJmsMessage()) {
                LOG.trace("Option map JMS message is false so using JMS
message as body: {}", message);
                return message;
            }

This means there should be no deserializing.

On the other end where you try to send the message, you want to make sure
Camel doesn't try to convert the original message (or serialize it) and
just pass it along:


from JmsBinding#makeJmsMessage:

            if (!jmsMessage.shouldCreateNewMessage() || force) {
                answer = jmsMessage.getJmsMessage();

                if (!force) {  <---- *we want to skip this*
                    // answer must match endpoint type
                    JmsMessageType type = endpoint != null ?
endpoint.getConfiguration().getJmsMessageType() : null;
                    if (type != null && answer != null) {
                        if (type == JmsMessageType.Text) {
                            answer = answer instanceof TextMessage ? answer
: null;
                        } else if (type == JmsMessageType.Bytes) {
                            answer = answer instanceof BytesMessage ?
answer : null;
                        } else if (type == JmsMessageType.Map) {
                            answer = answer instanceof MapMessage ? answer
: null;
                        } else if (type == JmsMessageType.Object) {
                            answer = answer instanceof ObjectMessage ?
answer : null;
                        } else if (type == JmsMessageType.Stream) {
                            answer = answer instanceof StreamMessage ?
answer : null;
                        }
                    }
                }
            }

If you want my test case, let me know and i can publish it.





On Tue, Jul 30, 2013 at 7:44 AM, jduncan <jd...@iqnavigator.com> wrote:

> Actually that also does not work for object messages.  Camel will still try
> to deserialize the object in the body.
>
>
>
> --
> View this message in context:
> http://camel.465427.n5.nabble.com/Camel-route-only-dealing-with-headers-tp5736452p5736502.html
> Sent from the Camel - Users mailing list archive at Nabble.com.
>



-- 
*Christian Posta*
http://www.christianposta.com/blog
twitter: @christianposta

Re: Camel route only dealing with headers

Posted by jduncan <jd...@iqnavigator.com>.
Actually that also does not work for object messages.  Camel will still try
to deserialize the object in the body.



--
View this message in context: http://camel.465427.n5.nabble.com/Camel-route-only-dealing-with-headers-tp5736452p5736502.html
Sent from the Camel - Users mailing list archive at Nabble.com.

Re: Camel route only dealing with headers

Posted by jduncan <jd...@iqnavigator.com>.
I know object messages are not the best, but there are some places in our app
that we do still use them.  I'm building a simple utility that should be
able to take any message, do some header manipulation, and then pass on the
message to another consumer.  I got my tests to pass by using
from("activemq:queue:incoming?jmsMessageType=Bytes")
I'm still doing some investigation to see if this breaks in some scenario I
don't have under test.

This utility is a home-grown version of the Routing Slip EIP.  We found
Camel's own routing slip insufficient, particularly because it does not work
when using JMS endpoints in a transactional context (because it uses the
InOut pattern).



--
View this message in context: http://camel.465427.n5.nabble.com/Camel-route-only-dealing-with-headers-tp5736452p5736491.html
Sent from the Camel - Users mailing list archive at Nabble.com.

Re: Camel route only dealing with headers

Posted by Christian Posta <ch...@gmail.com>.
Object message is not a very good way to send payload for various reasons.

Is your use case constrained to scenarios where ObjectMessages are being
used and cannot be changed? The more versatile choice would otherwise be
BytesMessage.




On Mon, Jul 29, 2013 at 2:20 PM, jduncan <jd...@iqnavigator.com> wrote:

> I have a route that listens on an ActiveMQ endpoint and only manipulates
> exchange headers.  I don't care about the body of the exchange at all.
> Consequently, I don't want to have to
> marshal/unmarshal/serialize/deserialize the body at all, but just send it
> along to anything downstream.  Particularly, I don't want to try and
> deserialize object messages in case I do not have the serialized class in
> my
> classpath.  I have tried adding the mapJmsMessage=false property to my AMQ
> consumer, but when I do that a null body gets passed to any downstream
> routes.
>
> How can I pass along the original body without touching it at all?
>
> Thanks!
> Jared
>
>
>
> --
> View this message in context:
> http://camel.465427.n5.nabble.com/Camel-route-only-dealing-with-headers-tp5736452.html
> Sent from the Camel - Users mailing list archive at Nabble.com.
>



-- 
*Christian Posta*
http://www.christianposta.com/blog
twitter: @christianposta

Re: Camel route only dealing with headers

Posted by Christian Müller <ch...@gmail.com>.
Hello Jared!

If you have to propagate the body to a downstream service, you have to care
about the body. You have to make sure the body has a format ActiveMQ can
serialize (String, byte array, map, ...). Otherwise, how should ActiveMQ be
able to send your body over the wire?

Best,
Christian
-----------------

Software Integration Specialist

Apache Camel committer: https://camel.apache.org/team
V.P. Apache Camel: https://www.apache.org/foundation/
Apache Member: https://www.apache.org/foundation/members.html

https://www.linkedin.com/pub/christian-mueller/11/551/642


On Mon, Jul 29, 2013 at 11:20 PM, jduncan <jd...@iqnavigator.com> wrote:

> I have a route that listens on an ActiveMQ endpoint and only manipulates
> exchange headers.  I don't care about the body of the exchange at all.
> Consequently, I don't want to have to
> marshal/unmarshal/serialize/deserialize the body at all, but just send it
> along to anything downstream.  Particularly, I don't want to try and
> deserialize object messages in case I do not have the serialized class in
> my
> classpath.  I have tried adding the mapJmsMessage=false property to my AMQ
> consumer, but when I do that a null body gets passed to any downstream
> routes.
>
> How can I pass along the original body without touching it at all?
>
> Thanks!
> Jared
>
>
>
> --
> View this message in context:
> http://camel.465427.n5.nabble.com/Camel-route-only-dealing-with-headers-tp5736452.html
> Sent from the Camel - Users mailing list archive at Nabble.com.
>