| [[UsinggetInorgetOutmethodsonExchange-MessageexchangepatternsandtheExchangeobject]] |
| = Message Exchange Patterns and the Exchange object |
| |
| The Camel API is influenced by APIs such as |
| http://en.wikipedia.org/wiki/Java_Business_Integration[JBI specification], |
| http://cxf.apache.org/[CXF] which defines a concept |
| called Message Exchange Patterns (MEP for short). |
| |
| The MEP defines the messaging style used such as one-way |
| (xref:{eip-vc}:eips:event-message.adoc[InOnly]) or request-reply |
| (xref:{eip-vc}:eips:request-reply.adoc[InOut]), |
| which means you have IN and optionally OUT messages. This closely maps |
| to other APIs such as WS, WSDL, REST, JBI and the likes. |
| |
| The xref:ROOT:exchange.adoc[Exchange] API provides two methods to get a |
| message, either `getIn` or `getOut`. |
| Obviously the `getIn` gets the IN message, and the `getOut` gets the OUT |
| message. |
| |
| [[UsinggetInorgetOutmethodsonExchange-Flowofanexchangethrougharoute]] |
| == Flow of an exchange through a route |
| |
| image::message_flow_in_route.png[image] |
| |
| * The out message from each step is used as the in message for the next |
| step |
| * if there is no out message then the in message is used instead |
| * For the InOut MEP the out from the last step in the route is returned |
| to the producer. In case of InOnly the last out is thrown away |
| |
| [TIP] |
| ==== |
| **Beware of `getOut` to check if there is an out message** |
| |
| `exchange.getOut` creates an out message if there is none. So if you want |
| to check if there is an out message then you should use `exchange.hasOut` |
| instead. |
| ==== |
| |
| [[UsinggetInorgetOutmethodsonExchange-UsinggetInorgetOutmethodsonExchange]] |
| == Using getIn or getOut methods on Exchange |
| |
| Now suppose you want to use a Camel xref:ROOT:processor.adoc[Processor] to |
| adjust a message. This can be done as follows: |
| |
| [source,java] |
| ---- |
| public void process(Exchange exchange) throws Exception { |
| String body = exchange.getIn().getBody(String.class); |
| // change the message to say Hello |
| exchange.getOut().setBody("Hello " + body); |
| } |
| ---- |
| |
| This seems intuitive and is what you would expect is the _right_ |
| approach to change a message from a xref:ROOT:processor.adoc[Processor]. |
| However there is an big issue -- the `getOut` method will create a new |
| xref:{eip-vc}:eips:message.adoc[Message], which means any other information |
| from the IN message will not be propagated; which means you will lose |
| that data. |
| |
| To remedy this we'll have to copy the data which is done as follows: |
| |
| [source,java] |
| ---- |
| public void process(Exchange exchange) throws Exception { |
| String body = exchange.getIn().getBody(String.class); |
| // change the message to say Hello |
| exchange.getOut().setBody("Hello " + body); |
| // copy headers from IN to OUT to propagate them |
| exchange.getOut().setHeaders(exchange.getIn().getHeaders()); |
| } |
| ---- |
| |
| Well that is not all, a xref:{eip-vc}:eips:message.adoc[Message] can also contain |
| attachments so to be sure you need to propagate those as well: |
| |
| [source,java] |
| ---- |
| public void process(Exchange exchange) throws Exception { |
| String body = exchange.getIn().getBody(String.class); |
| // change the message to say Hello |
| exchange.getOut().setBody("Hello " + body); |
| // copy headers from IN to OUT to propagate them |
| exchange.getOut().setHeaders(exchange.getIn().getHeaders(); |
| // copy attachements from IN to OUT to propagate them |
| exchange.getOut().setAttachments(exchange.getIn().getAttachments()); |
| } |
| ---- |
| |
| Now we ensure that all additional data is propagated on the new OUT |
| message. But its a shame we need 2 code lines to ensure data is |
| propagated. |
| What you can do instead is to change the IN message instead, as shown |
| below: |
| |
| [source,java] |
| ---- |
| public void process(Exchange exchange) throws Exception { |
| String body = exchange.getIn().getBody(String.class); |
| // change the existing message to say Hello |
| exchange.getIn().setBody("Hello " + body); |
| } |
| ---- |
| |
| [TIP] |
| ==== |
| **Consider using getIn** |
| |
| As shown above you most often need to alter the existing IN message, |
| than creating a totally new OUT message. |
| And therefore it's often easier just to adjust the IN message directly. |
| ==== |
| |
| Changing the IN message directly is possible in Camel as it doesn't |
| mind. Camel will detect that the xref:ROOT:exchange.adoc[Exchange] has no OUT |
| message and therefore use the IN message instead. |
| |
| [[UsinggetInorgetOutmethodsonExchange-AboutMessageExchangePatternandgetOut]] |
| == About Message Exchange Pattern and getOut |
| |
| If the xref:ROOT:exchange.adoc[Exchange] is using `InOnly` as the MEP, then |
| you may think that the xref:ROOT:exchange.adoc[Exchange] has no OUT |
| message. But you can still invoke the `getOut` method on |
| xref:ROOT:exchange.adoc[Exchange]; Camel will not barf. |
| |
| So the example code above is possible for any kind of MEP. The MEP is |
| _just_ a flag on the xref:ROOT:exchange.adoc[Exchange] which the Consumer and |
| Producer adhere to. |
| You can change the MEP on the xref:ROOT:exchange.adoc[Exchange] using the |
| `setPattern` method. And likewise there is DSL to change it as well. |