You are viewing a plain text version of this content. The canonical link for it is here.
Posted to users@camel.apache.org by kristofsajdak <kr...@gmail.com> on 2010/12/05 22:49:18 UTC

Re: Abstracting Routes using Components


cgiera wrote:
> 
> Hi Kristof, 
> 
> I've tried your example code(sample1) and it works fine when using camel
> 2.4.0. 
> In camel 2.5.0 it doesn't work: 
> org.apache.camel.CamelExecutionException: Exception occurred during
> execution on the exchange: Exchange[Message: [Body is instance of
> java.io.InputStream]] 
>         at
> org.apache.camel.util.ObjectHelper.wrapCamelExecutionException(ObjectHelper.java:1156) 
>         at
> org.apache.camel.util.ExchangeHelper.extractResultBody(ExchangeHelper.java:456) 
>         at
> org.apache.camel.impl.DefaultProducerTemplate.extractResultBody(DefaultProducerTemplate.java:441) 
>         at
> org.apache.camel.impl.DefaultProducerTemplate.extractResultBody(DefaultProducerTemplate.java:437) 
>         at
> org.apache.camel.impl.DefaultProducerTemplate.sendBody(DefaultProducerTemplate.java:125) 
>         at
> org.apache.camel.impl.DefaultProducerTemplate.sendBody(DefaultProducerTemplate.java:341) 
>         at
> com.xti.poc.camel.route.sample1.GenerateAndSignPdfRouteTest.testSignAndGeneratePdf(GenerateAndSignPdfRouteTest.java:36) 
>         at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) 
>         at
> sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39) 
>         at
> sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25) 
>         at java.lang.reflect.Method.invoke(Method.java:592) 
>         at
> org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:44) 
>         at
> org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:15) 
>         at
> org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:41) 
>         at
> org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:20) 
>         at
> org.junit.internal.runners.statements.RunBefores.evaluate(RunBefores.java:28) 
>         at
> org.junit.internal.runners.statements.RunAfters.evaluate(RunAfters.java:31) 
>         at
> org.junit.runners.BlockJUnit4ClassRunner.runNotIgnored(BlockJUnit4ClassRunner.java:79) 
>         at
> org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:71) 
>         at
> org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:49) 
>         at org.junit.runners.ParentRunner$3.run(ParentRunner.java:193) 
>         at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:52) 
>         at
> org.junit.runners.ParentRunner.runChildren(ParentRunner.java:191) 
>         at org.junit.runners.ParentRunner.access$000(ParentRunner.java:42) 
>         at
> org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:184) 
>         at org.junit.runners.ParentRunner.run(ParentRunner.java:236) 
>         at
> org.eclipse.jdt.internal.junit4.runner.JUnit4TestReference.run(JUnit4TestReference.java:49) 
>         at
> org.eclipse.jdt.internal.junit.runner.TestExecution.run(TestExecution.java:38) 
>         at
> org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:467) 
>         at
> org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:683) 
>         at
> org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.run(RemoteTestRunner.java:390) 
>         at
> org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.main(RemoteTestRunner.java:197) 
> Caused by: org.apache.camel.CamelExchangeException: No consumers available
> on endpoint: Endpoint[direct://start]. Exchange[Message: [Body is instance
> of java.io.InputStream]] 
>         at
> org.apache.camel.component.direct.DirectProducer.process(DirectProducer.java:56) 
>         at
> org.apache.camel.processor.UnitOfWorkProcessor.process(UnitOfWorkProcessor.java:99) 
>         at
> org.apache.camel.util.AsyncProcessorHelper.process(AsyncProcessorHelper.java:91) 
>         at
> org.apache.camel.processor.DelegateAsyncProcessor.process(DelegateAsyncProcessor.java:85) 
>         at
> org.apache.camel.processor.UnitOfWorkProducer.process(UnitOfWorkProducer.java:63) 
>         at
> org.apache.camel.impl.ProducerCache$1.doInProducer(ProducerCache.java:333) 
>         at
> org.apache.camel.impl.ProducerCache$1.doInProducer(ProducerCache.java:303) 
>         at
> org.apache.camel.impl.ProducerCache.doInProducer(ProducerCache.java:208) 
>         at
> org.apache.camel.impl.ProducerCache.sendExchange(ProducerCache.java:303) 
>         at
> org.apache.camel.impl.ProducerCache.send(ProducerCache.java:154) 
>         at
> org.apache.camel.impl.DefaultProducerTemplate.send(DefaultProducerTemplate.java:110) 
>         at
> org.apache.camel.impl.DefaultProducerTemplate.sendBody(DefaultProducerTemplate.java:123) 
>         ... 27 more
> 
> I also tried to run my own endpoint implementation and it works also fine
> in camel 2.4.0. 
> In camel 2.5.0 it looks like the behavior of the consumer has changed. 
> My implemenation crashes with an nullpointer exception in the
> RouteProducer class when calling the method process. 
> 
> There is one line in this method: 
> ((RouteletEndpoint)
> getEndpoint()).getConsumer().getProcessor().process(exchange);
> In this line the consumer is null, it looks like the setConsumer method is
> never called for the endpoint. 
> 
> Perhaps this information is important for CAMEL-3285. 
> 
> 
> best regards, 
> 
> Christoph 
> 


Hi Christoph,


I figured something like this might happen, the route component classes
which I attached
to the post was not a very elegant solution, rather a quick hack to get
something 
working in order to illustrate a point. For that particurlar customer I was
working for at
the time I needed some kind of abstraction mechanism which would allow me
to plug routes together without causing conflicts between various direct:
endpoints.
Moreover, those routes needed to be parameterizable in an easy non-verbose
way as I explained
in the quote you mentioned. 

Now, after the discussion with James I realized that the route endpoint I
had in mind was
actually a subset of the protocol component he suggested. The protocol
component is actually a better design choice as you are able to group
various related operations in one place. Also, it's more
flexible as it allows for in/out endpoints to be defined in the same
component.

I don't know what the current progress is on the issue, but I do feel you
should be using 
whatever the guys from Apache are coming out with. An optimal solution to
this problem probably needs
some mofication to the camel core to achieve the encapsulation goals.

However, just out of curiosity I did rewrite the solution I attached earlier
to match the 
suggestions made in this thread (works with camel 2.5.0). Furthermore I
complemented it with the url header value feature I was aiming for. E.g.
pdf:xslFopAndSign?xslUri=com/xti/poc/camel/route/sample1/krusty.xsl

The zip is attached to this post 
http://camel.465427.n5.nabble.com/file/n3293312/camel-route-new.zip
camel-route-new.zip 

As you will see in the code the RouteComponent starts a private
CamelContext, so encapsulation
is perfect. It also allows in and out endpoints in the same routeBuilder
definition.


The route xml :

        <route>
            <from uri="standardActions:out"/>
             <to
uri="pdf:xslFopAndSign?xslUri=com/xti/poc/camel/route/sample1/krusty.xsl"/>
            <to uri="mock:result"/>
        </route>

The pdf component :


@Component("pdf")
@Lazy
public class PdfComponent extends RouteComponent {

    @Override
    protected SpringRouteBuilder doCreateRouteBuilder() {
         return new SpringRouteBuilder() {
            @Override
            public void configure() throws Exception {
                from("direct:xslFopAndSign").to("direct:xslFop");

                from("direct:xslFop")
                       
.recipientList(simple("xslt:classpath:${header.xslUri}"))// using the header
value passed down from the xml 
                        .bean(new FopBean())
                        .to("direct:sign");

                // nesting mycomponent in pdf component 
                from("direct:sign").log("signing
pdf").to("mycomponent:mystart");
            }
        };
    }

The mycomponent :

@Component("mycomponent")
@Lazy
public class MyComponent extends RouteComponent {

    @Override
    protected SpringRouteBuilder doCreateRouteBuilder() {
        return new SpringRouteBuilder() {
            @Override
            public void configure() throws Exception {
                from("direct:mystart").log("Bla");
            }
        };
    }

}


Both components (pdf and mycomponent) can be configured using dependency
injection in spring and header values are passed down via url parameters.

Let me restate once more that I definitely recommend to use the solution the
Apache guys are coming up with.
Apart from that, feel free to use or disregard all together.


Regards,

K.
-- 
View this message in context: http://camel.465427.n5.nabble.com/Abstracting-Routes-using-Components-tp3234703p3293312.html
Sent from the Camel - Users mailing list archive at Nabble.com.

Re: Abstracting Routes using Components

Posted by James Strachan <ja...@fusesource.com>.
2011/3/1 Björn Bength <bj...@gmail.com>:
> On Tue, 2011-03-01 at 09:10 +0000, James Strachan wrote:
>> On 28 January 2011 07:19, Willem Jiang <wi...@gmail.com> wrote:
>> > On 1/28/11 4:36 AM, Mond Raymond wrote:
>> >>
>> >> Any more news on this?
>> >
>> > Ashwin already committed a camel-routebox component[1] into the Camel 2.6.0,
>> > and we will release it shortly.
>> >
>> > [1]https://cwiki.apache.org/CAMEL/routebox.html
>>
>> There's also a simpler to use implementation, using the CamelContext
>> as the 'component' and a simple naming convention:
>>
>> http://camel.apache.org/context.html
>>
>
>
> Hi,
>
> It's not possible to "connect" to another camel context via OSGi right,
> as they're not exposed like that?
> Or would it be advised to just use jms, nmr or vm in that case?
> Else I could possibly imagine some use cases for it.

Right now we've only really tested out the camel-context approach in a
pure Spring ApplicationContext. In principle the same idea could work
in OSGi too; though one added complication is inside a Spring
ApplicationContext we know that the CamelContext ids are unique so can
be used as a URI scheme. This isn't really the case when you look at
an entire OSGi container with many bundles being deployed.

You could use blueprint/spring-dm to lookup a CamelContext in OSGi and
create a smart proxy to it  and assign it an id - then use that id
with the camel-context code as shown in the Spring example above. Or
we could introduce a new component which looks up a CamelContext in
OSGi; though for now its probably simplest to just use the ServiceMix
Registry (the NMR) to refer to endpoints inside different OSGi
bundles.

-- 
James
-------
FuseSource
Email: james@fusesource.com
Web: http://fusesource.com
Twitter: jstrachan
Blog: http://macstrac.blogspot.com/

Open Source Integration

Re: Abstracting Routes using Components

Posted by Björn Bength <bj...@gmail.com>.
On Tue, 2011-03-01 at 09:10 +0000, James Strachan wrote:
> On 28 January 2011 07:19, Willem Jiang <wi...@gmail.com> wrote:
> > On 1/28/11 4:36 AM, Mond Raymond wrote:
> >>
> >> Any more news on this?
> >
> > Ashwin already committed a camel-routebox component[1] into the Camel 2.6.0,
> > and we will release it shortly.
> >
> > [1]https://cwiki.apache.org/CAMEL/routebox.html
> 
> There's also a simpler to use implementation, using the CamelContext
> as the 'component' and a simple naming convention:
> 
> http://camel.apache.org/context.html
> 


Hi,

It's not possible to "connect" to another camel context via OSGi right,
as they're not exposed like that?
Or would it be advised to just use jms, nmr or vm in that case?
Else I could possibly imagine some use cases for it.

regards
bjorn



Re: Abstracting Routes using Components

Posted by James Strachan <ja...@fusesource.com>.
On 28 January 2011 07:19, Willem Jiang <wi...@gmail.com> wrote:
> On 1/28/11 4:36 AM, Mond Raymond wrote:
>>
>> Any more news on this?
>
> Ashwin already committed a camel-routebox component[1] into the Camel 2.6.0,
> and we will release it shortly.
>
> [1]https://cwiki.apache.org/CAMEL/routebox.html

There's also a simpler to use implementation, using the CamelContext
as the 'component' and a simple naming convention:

http://camel.apache.org/context.html

-- 
James
-------
FuseSource
Email: james@fusesource.com
Web: http://fusesource.com
Twitter: jstrachan
Blog: http://macstrac.blogspot.com/

Open Source Integration

Re: Abstracting Routes using Components

Posted by Willem Jiang <wi...@gmail.com>.
On 1/28/11 4:36 AM, Mond Raymond wrote:
>
> Any more news on this?

Ashwin already committed a camel-routebox component[1] into the Camel 
2.6.0, and we will release it shortly.

[1]https://cwiki.apache.org/CAMEL/routebox.html

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

Re: Abstracting Routes using Components

Posted by Mond Raymond <mo...@gmail.com>.
Any more news on this?
-- 
View this message in context: http://camel.465427.n5.nabble.com/Abstracting-Routes-using-Components-tp3234703p3360406.html
Sent from the Camel - Users mailing list archive at Nabble.com.

Re: Abstracting Routes using Components

Posted by kristofsajdak <kr...@gmail.com>.
Looking forward to it :-)

-- 
View this message in context: http://camel.465427.n5.nabble.com/Abstracting-Routes-using-Components-tp3234703p3294704.html
Sent from the Camel - Users mailing list archive at Nabble.com.

Re: Abstracting Routes using Components

Posted by Claus Ibsen <cl...@gmail.com>.
Hi Kristof

Thanks for posting and keeping us updated.

I know Ashwin is working on this as well and I think he got most part working.
So we ought to have something to show in this month. Then we all can
take a look and have it improved a bit here and there.

Your solution looks cool though, so great work :)


On Sun, Dec 5, 2010 at 10:49 PM, kristofsajdak <kr...@gmail.com> wrote:
>
>
> cgiera wrote:
>>
>> Hi Kristof,
>>
>> I've tried your example code(sample1) and it works fine when using camel
>> 2.4.0.
>> In camel 2.5.0 it doesn't work:
>> org.apache.camel.CamelExecutionException: Exception occurred during
>> execution on the exchange: Exchange[Message: [Body is instance of
>> java.io.InputStream]]
>>         at
>> org.apache.camel.util.ObjectHelper.wrapCamelExecutionException(ObjectHelper.java:1156)
>>         at
>> org.apache.camel.util.ExchangeHelper.extractResultBody(ExchangeHelper.java:456)
>>         at
>> org.apache.camel.impl.DefaultProducerTemplate.extractResultBody(DefaultProducerTemplate.java:441)
>>         at
>> org.apache.camel.impl.DefaultProducerTemplate.extractResultBody(DefaultProducerTemplate.java:437)
>>         at
>> org.apache.camel.impl.DefaultProducerTemplate.sendBody(DefaultProducerTemplate.java:125)
>>         at
>> org.apache.camel.impl.DefaultProducerTemplate.sendBody(DefaultProducerTemplate.java:341)
>>         at
>> com.xti.poc.camel.route.sample1.GenerateAndSignPdfRouteTest.testSignAndGeneratePdf(GenerateAndSignPdfRouteTest.java:36)
>>         at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
>>         at
>> sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
>>         at
>> sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
>>         at java.lang.reflect.Method.invoke(Method.java:592)
>>         at
>> org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:44)
>>         at
>> org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:15)
>>         at
>> org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:41)
>>         at
>> org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:20)
>>         at
>> org.junit.internal.runners.statements.RunBefores.evaluate(RunBefores.java:28)
>>         at
>> org.junit.internal.runners.statements.RunAfters.evaluate(RunAfters.java:31)
>>         at
>> org.junit.runners.BlockJUnit4ClassRunner.runNotIgnored(BlockJUnit4ClassRunner.java:79)
>>         at
>> org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:71)
>>         at
>> org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:49)
>>         at org.junit.runners.ParentRunner$3.run(ParentRunner.java:193)
>>         at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:52)
>>         at
>> org.junit.runners.ParentRunner.runChildren(ParentRunner.java:191)
>>         at org.junit.runners.ParentRunner.access$000(ParentRunner.java:42)
>>         at
>> org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:184)
>>         at org.junit.runners.ParentRunner.run(ParentRunner.java:236)
>>         at
>> org.eclipse.jdt.internal.junit4.runner.JUnit4TestReference.run(JUnit4TestReference.java:49)
>>         at
>> org.eclipse.jdt.internal.junit.runner.TestExecution.run(TestExecution.java:38)
>>         at
>> org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:467)
>>         at
>> org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:683)
>>         at
>> org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.run(RemoteTestRunner.java:390)
>>         at
>> org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.main(RemoteTestRunner.java:197)
>> Caused by: org.apache.camel.CamelExchangeException: No consumers available
>> on endpoint: Endpoint[direct://start]. Exchange[Message: [Body is instance
>> of java.io.InputStream]]
>>         at
>> org.apache.camel.component.direct.DirectProducer.process(DirectProducer.java:56)
>>         at
>> org.apache.camel.processor.UnitOfWorkProcessor.process(UnitOfWorkProcessor.java:99)
>>         at
>> org.apache.camel.util.AsyncProcessorHelper.process(AsyncProcessorHelper.java:91)
>>         at
>> org.apache.camel.processor.DelegateAsyncProcessor.process(DelegateAsyncProcessor.java:85)
>>         at
>> org.apache.camel.processor.UnitOfWorkProducer.process(UnitOfWorkProducer.java:63)
>>         at
>> org.apache.camel.impl.ProducerCache$1.doInProducer(ProducerCache.java:333)
>>         at
>> org.apache.camel.impl.ProducerCache$1.doInProducer(ProducerCache.java:303)
>>         at
>> org.apache.camel.impl.ProducerCache.doInProducer(ProducerCache.java:208)
>>         at
>> org.apache.camel.impl.ProducerCache.sendExchange(ProducerCache.java:303)
>>         at
>> org.apache.camel.impl.ProducerCache.send(ProducerCache.java:154)
>>         at
>> org.apache.camel.impl.DefaultProducerTemplate.send(DefaultProducerTemplate.java:110)
>>         at
>> org.apache.camel.impl.DefaultProducerTemplate.sendBody(DefaultProducerTemplate.java:123)
>>         ... 27 more
>>
>> I also tried to run my own endpoint implementation and it works also fine
>> in camel 2.4.0.
>> In camel 2.5.0 it looks like the behavior of the consumer has changed.
>> My implemenation crashes with an nullpointer exception in the
>> RouteProducer class when calling the method process.
>>
>> There is one line in this method:
>> ((RouteletEndpoint)
>> getEndpoint()).getConsumer().getProcessor().process(exchange);
>> In this line the consumer is null, it looks like the setConsumer method is
>> never called for the endpoint.
>>
>> Perhaps this information is important for CAMEL-3285.
>>
>>
>> best regards,
>>
>> Christoph
>>
>
>
> Hi Christoph,
>
>
> I figured something like this might happen, the route component classes
> which I attached
> to the post was not a very elegant solution, rather a quick hack to get
> something
> working in order to illustrate a point. For that particurlar customer I was
> working for at
> the time I needed some kind of abstraction mechanism which would allow me
> to plug routes together without causing conflicts between various direct:
> endpoints.
> Moreover, those routes needed to be parameterizable in an easy non-verbose
> way as I explained
> in the quote you mentioned.
>
> Now, after the discussion with James I realized that the route endpoint I
> had in mind was
> actually a subset of the protocol component he suggested. The protocol
> component is actually a better design choice as you are able to group
> various related operations in one place. Also, it's more
> flexible as it allows for in/out endpoints to be defined in the same
> component.
>
> I don't know what the current progress is on the issue, but I do feel you
> should be using
> whatever the guys from Apache are coming out with. An optimal solution to
> this problem probably needs
> some mofication to the camel core to achieve the encapsulation goals.
>
> However, just out of curiosity I did rewrite the solution I attached earlier
> to match the
> suggestions made in this thread (works with camel 2.5.0). Furthermore I
> complemented it with the url header value feature I was aiming for. E.g.
> pdf:xslFopAndSign?xslUri=com/xti/poc/camel/route/sample1/krusty.xsl
>
> The zip is attached to this post
> http://camel.465427.n5.nabble.com/file/n3293312/camel-route-new.zip
> camel-route-new.zip
>
> As you will see in the code the RouteComponent starts a private
> CamelContext, so encapsulation
> is perfect. It also allows in and out endpoints in the same routeBuilder
> definition.
>
>
> The route xml :
>
>        <route>
>            <from uri="standardActions:out"/>
>             <to
> uri="pdf:xslFopAndSign?xslUri=com/xti/poc/camel/route/sample1/krusty.xsl"/>
>            <to uri="mock:result"/>
>        </route>
>
> The pdf component :
>
>
> @Component("pdf")
> @Lazy
> public class PdfComponent extends RouteComponent {
>
>    @Override
>    protected SpringRouteBuilder doCreateRouteBuilder() {
>         return new SpringRouteBuilder() {
>            @Override
>            public void configure() throws Exception {
>                from("direct:xslFopAndSign").to("direct:xslFop");
>
>                from("direct:xslFop")
>
> .recipientList(simple("xslt:classpath:${header.xslUri}"))// using the header
> value passed down from the xml
>                        .bean(new FopBean())
>                        .to("direct:sign");
>
>                // nesting mycomponent in pdf component
>                from("direct:sign").log("signing
> pdf").to("mycomponent:mystart");
>            }
>        };
>    }
>
> The mycomponent :
>
> @Component("mycomponent")
> @Lazy
> public class MyComponent extends RouteComponent {
>
>    @Override
>    protected SpringRouteBuilder doCreateRouteBuilder() {
>        return new SpringRouteBuilder() {
>            @Override
>            public void configure() throws Exception {
>                from("direct:mystart").log("Bla");
>            }
>        };
>    }
>
> }
>
>
> Both components (pdf and mycomponent) can be configured using dependency
> injection in spring and header values are passed down via url parameters.
>
> Let me restate once more that I definitely recommend to use the solution the
> Apache guys are coming up with.
> Apart from that, feel free to use or disregard all together.
>
>
> Regards,
>
> K.
> --
> View this message in context: http://camel.465427.n5.nabble.com/Abstracting-Routes-using-Components-tp3234703p3293312.html
> Sent from the Camel - Users mailing list archive at Nabble.com.
>



-- 
Claus Ibsen
-----------------
FuseSource
Email: cibsen@fusesource.com
Web: http://fusesource.com
Twitter: davsclaus
Blog: http://davsclaus.blogspot.com/
Author of Camel in Action: http://www.manning.com/ibsen/