camel-dev mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From Claus Ibsen <claus.ib...@gmail.com>
Subject Re: [DISCUSS] Semantics of IN and OUT (was: Faults and Exceptions in Camel)
Date Mon, 13 Jul 2009 16:50:02 GMT
On Mon, Jul 13, 2009 at 6:33 PM, James Strachan<james.strachan@gmail.com> wrote:
> 2009/7/13 Claus Ibsen <claus.ibsen@gmail.com>:
>> On Mon, Jul 13, 2009 at 5:50 PM, James Strachan<james.strachan@gmail.com> wrote:
>>> I'm confused. So rather than calling Exchange.getIn() to get the IN,
>>> you'd have to do Exchange.getUnitOfWork().somethingOrOther() to get
>>> the last IN? I don't see that as any simpler; making one of the 2
>>> messages harder to find, just moves the confusion somewhere else?
>>
>> Having access to the original input in a route path is very rarely
>> requested by end users.
>> In fact I think its even more confused if getIN always returned the
>> original input. (what should that be if a message is routed over (to
>> seda/from seda) a seda endpoint?)
>>
>> So what I am saying is that we should have a model similar to Mule and
>> Spring Integration = simpler and easier to understand and use.
>> And also simpler and easier to use within the Camel framework itself -
>> eg all the code that copies from IN to OUT and OUT to IN and whatnot.
>>
>> The last IN = the message itself.
>>
>> Given this route:
>> from("direct:start").to("bean:foo").processRef("bar").transform(constant("Bye
>> World")).processRef("me");
>>
>> And we send a "Hello World" message to direct:start. The message would be
>>
>> bean:foo
>> getMessage = "Hello World
>>
>> bar
>> getMessage = "Hello World
>>
>> me
>> getMessage = "Bye World
>>
>>
>> Now imagine we mutate the messages in bean foo
>> public String reverse(String s) {
>>   // return the reversed string
>> }
>
> am confused; a bean never even sees an Exchange/Message typically?
>
>> bean:foo
>> getMessage = "Hello World"
>>
>> bar
>> getMessage = "dlroW olleH"
>>
>> me
>> getMessage = "Bye World"
>>
>>
>> No more IN vs OUT and other confusing bits. getMessage gets you the
>> payload as it is.
>
> I dunnot what 'it' is? You mean we always copy the IN to the OUT
> regardless of what the code does just in case; so you mutate the
> current message - then if you zap headers/body you have to keep a
> track of them yourself in case you want to look at them again?
>

The current code in Camel makes it very easy for Camel to zap your
headers unintended.

Lets look at how it is today.

1:
IN = At the very first consumer its the original input (= good)

IN Body = Hello World
OUT = null

2:
Then the pipeline kicks in and invokes the next processor with the Exchange

Lets say this processor does some work on the exchange, it want to set
a new payload
Today you can set this payload in either IN or OUT, eg your choice.

Lets start with IN (see 3a)
exchange.getIn().setBody("I did this")

And try OUT instead (see 3b)
exchange.getOut().setBody("I also did this")


3a:
The pipeline still routes it and lets send it to a final destination,
a file producer that writes the content as a file
IN Body = I did this
OUT = null

This is lucky as the file producer always uses IN body to as source
for file content so the file is: I did this


3b
The pipeline still routes it and lets send it to a final destination,
a file producer that writes the content as a file
IN Body = I also did this
OUT = I also did this

We set an OUT body but the pipeline copied it to IN so the message is
what we expect
and the file producer can use IN to write the expected file content.

But now the Exchange is a bit confusing as we got both IN and OUT = the same.
And the original IN is lost.





>
>> If you have looked as much Camel code as I have you would also flag
>> that the IN OUT is leading to confusing and broken code.
>
> Note you were the one that pushed back when I said lets make getIn()
> immutable which would break some code :). Now you're saying lets just
> break *all* camel code.
>
>
>> And trust me its broken, when you use the Exchange, but the BODY
>> extractor of ProducerTemplate is fairly good at guessing and returning
>> the right one from OUT or IN :)
>>
>>
>> If its really that inportant to get hold of the original input we can
>> add a getter to it on the Exchange.
>> - getInputMessage()
>> - getOriginalMessage()
>> or what a good name would be.
>
> but this is exactly why we were talking about having getIn() and
> getOut(). Out is the output, the thing the processor/component
> mutates/generates. IN is just the immutable view of what was sent in.
>

The current model in Camel is IN not a immutable view. It can be
mutated as well, and this is actually essential that its done
as all the Camel processors rely on this that IN contains = the
current message. (and not what the original input is when the message
was consumed)

If we go by your suggestions.
1) All Camel code must be adapter to use OUT instead of IN as = the
current message. And eg fallback to IN if no OUT have been set
2) End users from Camel 1.x that are familiar with the (odd) IN and
OUT would have their code breaked and cannot understand why

3) So to make all aware that IN and OUT have changed we simply do not
have them anymore, or have them @deprecated.


>
>> And on top of this we do not lose headers as we do now when people use
>> a processor and do
>> exchange.getOut().setBody(myBody);
>>
>> And then all the headers from IN is lost.
>
> On this point aren't you confusing bugs in current implementation
> methods (like getOut()) with letting folks access the IN message while
> creating an OUT?
>
> As an experiment; could you mock up what the cxf and JBi components
> would look like having no getIn() and just having a getMessage() on
> Exchange? e.g. how would we map our code to CXF/JBI which require a
> separate IN and OUT?
>

Yeah these frameworks could require a bit more work. However we got a
camel-cxf and ca camel-jbi component where such logic can be
implemented.
If CXF can work with Mule or Spring Integration (they do not have
IN/OUT) why can it not work with Camel also?



> Or rather; if getOut() => getMessage() and we let folks see the
> immutable version of the original message - on a method called, say,
> getIn() - then isn't this what I was proposing last week; make getIn()
> immutable as the record of what was sent in then all
> mutation/modifications occur on getOut().
>
> Note I'm not 100% against any radical API change - I just want to make
> sure we're doing it for the right reasons.
>

It was in fact Hadrian that got the ball rolling. We where close to
close the lid and get 2.0 out.
However his proposal with FAULT -> OUT is good, but FAULT is not often
used anyway so the impact is not big.



> --
> James
> -------
> http://macstrac.blogspot.com/
>
> Open Source Integration
> http://fusesource.com/
>



-- 
Claus Ibsen
Apache Camel Committer

Open Source Integration: http://fusesource.com
Blog: http://davsclaus.blogspot.com/
Twitter: http://twitter.com/davsclaus

Mime
View raw message