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/10/24 23:19:27 UTC

Abstracting Routes using Components

Hi,

I'm currently working on a poc for a customer.

As part of their core business they offer a platform which mediates between
trading partners.
What is special about their use case is the fact that they want the actual
routes between 
partners to be defined by employees with limited technical knowledge
(solution consultants).

I know there is the xml dsl and the upcoming camel rider which lowers the
threshold for non developers. 
But even when using these features, the route configuration would be way too
fine grained for them and 
they would still require too much knowledge on the details of the technical
components.

Last week I was at the FUSE community day in Paris and spoke to James
Strachan on the customer
need to abstract some parts of the routes. He mentioned the idea of using a
component as a kind
of proxy for a route. 

I believe this is a real nice solution to the problem.
A complex route were a pdf is generated from an xml using xslt and fop and
the result is signed using a 
third party service exposed over http could be reduced to the following. 

        <route>
            <from uri="{{data.in}}"/>
            <to
uri="route:generateAndSignPdf?signatureReason=JustForFun&amp;signatureVisible=true&amp;xslUri=com/xti/poc/camel/route/sample1/krusty.xsl"/>
            <to uri="{{data.out}}"/>
        </route>

The route component concept abstracts the route low level technical details
and makes reuse easy. 
The solution consultant only needs to define the route:generateAndSignPdf
with the correct parameters.

As this construct would provide great value to the customer I went ahead and
implemented this idea as part of the poc. Attached to this post is my
codebase with a unit test executing the scenario mentioned above.

I would really appreciate some feedback from the community on the code I
wrote.
I tried fitting this in with the component lifecycle the best I could but
still have some doubts on whether it's done correct.

Getting an expert opinion on this would be a big help.


Best regards,


Kristof

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

Re: Abstracting Routes using Components

Posted by James Strachan <ja...@gmail.com>.
On 26 October 2010 16:17, Hadrian Zbarcea <hz...@gmail.com> wrote:
> So the idea is to use route templates and in order to parameterized them use URIs the camel way. That's nice and consistent.

There are a few different options here...

i) a parameterized RouteBuilder which can be dependency injected using
Spring/Java/Guice/whatever

ii) a parameterized RouteBuilder which is dependency injected using a
URI (which is kinda like Kristof's example code)

iii) a ProtocolBuilder which is-a Component and is-a RouteBuilder so
that the components URI namespace can be used to export 'global names'
to its logical endpoints which map to internal Camel endpoints names
used inside the routes. The ProtocolBuilder could even use a nested
internal CamelContext to totally hide the implementation detail. Which
is what I describe here...

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

This idea would let a default Protocol have default endpoints "in",
"out" and "err" for example.

Each of these approaches have their own strengths and weaknesses,
depending on what you are doing and if you need to 'wrap' or 'hide'
implementation details or if you just want simple parameterization of
a RouteBuilder class. If all you want is parametrization of a
RouteBuilder then (i) or (ii) works great; just pick your preferred
injection mechanism.

(iii) is subtly different; its like taking some integration code as an
implementation and packaging it up with a public interface for others
to use inside other routes; hiding the implementation detail from the
person doing the integration of this new component. With the customers
I've talked to where (iii) is more relevant they have one team making
a particular Protocol (a component which wraps a bunch of routing
rules), then they have other teams take the various Protocols output
by other teams and route them together.

In this sense the Protocols become just a way to package up a
collection of Routes into an easy to use form for others folks to use;
rather like using Composition with Object Orientation to make an easy
to use Facade on top of some implementation code.

-- 
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 Ashwin Karpe <ak...@fusesource.com>.
Hi Eric,

Please check out the link below

http://camel.apache.org/how-do-i-import-routes-from-other-xml-files.html
http://camel.apache.org/how-do-i-import-routes-from-other-xml-files.html 

Once you have routes in XML you can store them in any backing store,
repository or file. You can instantiate the routes in Spring (shown in the
link) or DSL. Based on what you are saying it seems like for the time-being
you need to do this to happen in a processor.

The code is quite simple. All you need to do is

a> Read the routeContext along with its routes into a list
ArrayList<RouteDefinition> routes = 
        (ArrayList<RouteDefinition>)
getCamelContext().getApplicationContext().
        getBean("serviceRoute", ArrayList.class);

b> Fire up the routes as follows...
getCamelContext().addRouteDefinitions(routes);

Hope this helps for the time-being...

Cheers,

Ashwin...

-----
---------------------------------------------------------
Ashwin Karpe
Apache Camel Committer & Sr Principal Consultant
FUSESource (a Progress Software Corporation subsidiary)
http://fusesource.com http://fusesource.com 

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

Re: Abstracting Routes using Components

Posted by Eric Jennings <er...@loopshot.com>.
Hi there!

Been following this thread very closely!

For what it's worth, I'm faced with a similar issue as Kristof for my current Camel-based project.  We're essentially wanting to support user-specific, user-defined routes, so that when a user presents themselves (whether through Shiro as a token, via a JMS header, or whatever), we would have a bean that instantiates that user's route for the In/Out channel pair specific to that client.

It seems to work in a simple manner, but now I need to determine the best way to represent/serialize/store the user-based routes.  Toss-up between something dynamic like Groovy or something more compiled-then-loaded like OSGi.  I don't want to hijack this thread, but I may be pinging you all for some insight soon regarding that issue.

Anyhow, since I had just been building this proxy route-instantiator the last couple of days when this thread popped up, count this as an additional vote for getting something like this going.

Thanks-
Eric Jennings

Re: Abstracting Routes using Components

Posted by Ashwin Karpe <ak...@fusesource.com>.
Hi James & Hadrian,

I like what you both have said. I was actually thinking of the URI more
along the lines of a URN (camel-lucene) rather than a URL Scheme
(camel-netty), but a ProtocolBuilder the way Hadrian has suggested will work
well too (route:blackboxroute1://out || route:blackboxroute1:out). 

The key is (as you correctly pointed out) James to be able to wrap a route
with multiple inputs/outputs and transparently move payloads arriving at
(route:blackboxroute1://out) to the right set of consumers and collect the
final exchange from the inner route and push it to the next coarse grainer
route (route:blackboxroute2:in).

Even more interesting is the situation that endpoint
(route:blackboxroute1://out) has to handle In-Out scenarios when an exchange
from the endpoint (route:blackboxroute2:in) is received on the outbound to
be directed back to the original client.

I still have to work out how an distributed client will know about the
protocol semantics of the hidden sub-route consumer (easy/no change when
involving an in-JVM client). Maybe query params??? Any thoughts...

I was thinking of taking advantage of using a ProtocolBuilderContext
(similar to RouteContext) to facilitate route declaration and encapsulation
of the inner route with the endpoint name (blackboxroute1) that can then be
wired by the component (route:) along the way.   

Any thoughts/ideas on this approach.... Getting a generic second level of
indirection in Camel using a coarse grained ProtocolBuilder component is
sweet !!! I love it...

Cheers,

Ashwin...



-----
---------------------------------------------------------
Ashwin Karpe
Apache Camel Committer & Sr Principal Consultant
FUSESource (a Progress Software Corporation subsidiary)
http://fusesource.com http://fusesource.com 

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

Re: Abstracting Routes using Components

Posted by James Strachan <ja...@gmail.com>.
On 26 October 2010 19:21, Hadrian Zbarcea <hz...@gmail.com> wrote:
> There are a few issues we need to sort out. One is that with something like this:
>> from("blackboxroute1://out")...
> You'd have to deal with naming. If everybody will define her "blackboxroute1" you'll have to deal with name clashes.

Sure - but thats what Spring / Guice / JNDI already do. The scheme
names in Camel come from your IoC container which already deal nicely
with name clashes.


> You can do something like "route:blackboxroute1://out".

How does an extra level of indirection help solve naming clashes?


> Then the lightweight part I would like not to get lost in this discussion, as in no interceptors, no dlc.

Don't follow. We're talking Camel all the way down here; so nothing
gets lost. We're just talking about wrapping Camel routes inside a
component for 'data hiding' and easier composition.


> You can then have processing pipelines (as in subroutes, not camel pipelines, I hope not creating confusion) that can be developed by independent groups and reused.
> Of course something like that can only be done today with direct: and seda: based routes, but we can simplify that.
>
> @James, I'll be in London for a couple of days. If you wanna chat about this over beer on Thu evening (your treat :) ), please let me know.

Thanks; though I'm out in the sticks these days (125 miles away) and
unfortunately its my turn to babysit. Maybe next time!

-- 
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 Hadrian Zbarcea <hz...@gmail.com>.
There are a few issues we need to sort out. One is that with something like this:
> from("blackboxroute1://out")...
You'd have to deal with naming. If everybody will define her "blackboxroute1" you'll have to deal with name clashes.
You can do something like "route:blackboxroute1://out". Then the lightweight part I would like not to get lost in this discussion, as in no interceptors, no dlc.
You can then have processing pipelines (as in subroutes, not camel pipelines, I hope not creating confusion) that can be developed by independent groups and reused.
Of course something like that can only be done today with direct: and seda: based routes, but we can simplify that.

@James, I'll be in London for a couple of days. If you wanna chat about this over beer on Thu evening (your treat :) ), please let me know.

Cheers,
Hadrian


On Oct 26, 2010, at 12:00 PM, James Strachan wrote:

> On 26 October 2010 16:40, Ashwin Karpe <ak...@fusesource.com> wrote:
>> 
>> Hi Hadrian,
>> 
>> Not sure if you recall, but we had discussed a similar idea about 8-10
>> months ago when I was on a consulting gig where we were trying to do
>> something similar (not exactly components, but black boxed subroutes) so
>> that we could do something like
>> 
>>     from(route:blackboxedroute1)
>>        .to(route:blackboxedroute2);
>> 
>> where "route:..." was a pointer to an encapsulated route and would
>> instantiate the route on demand.
> 
> BTW thats kinda the code Kristof submitted at the start of this thread
> if you take a look. Thats a totally valid approach too BTW.
> 
> For this approach you suggest we need to expose the RouteBuilder as a
> named bean so the "route:" component can refer to it, right? So the
> endpoint "route:foo" refers to the "foo" RouteBuilder.
> 
> The thing is a typical RouteBuilder might have many inputs and
> outputs; you typically want to be able to route to some of the
> endpoints inside some of the routes and from some of the endpoints. So
> how does this route: component know what endpoints are inside the
> black box RouteBuilder?
> 
> So we're often not wrapping up a set of routes as a 'single endpoint'
> - but instead as a black box with a number of endpoints (say one "in"
> and an "out" and "err"). Or maybe multiple in and outs?
> 
> 
> This was why I suggested the ProtocolBuilder; let lets you take a
> RouteBuilder and turn it into a Component and provide a way of
> converting simple component relative endpoint URIs to actual
> implementation endpoints. e.g. using your example Ashwin...
> 
>  from("blackboxroute1://out").to("backboxroute2://in")
> 
> Then in the ProtocolBuilder class, we do the normal RouteBuilder
> stuff, but also map some input/output names ("in", "out", "error" for
> example) to the actual physical endpoint URIs the routes are using.
> 
> The only difference really between the 'generic route component' and
> the ProtocolBuilder I'm proposing is the latter provides a simpler
> endpoint naming approach and can deal with an arbitrary number of
> input and output endpoints. Plus I'm not quite sure how the former
> works when a RouteBuilder defines many inputs and outputs :)
> 
> Maybe the "route proxy component" is good when you want to turn a
> RouteBuilder into a single Camel endpoint. The ProtocolBuilder is good
> when you want to turn a RouteBuilder into a number of named input &
> output endpoints - or when you want a simpler URI?
> 
> -- 
> 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 James Strachan <ja...@gmail.com>.
On 26 October 2010 16:40, Ashwin Karpe <ak...@fusesource.com> wrote:
>
> Hi Hadrian,
>
> Not sure if you recall, but we had discussed a similar idea about 8-10
> months ago when I was on a consulting gig where we were trying to do
> something similar (not exactly components, but black boxed subroutes) so
> that we could do something like
>
>     from(route:blackboxedroute1)
>        .to(route:blackboxedroute2);
>
> where "route:..." was a pointer to an encapsulated route and would
> instantiate the route on demand.

BTW thats kinda the code Kristof submitted at the start of this thread
if you take a look. Thats a totally valid approach too BTW.

For this approach you suggest we need to expose the RouteBuilder as a
named bean so the "route:" component can refer to it, right? So the
endpoint "route:foo" refers to the "foo" RouteBuilder.

The thing is a typical RouteBuilder might have many inputs and
outputs; you typically want to be able to route to some of the
endpoints inside some of the routes and from some of the endpoints. So
how does this route: component know what endpoints are inside the
black box RouteBuilder?

So we're often not wrapping up a set of routes as a 'single endpoint'
- but instead as a black box with a number of endpoints (say one "in"
and an "out" and "err"). Or maybe multiple in and outs?


This was why I suggested the ProtocolBuilder; let lets you take a
RouteBuilder and turn it into a Component and provide a way of
converting simple component relative endpoint URIs to actual
implementation endpoints. e.g. using your example Ashwin...

  from("blackboxroute1://out").to("backboxroute2://in")

Then in the ProtocolBuilder class, we do the normal RouteBuilder
stuff, but also map some input/output names ("in", "out", "error" for
example) to the actual physical endpoint URIs the routes are using.

The only difference really between the 'generic route component' and
the ProtocolBuilder I'm proposing is the latter provides a simpler
endpoint naming approach and can deal with an arbitrary number of
input and output endpoints. Plus I'm not quite sure how the former
works when a RouteBuilder defines many inputs and outputs :)

Maybe the "route proxy component" is good when you want to turn a
RouteBuilder into a single Camel endpoint. The ProtocolBuilder is good
when you want to turn a RouteBuilder into a number of named input &
output endpoints - or when you want a simpler URI?

-- 
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 Ashwin Karpe <ak...@fusesource.com>.
Hi JStrachan & Hadrian,

Please see my post above. It is very do-able... Do you think this is
something I could/should implement...? Do you see value in having this
feature?

Please let me know.

Cheers,

Ashwin...

P.S: I did something similar on the consulting gig (not exactly this, but
similar). In hindsight, I could have done in a much simpler and elegant way
as shown above.

-----
---------------------------------------------------------
Ashwin Karpe
Apache Camel Committer & Sr Principal Consultant
FUSESource (a Progress Software Corporation subsidiary)
http://fusesource.com http://fusesource.com 

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

Re: Abstracting Routes using Components

Posted by Ashwin Karpe <ak...@fusesource.com>.
Hi Hadrian,

Not sure if you recall, but we had discussed a similar idea about 8-10
months ago when I was on a consulting gig where we were trying to do
something similar (not exactly components, but black boxed subroutes) so
that we could do something like

     from(route:blackboxedroute1)
        .to(route:blackboxedroute2); 

where "route:..." was a pointer to an encapsulated route and would
instantiate the route on demand.

Now that I think about it it could be easily done with a simple
wrapper/proxy (component, if absolutely necessary) that could instantiate an
embedded route on demand and then proxy out from the more coarse-grained
route definition as shown above.

I dropped the thought before... Do you think it is worth pursuing and adding
a Jira entry for such a generic capability.

Please let me know. I would be happy to implement the same.

Cheers,

Ashwin...

-----
---------------------------------------------------------
Ashwin Karpe
Apache Camel Committer & Sr Principal Consultant
FUSESource (a Progress Software Corporation subsidiary)
http://fusesource.com http://fusesource.com 

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

Re: Abstracting Routes using Components

Posted by Hadrian Zbarcea <hz...@gmail.com>.
So the idea is to use route templates and in order to parameterized them use URIs the camel way. That's nice and consistent.
Not sure though it a component is the best way to go. To me this is similar to another idea discussed a while ago, lightweight routes (sub-routes, routelets ?)
that do not have the DLC, are,well, lightweight and are composed into a route.

My $0.02,
Hadrian


On Oct 26, 2010, at 10:46 AM, James Strachan wrote:

> Hi Kristof
> 
> BTW I raised a thread on the dev list to describe our chat...
> 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
> 
> On 24 October 2010 22:19, kristofsajdak <kr...@gmail.com> wrote:
>> 
>> Hi,
>> 
>> I'm currently working on a poc for a customer.
>> 
>> As part of their core business they offer a platform which mediates between
>> trading partners.
>> What is special about their use case is the fact that they want the actual
>> routes between
>> partners to be defined by employees with limited technical knowledge
>> (solution consultants).
>> 
>> I know there is the xml dsl and the upcoming camel rider which lowers the
>> threshold for non developers.
>> But even when using these features, the route configuration would be way too
>> fine grained for them and
>> they would still require too much knowledge on the details of the technical
>> components.
>> 
>> Last week I was at the FUSE community day in Paris and spoke to James
>> Strachan on the customer
>> need to abstract some parts of the routes. He mentioned the idea of using a
>> component as a kind
>> of proxy for a route.
>> 
>> I believe this is a real nice solution to the problem.
>> A complex route were a pdf is generated from an xml using xslt and fop and
>> the result is signed using a
>> third party service exposed over http could be reduced to the following.
>> 
>>        <route>
>>            <from uri="{{data.in}}"/>
>>            <to
>> uri="route:generateAndSignPdf?signatureReason=JustForFun&amp;signatureVisible=true&amp;xslUri=com/xti/poc/camel/route/sample1/krusty.xsl"/>
>>            <to uri="{{data.out}}"/>
>>        </route>
>> 
>> The route component concept abstracts the route low level technical details
>> and makes reuse easy.
>> The solution consultant only needs to define the route:generateAndSignPdf
>> with the correct parameters.
>> 
>> As this construct would provide great value to the customer I went ahead and
>> implemented this idea as part of the poc. Attached to this post is my
>> codebase with a unit test executing the scenario mentioned above.
>> 
>> I would really appreciate some feedback from the community on the code I
>> wrote.
>> I tried fitting this in with the component lifecycle the best I could but
>> still have some doubts on whether it's done correct.
>> 
>> Getting an expert opinion on this would be a big help.
> 
> Great stuff Kristof!
> 
> I also met a bunch of folks at the recent FuseDay in Washington who
> had similar ideas and use cases too; this general approach and idea
> seems to be gaining momentum.
> 
> I think its going to be increasingly common to take some routes, wrap
> them up in a 'black box' as a 'Protocol' that can then be handed off
> to other users/scenarios which are then configured and/or routed into
> or out of.
> 
> As I mentioned in the previous thread...
> 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
> 
> I like the idea of using a component instance for each 'black box' (or
> protocol lets say); as this then provides a nice name scoping for
> endpoints.
> 
> For example imagine if the "generateAndSignPdf" protocol had a single
> input ("in") and a default output ("out")  along with a failure
> endpoint ("err") - then we have in/out/err like unix pipes.  (Note a
> protocol could have a completely arbitrary number of inputs and output
> endpoints - am just thinking the in/out/err are common)...
> 
> You could then wire into the black box as...
> 
> <!-- we can route from multiple physical endpoints to the logical
> input endpoint... -->
> 
> <route>
>  <from uri="activemq:SomeInputQueue"/>
>  <to uri="generateAndSignPdf://in"/>
> </route>
> <route>
>  <from uri="file://someDir/foo"/>
>  <to uri="generateAndSignPdf://in"/>
> </route>
> 
> If you then wanted to process the output of the protocol...
> 
> <route>
>  <from uri="generateAndSignPdf://out"/>
>  <to uri="activemq:SomethingOrOther"/>
> </route>
> 
> In this example we're hiding the protocol behind a component URI
> naming convention and we can then refer to the logical exported
> endpoints by name which then map to actual physical endpoints. If the
> black box were totally stand alone & it wasn't intended for Camel to
> route into/out of it, then you might as well just make this protocol a
> bean...
> 
> <bean id="foo" class="com.acme.MyRouteBuilder">
>  <!-- lets configure the endpoints used in the route builder... -->
>  <property name="in" vallue="activemq:UseThisInputQueue"/>
>   ...
> 
> 
> Or to say that a slightly different way; if you just want a
> parameterised RouteBuilder, well thats just a bean; no need for
> anything new, Camel can do that nicely today. Whats different about
> this idea of "Protocols" and a ProtocolBuilder is the idea we can add
> the ability to expose endpoints within the namespace of the
> component/bean which you can route to outside of the Protocol. So its
> not just a black box; its a black box with defined public connector
> endpoints folks can route to without needing to understand any
> knowledge of whats inside.
> 
> As Willem mentioned on the previous thread; we could have a single
> component for these 'protocols'; though given the simplicity and URI
> naming simplicity; I'm preferring to combine the RouteBuilder and
> Component together into a single bean - which can then be configured
> using Dependency Injection, but can also expose arbitrary logical URIs
> which lets other folks route into and between these Protocols
> 
> e.g. we can create many instances of protocols; each get their own
> unique URI scheme in Camel and we can easily refer to the in/out/err
> of those protocols (if they use a standard shape of input/outputs).
> 
> -- 
> 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 kristofsajdak <kr...@gmail.com>.

"jstrachan' wrote:
> 
> So when we're routing into a Protocol from the outside, we need to 
> decide what the URI parameters map to - is it configuring properties 
> on the protocol bean, or passing headers into the message? It could go 
> either way. 
> 
> Typically we tend to configure a component (which can have many 
> possible endpoints) once through dependency injection 
> (spring/guice/jndi etc), then use uri parameters to configure the 
> actual Endpoint objects. 
> 
> So when a Protocol is a Component we should follow suit; if you want 
> different Protocol instances with different configurations (with their 
> own sets of endpoints) then use different dependency injected beans 
> with different URI schemes. 
> 
> So in your previous example we might use URIs "fooBar://in" & 
> "fooNoBar://in" on different component instances configured. 
> 
> When a Protocol is exposed as just a single Endpoint (with a fixed 
> "in" endpoint), then the act of creating the Endpoint from the 
> Protocol could configure a new instance of the Protocol bean using URI 
> query parameters. 
> 
> So in your example, "route:foo?foo=bar" could be instantiating the foo 
> bean, setting the foo property then invoking it's 'in' endpoint. 
> 
> 

Ok, I see, that makes sense.
When a protocol is a component, the component 'owns' the route config.
Since there are multiple endpoints, using a shorthand to configure
properties 
on the component level is plain wrong as it could result in erraditic
behaviour. 

If the Protocol component should support a shorthand notation, passing the
values as headers would be the only option I  guess.


jstrachan wrote:
> 
> Incidentally, maybe using the term "Protocol" for the Component or 
> Endpoint use cases above is confusing. Maybe we say a Protocol is-a 
> Component with a URI scheme and multiple public input/output endpoints 
> and for the Endpoint case (in your example) we just call that a "Route 
> Endpoint" - I.e. turning a named RouteBuilder bean into an Endpoint 
> (then sending to it's first 'from')? 
> 

Good point, distinct names for both concepts.

I'm starting to wonder though whether the Route Endpoint would still be of
use when there is a protocol 
component.

The only benefit of having a Route Endpoint is that you could configure
properties through URI parameters.
I don't even know whether there is be a real use case for that. Maybe the
concept of passing header values 
via a shorthand notation is already all the customer needs.

I guess we'll know once the customer will start the real implementation.
But I would definitively prefer to reusing the protocol concept as it fits 
the core requirement, which is creating reusable components with proper
endpoint encapsulation / scoping.

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

Re: Abstracting Routes using Components

Posted by James Strachan <ja...@gmail.com>.
So when we're routing into a Protocol from the outside, we need to
decide what the URI parameters map to - is it configuring properties
on the protocol bean, or passing headers into the message? It could go
either way.

Typically we tend to configure a component (which can have many
possible endpoints) once through dependency injection
(spring/guice/jndi etc), then use uri parameters to configure the
actual Endpoint objects.

So when a Protocol is a Component we should follow suit; if you want
different Protocol instances with different configurations (with their
own sets of endpoints) then use different dependency injected beans
with different URI schemes.

So in your previous example we might use URIs "fooBar://in" &
"fooNoBar://in" on different component instances configured.

When a Protocol is exposed as just a single Endpoint (with a fixed
"in" endpoint), then the act of creating the Endpoint from the
Protocol could configure a new instance of the Protocol bean using URI
query parameters.

So in your example, "route:foo?foo=bar" could be instantiating the foo
bean, setting the foo property then invoking it's 'in' endpoint.

Incidentally, maybe using the term "Protocol" for the Component or
Endpoint use cases above is confusing. Maybe we say a Protocol is-a
Component with a URI scheme and multiple public input/output endpoints
and for the Endpoint case (in your example) we just call that a "Route
Endpoint" - I.e. turning a named RouteBuilder bean into an Endpoint
(then sending to it's first 'from')?


On Thursday, October 28, 2010, kristofsajdak <kr...@gmail.com> wrote:
>
>
> kristofsajdak wrote:
>>
>> I really think this adds a lot of value for non technical people (e.g.
>> solution consultants).
>> The developers would take care of configuring ProtocolBuilder 'templates'
>> and injecting them with global properties and middleware stuff. The
>> solution consultants would further enhance the Builders with
>> protocol stuff using the URI parameters.
>>
>> This saves them the trouble defining beans for every variation of a
>> particurlar ProtocolBuilder template.
>>
>> E.g.
>>
>>         <route>
>>             <from uri="direct:start"/>
>>             <to uri="route:foo?foo=bar"/>
>>             <to uri="route:foo?foo=noBar"/>
>>             <to uri="mock:result"/>
>>         </route>
>>
>> I guess you'd need to define the Builder with a prototype scope to pull
>> something like this off ?
>>
>
> Mixing things up a bit.
> I copy/pasted the snippet above from the customer poc codebase.
>
> Based on what was discussed in this topic, it could look like
>
>     <route>
>             <from uri="direct:start"/>
>             <to uri="foo://in?foo=bar"/>
>             <to uri="foo://in?foo=noBar"/>
>             <to uri="mock:result"/>
>         </route>
>
> were foo is a bean in spring, injected with let's say a BarService
> middleware depedency.
>
> 2 usages of foo in the route above results in 2 foo instances.
> one instance parameterized with foo = bar, the other one with foo = noBar.
>
>
>
>
> --
> View this message in context: http://camel.465427.n5.nabble.com/Abstracting-Routes-using-Components-tp3234703p3241229.html
> Sent from the Camel - Users mailing list archive at Nabble.com.
>

-- 
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 kristofsajdak <kr...@gmail.com>.

kristofsajdak wrote:
> 
> I really think this adds a lot of value for non technical people (e.g.
> solution consultants).
> The developers would take care of configuring ProtocolBuilder 'templates'
> and injecting them with global properties and middleware stuff. The
> solution consultants would further enhance the Builders with
> protocol stuff using the URI parameters.
> 
> This saves them the trouble defining beans for every variation of a
> particurlar ProtocolBuilder template.
> 
> E.g.
> 
>         <route>
>             <from uri="direct:start"/>
>             <to uri="route:foo?foo=bar"/>
>             <to uri="route:foo?foo=noBar"/>
>             <to uri="mock:result"/>
>         </route>
> 
> I guess you'd need to define the Builder with a prototype scope to pull
> something like this off ? 
> 

Mixing things up a bit. 
I copy/pasted the snippet above from the customer poc codebase.

Based on what was discussed in this topic, it could look like 

    <route>
            <from uri="direct:start"/>
            <to uri="foo://in?foo=bar"/>
            <to uri="foo://in?foo=noBar"/>
            <to uri="mock:result"/>
        </route> 

were foo is a bean in spring, injected with let's say a BarService
middleware depedency.

2 usages of foo in the route above results in 2 foo instances.
one instance parameterized with foo = bar, the other one with foo = noBar.




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

Re: Abstracting Routes using Components

Posted by kristofsajdak <kr...@gmail.com>.

Claus Ibsen-2 wrote:
> 
> 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 does sound like a very nice way to add RouteBuilders in a non verbose
way.
However, if you go about it in that way, how would you limit the number of
RouteBuilders 
being initialized and addded to the CamelContext ? 

That is, if we are still talking about using one dependency to a module
which contains all of the Route abstractions. I guess you could have one
module for one RouteBuilder and add / remove those as dependencies to your
module. But that would require the non technical person to start editing the
pom.xml.

Maybe that's not a big deal but I would like to avoid the extra hassle if I
can ;-)


jstrachan wrote:
> 
> Agreed. 
> 
> We can also use the same kind of tricks with Component/Endpoint as 
> with Protocol; i.e. if you don't use a Protocol then nothing much 
> happens. Even when you do use a Protocol (like using a Component), 
> things only really kick in when you start really using them & routing 
> to/from them. 
> 

Sounds good to me.


jstrachan wrote:
> 
> 
> Yeah. I guess usually with Component/Endpoint type stuff, we tend to 
> use URI parameters to configure 'middleware type stuff'; for 
> Protocols, maybe the URIs should be 'protocol stuff' i.e. setting 
> headers which can be used inside the protocol to respond differently. 
> 
> Or to say that a different way; if the endpoints into and out of a 
> Protocol are all a simple standard kind (say the "local" endpoints 
> mentioned previously), there's not going to be a whole lot of 
> configuration parameters for those kinds of endpoints as they are 
> kinda like "direct" endpoints, so we can reuse the URI parameters as 
> short hand for passing in configuration/header information to the 
> protocol? 
> 
> 

yes.
I really think this adds a lot of value for non technical people (e.g.
solution consultants).
The developers would take care of configuring ProtocolBuilder 'templates'
and injecting them with global properties and middleware stuff. The solution
consultants would further enhance the Builders with 
protocol stuff using the URI parameters. 

This saves them the trouble defining beans for every variation of a
particurlar ProtocolBuilder template.

E.g.

        <route>
            <from uri="direct:start"/>
            <to uri="route:foo?foo=bar"/>
            <to uri="route:foo?foo=noBar"/>
            <to uri="mock:result"/>
        </route>

I guess you'd need to define the Builder with a prototype scope to pull
something like this off ?


Best regards,


Kristof 


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

Re: Abstracting Routes using Components

Posted by Ashwin Karpe <ak...@fusesource.com>.
Hi All,

I have started the development of this component and expect to have
something to show for in the coming weeks. 

I will open it up for comment at that time and will be happy to take further
suggestions.

Cheers,

Ashwin...

-----
---------------------------------------------------------
Ashwin Karpe
Apache Camel Committer & Sr Principal Consultant
FUSESource (a Progress Software Corporation subsidiary)
http://fusesource.com http://fusesource.com 

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

Re: Abstracting Routes using Components

Posted by James Strachan <ja...@gmail.com>.
On 28 October 2010 15:01, Ashwin Karpe <ak...@fusesource.com> wrote:
>
> Hi JStrachan,
>
>> Agreed. Protocols are just kinds of Component. My initial
>> ProtocolBuilder was a bit of a strawman focussing more on them also
>> being a RouteBuilder to get the Java DSL; but in many ways its
>> probably more important to think of them as being Components first and
>> foremost - the Spring DSL / RouteBuilder stuff is more an
>> implementation detail in how we wire those things.
>
> I couldn't agree more with what you just said. There are several potential
> ways to inject routes into the ProtocolComponent (Registry, RouteDefinition,
> RouteContext) etc. A component could solicit these as easily.
>
> It is more important that the Component and Endpoint to be a proper Camel
> entities and follow from the core building blocks. ProtocolBuilder (aka more
> specialized/extended abstract RouteBuilder) is more like developer glue/stub
> code to make the route known to the camel context...
>
> If the layering/blackboxing was unimportant we would not need a component.
> We could use the existing <routeBuilderRef> to achieve the same end...
>
> As for creating a child context per blackboxed endpoint, I am afraid, while
> we could get good encapsulation/management of individual endpoints and their
> routes, it could cause a proliferation of contexts in the JVM and be way
> more overhead if the route uses many such endpoints. This could be
> inefficient and a lot of unnecessary overhead. I am leaning towards making
> this an optional thing triggered by a URI query parameter....

Unless we figure out a way to create a really lightweight child
CamelContext which doesn't do a whole lot other than provide a naming
scope for private endpoints?

-- 
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 Ashwin Karpe <ak...@fusesource.com>.
Hi JStrachan,

> Agreed. Protocols are just kinds of Component. My initial 
> ProtocolBuilder was a bit of a strawman focussing more on them also 
> being a RouteBuilder to get the Java DSL; but in many ways its 
> probably more important to think of them as being Components first and 
> foremost - the Spring DSL / RouteBuilder stuff is more an 
> implementation detail in how we wire those things. 

I couldn't agree more with what you just said. There are several potential
ways to inject routes into the ProtocolComponent (Registry, RouteDefinition,
RouteContext) etc. A component could solicit these as easily. 

It is more important that the Component and Endpoint to be a proper Camel
entities and follow from the core building blocks. ProtocolBuilder (aka more
specialized/extended abstract RouteBuilder) is more like developer glue/stub
code to make the route known to the camel context...

If the layering/blackboxing was unimportant we would not need a component.
We could use the existing <routeBuilderRef> to achieve the same end...

As for creating a child context per blackboxed endpoint, I am afraid, while
we could get good encapsulation/management of individual endpoints and their
routes, it could cause a proliferation of contexts in the JVM and be way
more overhead if the route uses many such endpoints. This could be
inefficient and a lot of unnecessary overhead. I am leaning towards making
this an optional thing triggered by a URI query parameter....

Cheers,

Ashwin...


-----
---------------------------------------------------------
Ashwin Karpe
Apache Camel Committer & Sr Principal Consultant
FUSESource (a Progress Software Corporation subsidiary)
http://fusesource.com http://fusesource.com 

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

Re: Abstracting Routes using Components

Posted by James Strachan <ja...@gmail.com>.
On 28 October 2010 05:15, Claus Ibsen <cl...@gmail.com> wrote:
> On Wed, Oct 27, 2010 at 11:08 PM, kristofsajdak
> <kr...@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.

Agreed. Protocols are just kinds of Component. My initial
ProtocolBuilder was a bit of a strawman focussing more on them also
being a RouteBuilder to get the Java DSL; but in many ways its
probably more important to think of them as being Components first and
foremost - the Spring DSL / RouteBuilder stuff is more an
implementation detail in how we wire those things.

-- 
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 Claus Ibsen <cl...@gmail.com>.
On Wed, Oct 27, 2010 at 11:08 PM, kristofsajdak
<kr...@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/

Re: Abstracting Routes using Components

Posted by James Strachan <ja...@gmail.com>.
On 27 October 2010 22:08, kristofsajdak <kr...@gmail.com> wrote:
>
> Great feedback guys, much appreciated !

Agreed!

> 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.

Agreed.

This reminds me a little bit of how we use Components in Camel. We
want by default end users to not have to do anything at all thanks to
"convention over configuration"; components come with smart defaults.
You just add the dependency for a specific component to your pom.xml
(or use the correct archetype or whatever) and you're good to go -
there may be some dependency injection configuration required if the
defaults for the component don't quite match what you need.


So a Protocol (lets use that term for now) would be a Component as
well. Sure they are more complex (there's stuff inside! :),

A Protocol may internally use Java, Spring, Scala, Ruby or Groovy DSLs
to implement itself (but thats for the implementor of the Protocol to
choose). Then a Protocol may have a default URI scheme and smart
configuration defaults - or it can be explicitly instantiated,
configured and bound to a URI scheme name (bean ID in spring for
example) via Spring / Guice / JNDI dependency injection.

It should be pretty straight forward and the actual Protocol class
should hide as much of the implementation detail as possible so the
user of the protocol doesn't need to understand the implementation;
just like with Components today.


Once that kind of hiding is possible; it should be trivial to create,
say, an archetype using protocols A and B by having, say, a little bit
of Spring XML to configure these protocols once, then non-developers
can route into and out of these protocols easily.


> 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.

Agreed.

We can also use the same kind of tricks with Component/Endpoint as
with Protocol; i.e. if you don't use a Protocol then nothing much
happens. Even when you do use a Protocol (like using a Component),
things only really kick in when you start really using them & routing
to/from them.


> 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


Yeah. I guess usually with Component/Endpoint type stuff, we tend to
use URI parameters to configure 'middleware type stuff'; for
Protocols, maybe the URIs should be 'protocol stuff' i.e. setting
headers which can be used inside the protocol to respond differently.

Or to say that a different way; if the endpoints into and out of a
Protocol are all a simple standard kind (say the "local" endpoints
mentioned previously), there's not going to be a whole lot of
configuration parameters for those kinds of endpoints as they are
kinda like "direct" endpoints, so we can reuse the URI parameters as
short hand for passing in configuration/header information to the
protocol?


> 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");
>
>  }
> }

Great idea :). Thinking more about this, "local" tends to sound like
"local variable" or "private" really :)


> 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.

I didn't really explain it too well, let me take another stab.

A Protocol might wish to use different kinds of endpoints internally...

* middleware components (which are kinds of 'public' endpoints such as
activemq, jms, file, http etc). There is no real concept of 'hiding'
those, they are kinda real middleware stuff

* private endpoints - kinda like direct/seda but used purely inside a
protocol and private so noone else can see them

* public endpoints - used to export endpoints used inside routes to
being made public outside of the Protocol inside the
protocol/component URI schene. e.g. "public:in" inside a protocol
called "foo" would map to "foo:in" when used outside the protocol. So
a "public" endpoint is a kinda in-JVM bridge between the internals of
the protocol and the outside world.

I did wonder if we should treat things like direct/mock/seda/vm as
being 'middleware components'; as in protocols may wish to communicate
between each other or to the outside world using these kinds of
component as a kinda shared channel; then just have the public/private
endpoints when you want hiding/exporting. If we nest CamelContexts and
make direct/vm/seda purely local; there'd be no way to communicate
between protocols using those efficient non-middleware endpoints
(unless we introduce a new component that does this like "global" or
we force the global routes to route into 'public' endpoints on
protocols).

Just to throw another idea out there; maybe the mock/seda/vm/direct
type endpoints could be 'protocol nesting aware' using some naming
convention. A bit like how file systems can be absolute or relative;
maybe the URIs inside those components could have a nested-context
awareness to their names? e.g. we assume all mock/seda/vm endpoints
are absolute/global so far and we introduce a naming convention for
'private' versions of those endpoints.

But it might be we find that really to export an endpoint we want to
use 'public'; if we really want to hide an endpoint internally
'private' is all we really need; but we could go down the route of
private versions of mock/seda/vm later on if we need to?

e.g. what if "private:" prefix on a URI made a private version of that
endpoint in a nested context; so "private:foo" was syntax sugar for,
say, "private:direct:foo". Then we could have "private:seda:blah" if
we wanted to use "seda" rather than "direct"?


In summary; lots of things to think about :) but lots of stuff is
falling into place. Protocols sound like Components; we have a
consistent URI naming convention to route into and out of Protocols
and I'm liking the public/private URIs alot. Some details to be worked
out though; like do we really need nested CamelContexts's or do we
just figure out the nesting/private stuff as part of the usual URI
resolution mechanism?

-- 
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 kristofsajdak <kr...@gmail.com>.
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.

Re: Abstracting Routes using Components

Posted by Claus Ibsen <cl...@gmail.com>.
On Wed, Oct 27, 2010 at 5:54 PM, James Strachan
<ja...@gmail.com> wrote:
> On 27 October 2010 11:48, Scott England-Sullivan <su...@yahoo.com> wrote:
>> Hi all,
>>
>> Long time listener, first time caller...
>
> Welcome Scott!
>
>
>> Currently I have a similar issue on a project I am working on. Taking some hints from this discussion I am wondering if it is possible, and makes sense, to extend a Camel Context to provide the IN, OUT and ERROR Endpoints.
>>
>> Then you could nest this context inside a top level context and use nested context ID as it's namespace reference.
>>
>> {bean definition}
>> blackboxContext
>>     in
>>     out
>>     error
>>
>> routerContext
>>     from:seda
>>     to:blackboxContext
>>
>>     from:blackboxContext
>>     to:mock
>>
>> This isolates the namespaces and would allow abstraction of the desired capabilities.
>
> Agreed! I think we're all on about the same page; there's just a few
> devils in the details on exactly how this all works.
>
> * we want to wrap up a set of routes as either an Endpoint (kinda like
> the route:foo examples from Kristof which have a natural in/out type
> approach), or as a Component with internal named endpoints
>
> * we either use a "local:" component for local only endpoints inside
> nested routes; or just nest an inner CamelContext inside them to get
> the same kind of effect
>

I would assume the "local:" thing would be the easiest.

Having a nested CamelContext, we would maybe have to strip it down
from some features to keep it lighter (loading type converters, JMX
management, event notification, OSGi complexity, lifecycle etc.).



> * there are a few options as to how we should export or declare the
> 'public endpoints' for a Protocol (e.g. maybe component:in maps to
> local:in inside the route - or is there some explicit mapping of a
> public name "component:in" to some implementation endpoint URI?
>
> Maybe we just need to build a prototype of this feature and kick the
> tyres a bit and see which approaches seem to work the best?
>

Yeah kick on the tires from Kristof :)


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



-- 
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/

Re: Abstracting Routes using Components

Posted by Ashwin Karpe <ak...@fusesource.com>.
Hi All,

Based on this requirement/desire expressed by multiple users, I have added a
JIRA entry for this
https://issues.apache.org/activemq/browse/CAMEL-3285
https://issues.apache.org/activemq/browse/CAMEL-3285 

I have also assigned this to "yours truly" and will make you wish my
command... :)

Cheers,

Ashwin...

-----
---------------------------------------------------------
Ashwin Karpe
Apache Camel Committer & Sr Principal Consultant
FUSESource (a Progress Software Corporation subsidiary)
http://fusesource.com http://fusesource.com 

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

Re: Abstracting Routes using Components

Posted by James Strachan <ja...@gmail.com>.
On 27 October 2010 11:48, Scott England-Sullivan <su...@yahoo.com> wrote:
> Hi all,
>
> Long time listener, first time caller...

Welcome Scott!


> Currently I have a similar issue on a project I am working on. Taking some hints from this discussion I am wondering if it is possible, and makes sense, to extend a Camel Context to provide the IN, OUT and ERROR Endpoints.
>
> Then you could nest this context inside a top level context and use nested context ID as it's namespace reference.
>
> {bean definition}
> blackboxContext
>     in
>     out
>     error
>
> routerContext
>     from:seda
>     to:blackboxContext
>
>     from:blackboxContext
>     to:mock
>
> This isolates the namespaces and would allow abstraction of the desired capabilities.

Agreed! I think we're all on about the same page; there's just a few
devils in the details on exactly how this all works.

* we want to wrap up a set of routes as either an Endpoint (kinda like
the route:foo examples from Kristof which have a natural in/out type
approach), or as a Component with internal named endpoints

* we either use a "local:" component for local only endpoints inside
nested routes; or just nest an inner CamelContext inside them to get
the same kind of effect

* there are a few options as to how we should export or declare the
'public endpoints' for a Protocol (e.g. maybe component:in maps to
local:in inside the route - or is there some explicit mapping of a
public name "component:in" to some implementation endpoint URI?

Maybe we just need to build a prototype of this feature and kick the
tyres a bit and see which approaches seem to work the best?

-- 
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 Scott England-Sullivan <su...@yahoo.com>.
Hi all,

Long time listener, first time caller...

Currently I have a similar issue on a project I am working on. Taking some hints from this discussion I am wondering if it is possible, and makes sense, to extend a Camel Context to provide the IN, OUT and ERROR Endpoints. 

Then you could nest this context inside a top level context and use nested context ID as it's namespace reference. 

{bean definition}
blackboxContext
     in
     out
     error

routerContext
     from:seda
     to:blackboxContext

     from:blackboxContext
     to:mock

This isolates the namespaces and would allow abstraction of the desired capabilities. 

Thoughts?


Thanks,
Scott

On Oct 27, 2010, at 4:28 AM, James Strachan <ja...@gmail.com> wrote:

> Great discussion Kristof! More inline...
> 
> On 26 October 2010 22:12, kristofsajdak <kr...@gmail.com> wrote:
>> jstrachan wrote:
>>> 
>>> Or to say that a slightly different way; if you just want a
>>> parameterised RouteBuilder, well thats just a bean; no need for
>>> anything new, Camel can do that nicely today
>>> 
>> 
>> I considered using a parameterized RouteBuilder, however it failed to
>> address some specific
>> needs.
>> 
>> When using a solution based on parameterized RouteBuilders it requires you
>> to reference all
>> RouteBuilder used in the CamelContext.
>> 
>> This becomes complex when nesting route abstractions within route
>> abstractions several levels
>> deep. When using a top level RouteBuilder like
>> generateAndSignPdfRouteBuilder you are required
>> to also declare the signPdfRouteBuilder reference which exposes the
>> direct:signPdf endpoint.
>> 
>> E.g.
>> 
>>  <camelContext ...
>>    <routeBuilder ref="generateAndSignPdfRouteBuilder"/>
>>    <routeBuilder ref="signPdfRouteBuilder"/>
>>    ....
>> 
>> public class GenerateAndSignPdfRouteBuilder extends RouteBuilder {
>> 
>>    @Override
>>    public void configure() throws Exception {
>>                from("direct:generateAndSignPdf")
>>                   ...
>>                   to("direct:signPdf");
>>    }
>> 
>> }
>> 
>> public class SignPdfRouteBuilder extends RouteBuilder {
>> 
>>    @Override
>>    public void configure() throws Exception {
>>        from("direct:signPdf")
>>                        ...
>>    }
>> 
>> }
>> 
>> In other words, you would have to know how GenerateAndSignPdfRouteBuilder is
>> implemented
>> in order to use it.
> 
> 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 :)
> 
> 
>> The Route Component solution (II) doesn't require the RouteBuilders used to
>> be referenced
>> in the camelContext. It instantiates an endpoint which adds the Route
>> information to the
>> camelcontext at runtime whenever a producer or consumer is started.
>> 
>> Would this concept be available in the ProtocolBuilder construct as well ?
>> I do see the added value of using a ProtocolBuilder and declaring it as a
>> bean in spring
>> but wouldn't you need to use some kind of generic component in the middle to
>> instantiate
>> and add those builders on demand ?
>> 
>> E.g.
>> 
>>        <route>
>>            <from uri="route:standardActions://out"/>
>>            <to uri="route:generateAndSignPdf://in"/>
>>            <to uri="mock:result"/>
>>        </route>
>> 
>> Another reason why I didn't consider the Parameterized RouteBuilder is the
>> risk of name clashes
>> . When nesting components several levels deep and/or reusing the same
>> RouteBuilder beans multiple times
>>  yet with different properties, this could lead to impredictable behaviour
>> when direct endpoints and routeIds are not unique within the CamelContext.
> 
> 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.
> 
> 
> 
>> jstrachan wrote:
>>> 
>>> ii) a parameterized RouteBuilder which is dependency injected using a
>>> URI (which is kinda like Kristof's example code
>>> 
>> 
>> Yeah, maybe the implementation of the RouteEndpoint class is somewhat
>> clumsy, but what I am trying to
>> do here is to pass header values to the nested route.
>> 
>> Normally you would go about this using the setHeader statement, however this
>> is quite verbose when
>> using xml dsl.
>> 
>>           <setHeader headerName="signatureReason">
>>                <constant>JustForFun</constant>
>>            </setHeader>
>>            <setHeader headerName="signatureVisible">
>>                <constant>true</constant>
>>            </setHeader>
>>            <setHeader headerName="xslUri">
>> 
>> <constant>com/xti/poc/camel/route/sample1/krusty.xsl</constant>
>>            </setHeader>
>> 
>> That's why I figured i'd use the uri parameters to have some kind of
>> shorthand notation for assigning
>> header values.
>> 
>> ?signatureReason=JustForFun&signatureVisible=true&xslUri=com/xti/poc/camel/route/sample1/krusty.xsl
> 
> Ah sorry - I misunderstood. (Bad James, should have read your code
> more closely).
> 
> Thats a pretty neat idea. Given that the 'local' endpoints I mention
> above would be pretty simple things; we could maybe do something
> similar in the ProtocolBuilder idea?
> 
> 
> 
>> Maybe the implementation would be cleaner if properties are used only for
>> dependency injection.
>> The shorthand notation could define an interceptor on the from of the target
>> RouteBuilder. The interceptor could then populate the headers
>> when the exchange comes in.
> 
> Or the setting of headers could be done inside the ProtocolBuilder's
> configure() method? So its hidden inside the implementation detail of
> the ProtocolBuilder, then folks wiring A and B together don't need to
> worry about that kinda thing?
> 
> -- 
> 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 James Strachan <ja...@gmail.com>.
Great discussion Kristof! More inline...

On 26 October 2010 22:12, kristofsajdak <kr...@gmail.com> wrote:
> jstrachan wrote:
>>
>> Or to say that a slightly different way; if you just want a
>> parameterised RouteBuilder, well thats just a bean; no need for
>> anything new, Camel can do that nicely today
>>
>
> I considered using a parameterized RouteBuilder, however it failed to
> address some specific
> needs.
>
> When using a solution based on parameterized RouteBuilders it requires you
> to reference all
> RouteBuilder used in the CamelContext.
>
> This becomes complex when nesting route abstractions within route
> abstractions several levels
> deep. When using a top level RouteBuilder like
> generateAndSignPdfRouteBuilder you are required
> to also declare the signPdfRouteBuilder reference which exposes the
> direct:signPdf endpoint.
>
> E.g.
>
>  <camelContext ...
>    <routeBuilder ref="generateAndSignPdfRouteBuilder"/>
>    <routeBuilder ref="signPdfRouteBuilder"/>
>    ....
>
> public class GenerateAndSignPdfRouteBuilder extends RouteBuilder {
>
>    @Override
>    public void configure() throws Exception {
>                from("direct:generateAndSignPdf")
>                   ...
>                   to("direct:signPdf");
>    }
>
> }
>
> public class SignPdfRouteBuilder extends RouteBuilder {
>
>    @Override
>    public void configure() throws Exception {
>        from("direct:signPdf")
>                        ...
>    }
>
> }
>
> In other words, you would have to know how GenerateAndSignPdfRouteBuilder is
> implemented
> in order to use it.

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 :)


> The Route Component solution (II) doesn't require the RouteBuilders used to
> be referenced
> in the camelContext. It instantiates an endpoint which adds the Route
> information to the
> camelcontext at runtime whenever a producer or consumer is started.
>
> Would this concept be available in the ProtocolBuilder construct as well ?
> I do see the added value of using a ProtocolBuilder and declaring it as a
> bean in spring
> but wouldn't you need to use some kind of generic component in the middle to
> instantiate
> and add those builders on demand ?
>
> E.g.
>
>        <route>
>            <from uri="route:standardActions://out"/>
>            <to uri="route:generateAndSignPdf://in"/>
>            <to uri="mock:result"/>
>        </route>
>
> Another reason why I didn't consider the Parameterized RouteBuilder is the
> risk of name clashes
> . When nesting components several levels deep and/or reusing the same
> RouteBuilder beans multiple times
>  yet with different properties, this could lead to impredictable behaviour
> when direct endpoints and routeIds are not unique within the CamelContext.

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.



> jstrachan wrote:
>>
>> ii) a parameterized RouteBuilder which is dependency injected using a
>> URI (which is kinda like Kristof's example code
>>
>
> Yeah, maybe the implementation of the RouteEndpoint class is somewhat
> clumsy, but what I am trying to
> do here is to pass header values to the nested route.
>
> Normally you would go about this using the setHeader statement, however this
> is quite verbose when
> using xml dsl.
>
>           <setHeader headerName="signatureReason">
>                <constant>JustForFun</constant>
>            </setHeader>
>            <setHeader headerName="signatureVisible">
>                <constant>true</constant>
>            </setHeader>
>            <setHeader headerName="xslUri">
>
> <constant>com/xti/poc/camel/route/sample1/krusty.xsl</constant>
>            </setHeader>
>
> That's why I figured i'd use the uri parameters to have some kind of
> shorthand notation for assigning
> header values.
>
> ?signatureReason=JustForFun&signatureVisible=true&xslUri=com/xti/poc/camel/route/sample1/krusty.xsl

Ah sorry - I misunderstood. (Bad James, should have read your code
more closely).

Thats a pretty neat idea. Given that the 'local' endpoints I mention
above would be pretty simple things; we could maybe do something
similar in the ProtocolBuilder idea?



> Maybe the implementation would be cleaner if properties are used only for
> dependency injection.
> The shorthand notation could define an interceptor on the from of the target
> RouteBuilder. The interceptor could then populate the headers
> when the exchange comes in.

Or the setting of headers could be done inside the ProtocolBuilder's
configure() method? So its hidden inside the implementation detail of
the ProtocolBuilder, then folks wiring A and B together don't need to
worry about that kinda thing?

-- 
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 kristofsajdak <kr...@gmail.com>.

jstrachan wrote:
> 
> Or to say that a slightly different way; if you just want a 
> parameterised RouteBuilder, well thats just a bean; no need for 
> anything new, Camel can do that nicely today
> 

I considered using a parameterized RouteBuilder, however it failed to
address some specific 
needs. 

When using a solution based on parameterized RouteBuilders it requires you
to reference all 
RouteBuilder used in the CamelContext.

This becomes complex when nesting route abstractions within route
abstractions several levels 
deep. When using a top level RouteBuilder like
generateAndSignPdfRouteBuilder you are required 
to also declare the signPdfRouteBuilder reference which exposes the
direct:signPdf endpoint.

E.g.

 <camelContext ...
    <routeBuilder ref="generateAndSignPdfRouteBuilder"/> 
    <routeBuilder ref="signPdfRouteBuilder"/>
    ....

public class GenerateAndSignPdfRouteBuilder extends RouteBuilder {

    @Override
    public void configure() throws Exception {
                from("direct:generateAndSignPdf")
		   ...
		   to("direct:signPdf");
    }

}

public class SignPdfRouteBuilder extends RouteBuilder {

    @Override
    public void configure() throws Exception {
        from("direct:signPdf")
                        ...
    }

}

In other words, you would have to know how GenerateAndSignPdfRouteBuilder is
implemented
in order to use it. 

The Route Component solution (II) doesn't require the RouteBuilders used to
be referenced
in the camelContext. It instantiates an endpoint which adds the Route
information to the 
camelcontext at runtime whenever a producer or consumer is started.

Would this concept be available in the ProtocolBuilder construct as well ? 
I do see the added value of using a ProtocolBuilder and declaring it as a
bean in spring 
but wouldn't you need to use some kind of generic component in the middle to
instantiate 
and add those builders on demand ? 

E.g.

 	<route> 
            <from uri="route:standardActions://out"/> 
            <to uri="route:generateAndSignPdf://in"/> 
            <to uri="mock:result"/> 
        </route> 
   
Another reason why I didn't consider the Parameterized RouteBuilder is the
risk of name clashes
. When nesting components several levels deep and/or reusing the same
RouteBuilder beans multiple times
 yet with different properties, this could lead to impredictable behaviour
when direct endpoints and routeIds are not unique within the CamelContext.


jstrachan wrote:
> 
> ii) a parameterized RouteBuilder which is dependency injected using a 
> URI (which is kinda like Kristof's example code
> 

Yeah, maybe the implementation of the RouteEndpoint class is somewhat
clumsy, but what I am trying to
do here is to pass header values to the nested route.

Normally you would go about this using the setHeader statement, however this
is quite verbose when
using xml dsl. 

	   <setHeader headerName="signatureReason"> 
                <constant>JustForFun</constant> 
            </setHeader> 
            <setHeader headerName="signatureVisible"> 
                <constant>true</constant> 
            </setHeader> 
            <setHeader headerName="xslUri"> 
               
<constant>com/xti/poc/camel/route/sample1/krusty.xsl</constant> 
            </setHeader> 

That's why I figured i'd use the uri parameters to have some kind of
shorthand notation for assigning 
header values.

?signatureReason=JustForFun&signatureVisible=true&xslUri=com/xti/poc/camel/route/sample1/krusty.xsl

Maybe the implementation would be cleaner if properties are used only for
dependency injection.
The shorthand notation could define an interceptor on the from of the target 
RouteBuilder. The interceptor could then populate the headers 
when the exchange comes in.


Best regards,


Kristof



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

Re: Abstracting Routes using Components

Posted by James Strachan <ja...@gmail.com>.
Hi Kristof

BTW I raised a thread on the dev list to describe our chat...
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

On 24 October 2010 22:19, kristofsajdak <kr...@gmail.com> wrote:
>
> Hi,
>
> I'm currently working on a poc for a customer.
>
> As part of their core business they offer a platform which mediates between
> trading partners.
> What is special about their use case is the fact that they want the actual
> routes between
> partners to be defined by employees with limited technical knowledge
> (solution consultants).
>
> I know there is the xml dsl and the upcoming camel rider which lowers the
> threshold for non developers.
> But even when using these features, the route configuration would be way too
> fine grained for them and
> they would still require too much knowledge on the details of the technical
> components.
>
> Last week I was at the FUSE community day in Paris and spoke to James
> Strachan on the customer
> need to abstract some parts of the routes. He mentioned the idea of using a
> component as a kind
> of proxy for a route.
>
> I believe this is a real nice solution to the problem.
> A complex route were a pdf is generated from an xml using xslt and fop and
> the result is signed using a
> third party service exposed over http could be reduced to the following.
>
>        <route>
>            <from uri="{{data.in}}"/>
>            <to
> uri="route:generateAndSignPdf?signatureReason=JustForFun&amp;signatureVisible=true&amp;xslUri=com/xti/poc/camel/route/sample1/krusty.xsl"/>
>            <to uri="{{data.out}}"/>
>        </route>
>
> The route component concept abstracts the route low level technical details
> and makes reuse easy.
> The solution consultant only needs to define the route:generateAndSignPdf
> with the correct parameters.
>
> As this construct would provide great value to the customer I went ahead and
> implemented this idea as part of the poc. Attached to this post is my
> codebase with a unit test executing the scenario mentioned above.
>
> I would really appreciate some feedback from the community on the code I
> wrote.
> I tried fitting this in with the component lifecycle the best I could but
> still have some doubts on whether it's done correct.
>
> Getting an expert opinion on this would be a big help.

Great stuff Kristof!

I also met a bunch of folks at the recent FuseDay in Washington who
had similar ideas and use cases too; this general approach and idea
seems to be gaining momentum.

I think its going to be increasingly common to take some routes, wrap
them up in a 'black box' as a 'Protocol' that can then be handed off
to other users/scenarios which are then configured and/or routed into
or out of.

As I mentioned in the previous thread...
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

I like the idea of using a component instance for each 'black box' (or
protocol lets say); as this then provides a nice name scoping for
endpoints.

For example imagine if the "generateAndSignPdf" protocol had a single
input ("in") and a default output ("out")  along with a failure
endpoint ("err") - then we have in/out/err like unix pipes.  (Note a
protocol could have a completely arbitrary number of inputs and output
endpoints - am just thinking the in/out/err are common)...

You could then wire into the black box as...

<!-- we can route from multiple physical endpoints to the logical
input endpoint... -->

<route>
  <from uri="activemq:SomeInputQueue"/>
  <to uri="generateAndSignPdf://in"/>
</route>
<route>
  <from uri="file://someDir/foo"/>
  <to uri="generateAndSignPdf://in"/>
</route>

If you then wanted to process the output of the protocol...

<route>
  <from uri="generateAndSignPdf://out"/>
  <to uri="activemq:SomethingOrOther"/>
</route>

In this example we're hiding the protocol behind a component URI
naming convention and we can then refer to the logical exported
endpoints by name which then map to actual physical endpoints. If the
black box were totally stand alone & it wasn't intended for Camel to
route into/out of it, then you might as well just make this protocol a
bean...

<bean id="foo" class="com.acme.MyRouteBuilder">
  <!-- lets configure the endpoints used in the route builder... -->
  <property name="in" vallue="activemq:UseThisInputQueue"/>
   ...


Or to say that a slightly different way; if you just want a
parameterised RouteBuilder, well thats just a bean; no need for
anything new, Camel can do that nicely today. Whats different about
this idea of "Protocols" and a ProtocolBuilder is the idea we can add
the ability to expose endpoints within the namespace of the
component/bean which you can route to outside of the Protocol. So its
not just a black box; its a black box with defined public connector
endpoints folks can route to without needing to understand any
knowledge of whats inside.

As Willem mentioned on the previous thread; we could have a single
component for these 'protocols'; though given the simplicity and URI
naming simplicity; I'm preferring to combine the RouteBuilder and
Component together into a single bean - which can then be configured
using Dependency Injection, but can also expose arbitrary logical URIs
which lets other folks route into and between these Protocols

e.g. we can create many instances of protocols; each get their own
unique URI scheme in Camel and we can easily refer to the in/out/err
of those protocols (if they use a standard shape of input/outputs).

-- 
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 Ryadh Amar <ry...@gmail.com>.
Ah I understand better now :D
But the way I see it, if you could work out more complex stuff in your
routes (other than setting headers), things become more interesting.
But at the end of the day, this proposal will make things easier for the
developer community, I think the business analyst types will be more
inclined to use tools to compose the routes.
I have to confess I didn't checkout your updated test cases, which I will do
gladly after work.
-- 
View this message in context: http://camel.465427.n5.nabble.com/Abstracting-Routes-using-Components-tp3234703p3237148.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/

Re: Abstracting Routes using Components

Posted by kristofsajdak <kr...@gmail.com>.

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 kristofsajdak <kr...@gmail.com>.

I agree that what is available in Camel out of the box is not far from what
I want to achieve, but for this particurlar use case it means a big
difference.

Just compare the first solution (1.) I came up with using direct endpoints
(is this the proxy pattern you are referring to ?) with the route component
one (2.) 

1.   

<bean id="generateAndSignPdfRouteBuilder"
class="com.xti.poc.camel.route.sample2.GenerateAndSignPdfRouteBuilder"/>
    <bean id="signPdfRouteBuilder"
class="com.xti.poc.camel.route.sample2.SignPdfRouteBuilder"/>

    <camelContext id="sample-1"
xmlns="http://camel.apache.org/schema/spring">

        <routeBuilder ref="generateAndSignPdfRouteBuilder"/>
        <routeBuilder ref="signPdfRouteBuilder"/>
        <route>
            <from uri="direct:start"/>
            <setHeader headerName="signatureReason">
                <constant>JustForFun</constant>
            </setHeader>
            <setHeader headerName="signatureVisible">
                <constant>true</constant>
            </setHeader>
            <setHeader headerName="xslUri">
               
<constant>com/xti/poc/camel/route/sample1/krusty.xsl</constant>
            </setHeader>
            <to uri="direct:generateAndSignPdf"/>
            <to uri="mock:result"/>
        </route>

    </camelContext>

2.

    <camelContext id="sample-1"
xmlns="http://camel.apache.org/schema/spring">

        <route>
            <from uri="direct:start"/>
            <to
uri="route:generateAndSignPdf?signatureReason=JustForFun&amp;signatureVisible=true&amp;xslUri=com/xti/poc/camel/route/sample1/krusty.xsl"/>
            <to uri="mock:result"/>
        </route>

    </camelContext>

The route component solution (2.) doesn't require me to include the
references to the routeBuilders used in the camelcontext (this gets more
complex when you are nesting routes within routes), neither do I have to
copy the headers in a verbose way. Using the url parameters is a much more
elegant solution in this case.

Another reason to use route components is because it allows you to create
parameterizable route abstractions which can be used as a from endpoint.

Take a look at the snippet below where the route is using a route component
to abstract the following actions : receive from direct:start, set the foo
header to the value specified by the parameter and pass the message on to
the next processor in the route. 

        <route>
            <from uri="route:standardActions?foo=Bar"/>
            <to
uri="route:generateAndSignPdf?signatureReason=JustForFun&amp;signatureVisible=true&amp;xslUri=com/xti/poc/camel/route/sample1/krusty.xsl"/>
            <to uri="mock:result"/>
        </route>


I know this is a naive example but at the customer we came up with some
really meaningful abstractions, shielding the solution consultant from
technical details. 

I attached a new version of the codebase to this post, it contains both
solutions + tests so you can easily compare.

Best regards,

Kristof

http://camel.465427.n5.nabble.com/file/n3236211/camel-route-solution1and2.zip
camel-route-solution1and2.zip 



   

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

Re: Abstracting Routes using Components

Posted by Ryadh Amar <ry...@gmail.com>.
This is a pretty neat idea, I was actually around when you were explaining
your need.
Thing is we are not really far from what you want to achieve if we use the
bean component or if the proxy pattern is applied.
It all boils down the extent to which you want to make things easier for the
users.
But why wouldn't you just build a component?

-- 
View this message in context: http://camel.465427.n5.nabble.com/Abstracting-Routes-using-Components-tp3234703p3235270.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

Just wanted to say great work and a nice debate you have started.

I have only had the time to skim read, but so many great minds is
already debating this.
So keep in there and I am sure we will get some great new feature in
Camel based on your work.



On Sun, Oct 24, 2010 at 11:19 PM, kristofsajdak
<kr...@gmail.com> wrote:
>
> Hi,
>
> I'm currently working on a poc for a customer.
>
> As part of their core business they offer a platform which mediates between
> trading partners.
> What is special about their use case is the fact that they want the actual
> routes between
> partners to be defined by employees with limited technical knowledge
> (solution consultants).
>
> I know there is the xml dsl and the upcoming camel rider which lowers the
> threshold for non developers.
> But even when using these features, the route configuration would be way too
> fine grained for them and
> they would still require too much knowledge on the details of the technical
> components.
>
> Last week I was at the FUSE community day in Paris and spoke to James
> Strachan on the customer
> need to abstract some parts of the routes. He mentioned the idea of using a
> component as a kind
> of proxy for a route.
>
> I believe this is a real nice solution to the problem.
> A complex route were a pdf is generated from an xml using xslt and fop and
> the result is signed using a
> third party service exposed over http could be reduced to the following.
>
>        <route>
>            <from uri="{{data.in}}"/>
>            <to
> uri="route:generateAndSignPdf?signatureReason=JustForFun&amp;signatureVisible=true&amp;xslUri=com/xti/poc/camel/route/sample1/krusty.xsl"/>
>            <to uri="{{data.out}}"/>
>        </route>
>
> The route component concept abstracts the route low level technical details
> and makes reuse easy.
> The solution consultant only needs to define the route:generateAndSignPdf
> with the correct parameters.
>
> As this construct would provide great value to the customer I went ahead and
> implemented this idea as part of the poc. Attached to this post is my
> codebase with a unit test executing the scenario mentioned above.
>
> I would really appreciate some feedback from the community on the code I
> wrote.
> I tried fitting this in with the component lifecycle the best I could but
> still have some doubts on whether it's done correct.
>
> Getting an expert opinion on this would be a big help.
>
>
> Best regards,
>
>
> Kristof
>
> http://camel.465427.n5.nabble.com/file/n3234703/camel-route.zip
> camel-route.zip
> --
> View this message in context: http://camel.465427.n5.nabble.com/Abstracting-Routes-using-Components-tp3234703p3234703.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/