camel-dev mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From Roman Kalukiewicz <roman.kalukiew...@gmail.com>
Subject Re: [DISCUSS] Semantics of IN and OUT (was: Faults and Exceptions in Camel)
Date Tue, 14 Jul 2009 09:50:51 GMT
2009/7/14 James Strachan <james.strachan@gmail.com>:
> 2009/7/13 Claus Ibsen <claus.ibsen@gmail.com>:
>>>
>>> Reading between the lines; are you really just trying to make folks
>>> use (what is currently called) "getOut()" and never try mutate what is
>>> currently called getIn()?
>>>
>>> i.e. so by default the "OUT" property is defaulted to a copy of IN
>>> that folks can change/mutate.
>>>
>>> (what we call these 2 methods is a separate discussion, whether its
>>> "in,out" or "originalMessage,message" or whatever
>>>
>>
>> Hadrian and I had a chat today and we are clearing up some bits.
>> I am more on line with him now on the IN and OUT thing.
>>
>> So lets keep them.
>>
>> And use the time to fix the tiny bits such as the getOut() doing its
>> lazy creating a new empty message.
>> And whether its possible to let IN be immutable.
>
> I think we're kinda mostly on the same page (though saying it in
> different ways). BTW I'm taking off my devils advocate hat now :)...
>
> What we're agreeing on I think is that;
>
> * getIn() should be immutable (when folks try to change it we can
> throw the exception and describe how getOut() should be used to change
> the message) - to prevent folks using the old code (which will require
> code changes).

Definitely agree.

> * having the original immutable message available is handy; but mostly
> folks should concentrate on the 'out' (current name today)

It is handy.But the question is if we should add another message while
both client and processor implementor can store original message (body
or headers he wants) in a variable if they only want to store them. Do
we have to store those things for them no mater if they need it or
not? This comment applies only if we want to have IN message on
processor level (every processor receives its new IN message).

I personally don't see a huge difference between:
Object oldBody = exchange.getMessage().getBody();
template.send(exchange);
Object newBody = exchange.getMessage.getBody();

and
template.send(exchange);
Object oldBody = exchange.getOriginalMessage().getBody();
Object newBody = exchange.getMessage().getBody();

while the second one complicates an API by having additional method on
the exchange.

> * the out should be automatically populated with a clone of the IN (to
> avoid all that pain with checking if there's an out or an in, or the
> possible loss of headers etc. Internally we can use a CopyOnWrite
> facade to reduce the cost of potentially copying a message which is
> not actually mutated.

True

> Given that; I think we're mostly agreeing. However given the confusion
> of getIn() and getOut() I'm wondering if actually your previous idea
> of changing the api of exchange to have a getMessage() which returns
> the thing a processor should be changing; then having a
> getOriginalMessage() (which can be null if you are the first in the
> chain) might reduce the amount of confusion?

Because of previous comment about IN messages I believe that maybe we
should have getOriginalMessage() that returns an original message as
JMS Message, JBI Exchange and so on. This assures that users can
always reach full information they received. It would look like
from("jms:q1")  // Original message contains JMS message received
.transform(expression) // Still original JMS message - no endpoint involved
.setHeader("foo", expression) // Still original JMS message - still I
can reach some JMS specific things
.to("jbi:service") // Now I have JBI exchange in original message
.bean(myBean) // My Bean reaches exchange directly to reach some stuff
from ServiceMix specific JBI exchange
.to("jms:q2") // JMS response message in original message
.to("direct:end") // Camel Exchange in original message as it is now
endpoint specific type
.to("seda:foo") // InOnly operation. I'm not sure if it should be null
in original message, or maybe nothing modified.

I propose it because I don't really like our custom Message
subclasses. They tend to mirror Camel message model and some
underlying technology's model. But sometimes they are not compatible
really and strange things happen. But maybe this is the discussion for
another thread?

> i.e. after sleeping on it, I'm warming to the idea of renaming getIn()
> -> getOriginalMessage() and getOut() -> getMessage(). (Or maybe
> getInputMessage() for getIn()?)
>
> Thoughts?

I definitely agree that for the moment we can add those methods,
deprecate getIn()/getOut() and let them simply return getMessage().

To summarize my ideal model is (helpers like getBody(Class) omitted):
CamelMessage
Object get/setBody() //obvious
Map<String, Object> getHeaders() // for technology specific headers
received/sent
Map<String, Object> getProperties() // for business specific
information that is generally not touched by endpoints - user can
store there any information he wants to be sent through the flow and
not be lost at the endpoint
Object get/setOriginalMessage() // For technology specific message
representation like JMS Message/JBI Exchange
Exception get/setException() // For exception handling
boolean is/setFault() // For business fault detection

In a model where only one message exists, exchange is not even needed.

Heh - I feel guilty for enlisting all those things now while it looks
that an agreement on API changes exists ;)
Maybe a proposal for 2.1? ;)

Roman

Mime
View raw message