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 <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