camel-users mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From Claus Ibsen <claus.ib...@gmail.com>
Subject Re: Abstracting Routes using Components
Date Thu, 28 Oct 2010 04:15:11 GMT
On Wed, Oct 27, 2010 at 11:08 PM, kristofsajdak
<kristof.sajdak@gmail.com> wrote:
>
> Great feedback guys, much appreciated !
>
>
> jstrachan wrote:
>>
>> Agreed. If you kinda squint a bit and think of the route builders as
>> 'objects' and you want to compose 2 different routes together with
>> shared dependencies its a bit like 'constructors' and 'data hiding'.
>>
>> We have protocol A and B and we need to route the output of A to the
>> input of B; so rather than B needing to know the implementation detail
>> of A; we add a constructor parameter for B's input...
>>
>> class A extends ProtocolBuilder {...}
>>
>> class B extends ProtocolBuilder {
>>   public B(String inputUri) { ... }
>> }
>>
>> // lets use Java code to simulate DI...
>> ProtocolBuilder a = new A();
>> ProtocolBuilder b = new B(b.getOutputUri());
>>
>>
>> we've now wired A and B together without B knowing anything about the
>> implementation detail of A.
>>
>> Its quite common for lots of protocols to be 'unix pipe-ish' with an
>> input and output; so we could have helper classes where there's
>> standard input/output endpoints like this to create a pipeline...
>>
>> CompositeProtocol composite = Protocols.pipeline(A.class, B.class,
>> C.class);
>>
>> where A:out -> B:in and B:out -> C:in. Indeed that could return a new
>> protocol; where composite:in maps to A:in and composite:out maps to
>> C:out
>>
>> But then this is sounding like just treating A, B and C as endpoints :)
>>
>
> Indeed that is adding more flexibility and will be quite usefull when
> nesting protocolBuilders several levels deep.
>
> However, I do have another point which relates to the specific use case of
> the customer I mentioned.
>
> Developers -> provide ProtocolBuilder implementations
> Solution consultants -> use ProtocolBuilders abstractions to wire the route.
>

Yeah this sounds like a great use case and in demand in more and more companies.
This is something that we hear more often and often.



> Practically, it seems to me that the easiest way of achieving that is to
> create one or more modules
> which contain the ProtocolBuilders implementation classes and the spring xml
> files which configure them.
>
> Whenever a solution consultant starts working on a new customer
> implementation he could use an archetype to create a module which has the
> dependencies to the ProtocolBuilder modules preconfigured.
>
> The solution consultant would then create the route in xml dsl and use
> camel:run to execute the route, this plugin goal would in turn bootstrap all
> the ProtocolBuilder configurations located in
> classpath*:META-INF/spring/.xml, making them available to the route at
> runtime.
>
> Now my question is: When you define a ProtocolBuilder in the spring xml,
> would it get initialized and added to the CamelContext at that point ? I
> mean I don't think it's a good idea to initialize and add all the
> ProtocolBuilders which are available in classpath*:META-INF/spring, but
> neither do I want to leave it up to the solution consultant to explicitly
> define which builders get initialized.
>
> E.g. Like with the Parameterized RouteBuilder concept I mentioned earlier
>
>  <camelContext ...
>    <routeBuilder ref="generateAndSignPdfRouteBuilder"/>
>    <routeBuilder ref="signPdfRouteBuilder"/>
>    ....
>
> Which is just way to complex for non developers in my opinion.
>

You can use annotations, for example the Spring @Component annotation.
You would then @Component annotate the RouteBuilder to be included.

Then you can use the <contextScan/> tag
See http://camel.apache.org/spring.html

This means its standard Spring stuff to annotate and use the spring
XML tag to enable its context scanner.

All you do in Camel is to add this <contextScan/> inside the <camelContext> tag.


Maybe there are other ways to make this easier? Any suggestions?



>
> It sure would be nice if you could initialize and add the ProtocolBuilder
> route configuration on demand.
> Saving overhead on startup and runtime, yet making it easy for a low tech
> guy to use all of the available
> ProtocolBuilders -> no explicit declaration of ProtocolBuilders nor any
> fiddling with dependencies in the pom.xml.
>
> The concept of the shorthand notation could add value here as well.
>
> The global properties + tech dependencies like a datasource could be
> configured by developers using spring di in the xml. Wheras the parameters,
> which make sense in the context of the route, are defined by the solution
> consultant using the shorthand notation.
>
> E.g.
>
> ?signatureReason=JustForFun&signatureVisible=true&xslUri=com/xti/poc/camel/route/sample1/krusty.xsl
>
>
>
> jstrachan wrote:
>>
>>
>> Thats a great point! Just like with OO, we probably need some kind of
>> data hiding; or in this case its 'endpoint hiding'. So maybe using
>> nested CamelContexts is a good thing.
>>
>> Another random idea; imagine if we had a ProtocolBuilder which created
>> a child CamelContext - so all "direct:foo" and "seda:bar" endpoints
>> were totally private. Then imagine, as a simple implementation option
>> - we map all URIs within the ProtocolBuilder's URI space to the
>> direct: endpoint within the nested CamelContext.
>>
>> So rather than having to add the "alias()" method I mentioned in the
>> other thread - we could just use URIs inside the route for the
>> 'input/output/error' URIs...
>> http://camel.465427.n5.nabble.com/implementing-Protocols-or-a-way-to-make-it-easier-to-black-box-routes-and-compose-them-with-other-ros-td3218777.html#a3218777
>>
>> e.g. imagine...
>>
>> class A extends ProtocolBuilder {
>>   public void configure() {
>>     from("direct:in").
>>      beanRef("foo").
>>      to("direct:out");
>>   }
>> }
>>
>> class B extends ProtocolBuilder {
>>   public void configure() {
>>     from("direct:in").
>>      unmarshal().jaxb().
>>      to("direct:out");
>>   }
>> }
>>
>> // now lets wire A and B
>> // kinda like "Foo | A | B | Bar" on a unix command line
>>
>> class Foo extends RouteBuilder {
>>   public void configure() {
>>     from("activemq:Foo").to("a:in");
>>     from("a:out").to("b:in");
>>     from("b:out").to("activemq:Bar");
>>   }
>> }
>>
>>
>> i.e. so A and B have no knowledge of each other (kinda like unix
>> pipes), you can compose them together in any way you like (Foo) - and
>> bind them to any middleware.
>>
>> In this example the 'local endpoints' (using direct:) are totally
>> private to each ProtocolBuilder so there's no name clashes as we're
>> using nested CamelContext's.
>>
>> Not totally sure if we should make "direct" into some magical
>> component here; or if we should just introduce some kind of "local:"
>> endpoint to use inside a ProtocolBuilder to emphasise a local,
>> internal endpoint which is private to the ProtocolBuilder? e.g.
>> replace "direct:in" to "local:in".
>>
>> The question of local v global endpoint URIs is interesting; I wonder
>> how many kinds of endpoints can even support the concept of local.
>> Using nested CamelContexts we'd have local seda/vm/direct I think;
>> though given their similarity, maybe a new 'local' endpoint is simpler
>> as it clearly describes what really is local versus what really is an
>> external/global endpoint?
>>
>> Note that there's nothing to stop these protocols using
>> external/global endpoints too; am sure they will. Its more where we
>> parameterise things together we might want to use local endpoints
>> which we can then route into / out of.
>>
>
> Having the ProtocolBuilder create a child CamelContext seems like a very
> good idea !
> This way you can use the direct: and seda endpoints with normal semantics
> and without risk of namespace collisions.
>
> Just a thought though, if you are going with this concept, wouldn't it make
> more sense to use a public: endpoint to explicitly define public endpoints ?
>
> E.g.
>
> class A extends ProtocolBuilder {
>
>  public void configure() {
>
>    from("public:in").
>     beanRef("foo").
>     to("direct:bar");
>
>     from("direct:bar").
>     to("public:out");
>
>  }
> }
>
> Doesn't a local: endpoints make more sense when you are not using a nested
> Context,
> and therefore would have to define explicitly what you keep private.
> In the case of a nested CamelContext, the direct: and seda: endpoints are
> always private and defining explicitly what you want as public makes sense.
>
> --
> View this message in context: http://camel.465427.n5.nabble.com/Abstracting-Routes-using-Components-tp3234703p3239506.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/

Mime
View raw message