On Tue Oct 11 23:20:05 2011, Bernd Fischer wrote:
Hi all together,

during playing around with Camel I found an use case for which I like
to ask the "experts" for some advice.

I'm using Camel 2.8.0 with spring 3.0.5 on java 1.6 in a multi Camel
Context unit test scenario (one for simulating client and one for
server).

For uri's like

<to uri="bean:processor?method=process"/>

Camel usually resolves beans during creation of endpoints. This way
Camel Context from endpoint, which points to Spring application
context containing bean definition, is used. This works well.

The splitter component can use a "split method" with similar "syntax".

       <split>
         <method bean   ="stringLineSplitter" method="split"/>
         <log    message="before sending: ${body}"/>
         <inOut  uri    ="vm:route04"/>
         <log    message="after sending"/>
       </split>

It seems that this "split bean" is resolved using Camel Context from exchange.

If I send an exchange using client Camel Context, please remember I'm
using two Camel Contexts, to a route defined in server Camel Context
using in-memory transport like "direct" or "vm"

     <route id="route02" trace="false" streamCache="false">
       <from uri="vm:route02"/>
       <split>
         <method bean   ="stringLineSplitter" method="split"/>
         <log    message="before sending: ${body}"/>
         <inOut  uri    ="vm:route04"/>
         <log    message="after sending"/>
       </split>
       <to uri="mock:route02"/>
     </route>

the test fails with "Cannot find class: stringLineSplitter" thrown
from a class "ObjectHelper". If I understood Camel right it fails
because it tries to resolve this bean based on client Camel Context
which is still set at the exchange send from client to server but
doesn't contain the bean.

If I send an exchange using same client Camel Context to a route in
server Camel Context involving "external" components like "jms"
(ActiveMQ)

     <route id="route03" trace="false" streamCache="false">
       <from uri="jms:queue:route03"/>
       <split>
         <method bean   ="stringLineSplitter" method="split"/>
         <log    message="before sending: ${body}"/>
         <inOut  uri    ="vm:route04"/>
         <log    message="after sending"/>
       </split>
       <to uri="mock:route03"/>
     </route>

the test passed successfully. It seems that "jms" component creates a
new exchange but "vm" reuses the one from internal queue.

After diving into the code I found a place to adjust this behavior.
Changing one line in the else-clause of

class org.apache.camel.model.language.MethodCallExpression

method

createExpression( CamelContext camelContext ) : Expression

from

answer = new BeanExpression( ref1, getMethod() );

to

answer = new BeanExpression( this.instance, getMethod() );

did the trick (means: now all my tests passed successfully).
In the code lines before the bean holder was already created but in
original version not used.

I just checked the code on the trunk and can't exactly the change that you made, can provide a diff file for it ?


Now my questions:

1. Is it right to expect that both use cases should behave similar?
I'm not sure how can you get the bean instance without looking up by using the reference name.
2. Shouldn't every component create a new exchange during
receiving/consuming, minimally re-set Camel Context if it crosses
borders?
I think we can reset the camel context on the exchange when the VM endpoint consume it, and it would not change
3, Is the proposed change correct or will it produce (unwanted) side effects?
4. If change is ok could it be part of Camel?
Could you create a JIRA and submit a simple testcase with your patch?
It will be helpful for us to put this fix into the feature release of Camel.


Any help/comment/hint are highly welcome.

Best Regards
Bernd



--
Willem
----------------------------------
FuseSource
Web: http://www.fusesource.com
Blog:    http://willemjiang.blogspot.com (English)
         http://jnn.javaeye.com (Chinese)
Twitter: willemjiang
Weibo: willemjiang

Reply via email to