2009/7/10 Claus Ibsen <claus.ib...@gmail.com>:
> On Fri, Jul 10, 2009 at 1:20 PM, James Strachan<james.strac...@gmail.com> 
> wrote:
>> 2009/7/10 Claus Ibsen <claus.ib...@gmail.com>:
>>> 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 for
>>> 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?

-- 
James
-------
http://macstrac.blogspot.com/

Open Source Integration
http://fusesource.com/

Reply via email to