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/