camel-dev mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From James Strachan <>
Subject Re: [DISCUSS] Semantics of IN and OUT (was: Faults and Exceptions in Camel)
Date Fri, 10 Jul 2009 15:16:36 GMT
2009/7/10 Hadrian Zbarcea <>:
> Moved this slightly different topic to a separate thread.
> ++1 from me.
> Do we need a vote on this one or it's a consensus?  Claus, it looks like you
> agree, but pointed out that there is some work involved, correct?
> Hadrian
> On Jul 10, 2009, at 8:40 AM, James Strachan wrote:
>> 2009/7/10 Claus Ibsen <>:
>>> On Fri, Jul 10, 2009 at 1:20 PM, James Strachan<>
>>> wrote:
>>>> 2009/7/10 Claus Ibsen <>:
>>>>> Hi
>>>>> Another update on the IN vs OUT when you send in an Exchange.
>>>>> The ProducerCache that is doing the actual sending when using template
>>>>> or sendTo etc, its basically doing all send X to endpoint.
>>>>> Well I am playing with to let it adhere to the principle Hadrian
>>>>> pointed out. He wanted the IN to be more static.
>>>>> And we cannot get there yet when you do routing as all the processors
>>>>> rely on IN being able to mutate during routing.
>>>>> Anyway my grief is that when you send in an Exchange the result would
>>>>> sometimes be stored on IN and not OUT.
>>>>> What I want it to do always is to store the result in OUT and keep IN
>>>>> as the original input.
>>>>> The code to do this is now a bit more complex than just before
>>>>>               // copy the original input
>>>>>               Message original = exchange.getIn().copy();
>>>>>               producer.process(exchange);
>>>>>               // if no OUT then set current IN as result (except
>>>>> optional out)
>>>>>               if (!exchange.hasOut() && exchange.getPattern()
>>>>> ExchangePattern.InOptionalOut) {
>>>>>                   // but only if its not the same as original
IN to
>>>>> avoid duplicating it
>>>>>                   // and to adhere to the fact that there was
no OUT
>>>>> result at all
>>>>>                   if (original.getBody() != null &&
>>>>> !original.getBody().equals(exchange.getIn().getBody())) {
>>>>>                       exchange.setOut(exchange.getIn());
>>>>>                   }
>>>>>               }
>>>>>               // and restore original in
>>>>>               exchange.setIn(original);
>>>>>               return exchange;
>>>>> What I need to do is to copy the original IN message as it can be
>>>>> mutated during routing.
>>>> How about we prevent mutation of the IN message? Create a Message
>>>> facade which throws UnsupportedOperationException if you try to mutate
>>>> it in any way. Then we can pass the same read-only Message around as
>>>> the IN within retry loops or from step to step if no new output is
>>>> created (e.g. in a content based router where you just move a Message
>>>> to the right endpoint without changing it)
>>> A good idea but will break a lot of logic in Camel.
>> Agreed. But with the benefit that we'd be able to get rid of all the
>> defensive copies in our code; plus we'd be able to pass the same
>> Message from step to step. The API would be a bit more clean; to
>> change the output, you create an OUT message (maybe by copying the
>> IN).
>>> Most of the Camel
>>> processors work on the IN message and set the result on either IN or
>>> OUT. At best they set it on OUT. But then the IN is always the
>>> original input? Or am I mistaking?
>> Yeah, we'd have to patch code to no longer mutate IN
>>> How will this work with the Pipes And Filters EIP if the IN is
>>> immutable and always the original input?
>> If no OUT, then no output was created, so pass the IN along...
>> OK how about this; a CopyOnWriteMessageFacade which does not mutate
>> the original message at all ever; if a message is used in a purely
>> read only way, it does nothing but delegate to the original message -
>> but then as soon as someone mutates it, it creates a copy and uses
>> that from that point on?
>> i.e. make the copy of the message lazy - and only make a copy when a
>> Processor really does try to mutate the Message?
>> Then we'd get the best of both worlds; avoid breaking old code but
>> avoid tons of unnecessary copies?

BTW then using the current API you could have a Message and then call

Message origin = ...;
Message newMsg = origin.copy().copy().copy().copy();

and the message would not actually be copied at all; new would just be
a CopyOnWriteMessageFacade which would hold a reference to 'origin' as
the readOnlyMessage (which it never mutates).

The copy would only take place if you did



Open Source Integration

View raw message