camel-users mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From kristofsajdak <kristof.saj...@gmail.com>
Subject Re: Abstracting Routes using Components
Date Sun, 05 Dec 2010 21:49:18 GMT


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.

Mime
View raw message