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. 

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.


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.

Reply via email to