You are viewing a plain text version of this content. The canonical link for it is here.
Posted to users@camel.apache.org by klausb <kl...@hp.com> on 2010/12/14 12:04:47 UTC

How to setup a dynamic route using beans in Java w/o having a spring ref to them?

I want to configure routing by an external configuration file.
The routes are made of beans, which register themselves using the
spring/osgi registry.
Now the route builder, made with the Java DSL, wants to use the beans
without knowing them in advance. That is, they are not configured in the
spring config of the route component.
My understanding is, that I cannot use "bean:myBean" URI without having
myBean declared as osgi:reference in a corresponding spring xml file. 

Is there a way to use such a bean, by doing the osgi-resgistry lookup
programatically?

klaus.
-- 
View this message in context: http://camel.465427.n5.nabble.com/How-to-setup-a-dynamic-route-using-beans-in-Java-w-o-having-a-spring-ref-to-them-tp3304398p3304398.html
Sent from the Camel - Users mailing list archive at Nabble.com.

Re: How to setup a dynamic route using beans in Java w/o having a spring ref to them?

Posted by Jesús Castillo <je...@gmail.com>.
Hi Klaus,

the main problem with the solutions proposed is that either you need
to modify the
OSGi service registry or you need to make some changes in the Camel
bean component.


What I did was decouple the Camel route from the the bean registered in OSGi by
using the Observer pattern. The Observable or Subject is added to the
Camel route and the Observers are exposed as OSGi services and injected
dynamically by Spring to the list of Observers. In this way, Camel
knows about the
bean in Advance but does not anything about the services registered in OSGi.

By the same token, the OSGi services don't know anything about Camel Routes.

This is a sample test code:

The Observable:

{code}

package example;

public class RouteServiceProvider {

    private static final Logger LOG =
LoggerFactory.getLogger(RouteServiceProvider.class);
	
	List<Provider> providers = new ArrayList<Provider>();

	protected final Provider defaultProvider = new DefaultProvider();
	
	/**
	 * @return the providers
	 */
	public List<Provider> getProviders() {
		return providers;
	}

	/**
	 * @param providers the providers to set
	 */
	public void setProviders(List<Provider> providers) {
		this.providers = providers;
	}
	
	public final void handleRequest(Map<String,String> headers) {
		LOG.debug("RouteServiceProvider :: handleRequest() invoked");
		doHandleRequest(headers);
		// Call Providers
		for (Provider provider : providers) {
			if (provider.requestReceived(headers)){
				return;
			}				
		}	
		// Invoke the Default provider if not provider found
		LOG.info("RouteServiceProvider :: No Provider was suitable. Calling
the Default provider");
		defaultProvider.requestReceived(headers);
	}	
	
	protected void doHandleRequest(Map<String,?> headers) {
		//	Do some actions before calling providers		
	}
	
{code}

The providers(observers):

{code}
public interface Provider {
	public boolean requestReceived(Map<String, String> headers);
}

public class DefaultProvider implements Provider {

    private static final Logger LOG =
LoggerFactory.getLogger(DefaultProvider.class);
	
	@Override
	public boolean requestReceived(Map<String, String> headers) {
		LOG.info("Default provider is handling the request");
		headers.put("requestType", "DEFAULT");
		return false;
	}

}

public class LocalProvider implements Provider {

    private static final Logger LOG =
LoggerFactory.getLogger(LocalProvider.class);
	
	@Override
	public boolean requestReceived(Map<String, String> headers) {
		LOG.debug("Local provider is handling the request");
		headers.put("requestType", "LOCAL");
		return false; //true means I managed the request.
	}

}

{code}

The service is registered in OSGi as.

  <bean id="localProvider" class="example.impl.LocalProvider">
  </bean>

  <osgi:service ref="localProvider" interface="example.Provider"/>



The services are referenced as as:

  <bean id="routeServiceProvider" class="example.RouteServiceProvider">
    <property name="providers" ref="providers"/>
  </bean>

  <osgi:list id="providers"
  	interface="example.Provider" cardinality="0..N" />

The Camel route looks like:

		from("direct:start")
			.to("bean:routeServiceProvider?method=handleRequest")
	                .to("mock:result");		


This solution is purely based on POJO classes and no need to
create special components in OSGi or Camel.

Regards,

Jesus.

Re: How to setup a dynamic route using beans in Java w/o having a spring ref to them?

Posted by klausb <kl...@hp.com>.
Hi Jesus,

it's not a burning issue any longer (for me), but I'm still curious.
So if you could sketch your solution, that would be helpful. I can imagine,
picking up this approach again in future projects.

Regards,
klaus.

--
View this message in context: http://camel.465427.n5.nabble.com/How-to-setup-a-dynamic-route-using-beans-in-Java-w-o-having-a-spring-ref-to-them-tp3304398p4912687.html
Sent from the Camel - Users mailing list archive at Nabble.com.

Re: How to setup a dynamic route using beans in Java w/o having a spring ref to them?

Posted by Jesus Castillo <je...@gmail.com>.
Hi All,

is this still an issue?

I ran into the same situation and found out a way of deal with this 
without changing Camel, writing new features or dealing with the
OSGi registry.

Le me know.

Jesus.

--
View this message in context: http://camel.465427.n5.nabble.com/How-to-setup-a-dynamic-route-using-beans-in-Java-w-o-having-a-spring-ref-to-them-tp3304398p4910638.html
Sent from the Camel - Users mailing list archive at Nabble.com.

Re: How to setup a dynamic route using beans in Java w/o having a spring ref to them?

Posted by ext2 <xu...@tongtech.com>.
Hi, Willem Jiang:
	I think maybe the feature is not very ease to add; 
	Although we can temporary change the code of OSGIServiceRegistry to
enable osgi service filter. But the solution has such disadvantages:
	1) the bean-name will be ugly , because it contains not only the
service class name , but also the filter express. The format of bean-name is
un-usual; maybe: if we list the filter express in uri parameters, things
will be better; 

	2) camel bean's lifecycle is assumed statically. But OSGI services
is not so; It maybe dynamically, or be-not-ready when camel route started;
So if we still rely on bean-endpoint to invoke OSGI service, things will be
wrong if service is not static;
	I think the correct solution should be : introduce another component
(OSGI Component) to dynamically invoke osgi services; not to just change
Camel's  OSGI-Registry;

-----Original -----
Sender: Willem Jiang [mailto:willem.jiang@gmail.com] 
Date: 2010/12/16 20:07
Receiver: users@camel.apache.org
Subject: Re: How to setup a dynamic route using beans in Java w/o having a
spring ref to them?

Yes, Current Camel OSGi registry just grab the service from OSGi service 
registry, it doesn't support the filter.

I think this feature is easy to add and please don't hesitate to 
contribute your patch.

On 12/16/10 7:25 PM, ext2 wrote:
> Camel Osgi registry doesn't support filter for services;
>
> You'd better write your own processor to locate osgi services; it's not so
> sophisticated , just do some  reflecting works;
>
> But if you do wish to use camel bean's features, the only way I know is
> change the source code of CamelOsgiRegistry to support osgi service
filter;
> (it's unfortunately) then you can use recipient list to dynamic create a
> endpoint to invoke osgi service;
>
> -----Original-----
> Sender: klausb [mailto:klaus.baumecker@hp.com]
> Date: 2010/12/16 17:47
> Receiver: users@camel.apache.org
> Subject: Re: How to setup a dynamic route using beans in Java w/o having a
> spring ref to them?
>
>
> Hi Sebastian,
>
> thanks for the good explaination. However I do not have a problem with a
> dynamic bean activation as such.
> I was rather asking for a method to avoid the osgi reference tag, because
> the wiring-component, that creates the routes from an external config
should
> not know about the beans in advance. Which is the case, if I have to
> register all the potential beans in the spring file.
>
> klaus


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



Re: How to setup a dynamic route using beans in Java w/o having a spring ref to them?

Posted by Willem Jiang <wi...@gmail.com>.
Yes, Current Camel OSGi registry just grab the service from OSGi service 
registry, it doesn't support the filter.

I think this feature is easy to add and please don't hesitate to 
contribute your patch.

On 12/16/10 7:25 PM, ext2 wrote:
> Camel Osgi registry doesn't support filter for services;
>
> You'd better write your own processor to locate osgi services; it's not so
> sophisticated , just do some  reflecting works;
>
> But if you do wish to use camel bean's features, the only way I know is
> change the source code of CamelOsgiRegistry to support osgi service filter;
> (it's unfortunately) then you can use recipient list to dynamic create a
> endpoint to invoke osgi service;
>
> -----Original-----
> Sender: klausb [mailto:klaus.baumecker@hp.com]
> Date: 2010/12/16 17:47
> Receiver: users@camel.apache.org
> Subject: Re: How to setup a dynamic route using beans in Java w/o having a
> spring ref to them?
>
>
> Hi Sebastian,
>
> thanks for the good explaination. However I do not have a problem with a
> dynamic bean activation as such.
> I was rather asking for a method to avoid the osgi reference tag, because
> the wiring-component, that creates the routes from an external config should
> not know about the beans in advance. Which is the case, if I have to
> register all the potential beans in the spring file.
>
> klaus


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

Re: How to setup a dynamic route using beans in Java w/o having a spring ref to them?

Posted by ext2 <xu...@tongtech.com>.
Camel Osgi registry doesn't support filter for services;

You'd better write your own processor to locate osgi services; it's not so
sophisticated , just do some  reflecting works;

But if you do wish to use camel bean's features, the only way I know is
change the source code of CamelOsgiRegistry to support osgi service filter;
(it's unfortunately) then you can use recipient list to dynamic create a
endpoint to invoke osgi service;

-----Original-----
Sender: klausb [mailto:klaus.baumecker@hp.com] 
Date: 2010/12/16 17:47
Receiver: users@camel.apache.org
Subject: Re: How to setup a dynamic route using beans in Java w/o having a
spring ref to them?


Hi Sebastian,

thanks for the good explaination. However I do not have a problem with a
dynamic bean activation as such.
I was rather asking for a method to avoid the osgi reference tag, because
the wiring-component, that creates the routes from an external config should
not know about the beans in advance. Which is the case, if I have to
register all the potential beans in the spring file.

klaus
-- 
View this message in context:
http://camel.465427.n5.nabble.com/How-to-setup-a-dynamic-route-using-beans-i
n-Java-w-o-having-a-spring-ref-to-them-tp3304398p3307652.html
Sent from the Camel - Users mailing list archive at Nabble.com.



Re: How to setup a dynamic route using beans in Java w/o having a spring ref to them?

Posted by klausb <kl...@hp.com>.
Hi Sebastian,

thanks for the good explaination. However I do not have a problem with a
dynamic bean activation as such.
I was rather asking for a method to avoid the osgi reference tag, because
the wiring-component, that creates the routes from an external config should
not know about the beans in advance. Which is the case, if I have to
register all the potential beans in the spring file.

klaus
-- 
View this message in context: http://camel.465427.n5.nabble.com/How-to-setup-a-dynamic-route-using-beans-in-Java-w-o-having-a-spring-ref-to-them-tp3304398p3307652.html
Sent from the Camel - Users mailing list archive at Nabble.com.

Re: How to setup a dynamic route using beans in Java w/o having a spring ref to them?

Posted by Sebastian Münz <se...@catify.com>.
Maybe the recipientList pattern is a solution for you in order to make 
your route dynamic.

Write the bean(s) you would like to call in the exchange header and 
that's it :)

Example:

MockEndpoint mockEndpoint = context.getEndpoint("mock:end", 
MockEndpoint.class);
assertNotNull(mockEndpoint);
mockEndpoint.expectedMessageCount(1);
       
context.addRoutes(new SpringRouteBuilder() {
           
  @Override
  public void configure() throws Exception {
               
     from("direct:startTest")
     .recipientList(header("destinations"), ",");
                   
  }
});
       
// destinations is the header variable name
context.createProducerTemplate().sendBodyAndHeader("direct:startTest", 
"testbody", "destinations", 
"bean:myBean?method=collect,bean:yourBean?method=collect,mock:end");
mockEndpoint.assertIsSatisfied(2000);

In this case it doesn't matter wheter the beans implements an interface 
or not. Just send the bean (and method if wished) you would like to call 
as a header variable.
The beans must be registered in spring's application context in your 
case or referenced by osgi reference tag like your description before.

Hope this helps...

Sebastian



klausb schrieb:
> Now I'm puzzled.
>
> Did you say, that a bean is identified by its interface only?
>
> How can I setup a route that uses different beans, where all beans implement
> the same interface?
>
> klaus.
>   

Re: How to setup a dynamic route using beans in Java w/o having a spring ref to them?

Posted by ext2 <xu...@tongtech.com>.
Yes, camel 's OSGIServiceRegistry doesn't support filter yet;
If your services use same interface, I think recipient list pattern cannot
be used, directly;

Maybe you can write a custom processor to invoke osgi services by your self;

But if you really like the bean feature supported by camel, you can
temporary change the source code of
rg.apache.camel.core.osgi.OsgiServiceRegistry.java which exists in
camel-core-osgi component;

For example: you can use a special split character in beanName to split
osgi-service-class and filter condition; so the uri format may looks like
as:
"bean:test.TestClass|attr=xxx?method=.... "
(I don't know if "|" can safely used in the uri , you can try it  or some
other character)

And in OsgiServiceRegistry: you can change the source code , parse  the
split character in bean name to get osgi-service-name and filter;


But anyway, this is only a temporary method; I don't know when camel will
support osgi service ; the temporary method has such disadvantage:
osgi-service must be started already, and cannot be dynamic;








-----Original-----
Sender: klausb [mailto:klaus.baumecker@hp.com] 
Date: 2010/12/16 0:42
Receiver: users@camel.apache.org
Subject: Re: How to setup a dynamic route using beans in Java w/o having a
spring ref to them?


Now I'm puzzled.

Did you say, that a bean is identified by its interface only?

How can I setup a route that uses different beans, where all beans implement
the same interface?

klaus.
-- 
View this message in context:
http://camel.465427.n5.nabble.com/How-to-setup-a-dynamic-route-using-beans-i
n-Java-w-o-having-a-spring-ref-to-them-tp3304398p3306580.html
Sent from the Camel - Users mailing list archive at Nabble.com.



Re: How to setup a dynamic route using beans in Java w/o having a spring ref to them?

Posted by klausb <kl...@hp.com>.
Now I'm puzzled.

Did you say, that a bean is identified by its interface only?

How can I setup a route that uses different beans, where all beans implement
the same interface?

klaus.
-- 
View this message in context: http://camel.465427.n5.nabble.com/How-to-setup-a-dynamic-route-using-beans-in-Java-w-o-having-a-spring-ref-to-them-tp3304398p3306580.html
Sent from the Camel - Users mailing list archive at Nabble.com.

Re: How to setup a dynamic route using beans in Java w/o having a spring ref to them?

Posted by ext2 <xu...@tongtech.com>.
Sorry, forget to say, in osgi registry, the name of service(bean) is the
osgi service's class name; that's to say to using "to" endpoint to invoke a
osgi service is not like to invoke a spring bean. It should use the class as
name , not the id like spring registry does;

By the way, if you osgi service is dynamic while camel is running, you
cannot use the osgi registry safely, because camel doesn't tracking the osgi
service correctly (at least in camel 2.4.0)

===========================================================================
Trying recipient-list pattern(dynamic to create to endpoint to invoke beans
in registry), it will look registry of osgi first(Clause has already said )

-----original -----
Sender: klausb [mailto:klaus.baumecker@hp.com] 
Date: 2010/12/14 23:31
Sender: users@camel.apache.org
Subject: Re: How to setup a dynamic route using beans in Java w/o having a
spring ref to them?


Hi Claus,

I tried it, but it doesn't work.

The point is, that my dynamic Java-DSL route-builder does not know, what the
IDs of the beans are, which are added to the routes. It works, if I'm adding
the osgi:ref to one of the spring resource files, like this:

<osgi:reference id="myBean" interface="com.corp.MyIF"/>

Without this line, the bean is not found inside a bean step like this:

.to("bean:${beanName}?method=collect"),

where beanName=myBean. This is the dynamic part of this route-builder
(Groovy string).

What I'm looking for is a way to do the lookup like <osgi:ref...> statement
in my Java code during route construction.

klaus.
-- 
View this message in context:
http://camel.465427.n5.nabble.com/How-to-setup-a-dynamic-route-using-beans-i
n-Java-w-o-having-a-spring-ref-to-them-tp3304398p3304754.html
Sent from the Camel - Users mailing list archive at Nabble.com.






Re: How to setup a dynamic route using beans in Java w/o having a spring ref to them?

Posted by ext2 <xu...@tongtech.com>.
Trying recipient-list pattern(dynamic to create to endpoint to invoke beans
in registry), it will look registry of osgi first(Clause has already said )

-----original -----
Sender: klausb [mailto:klaus.baumecker@hp.com] 
Date: 2010/12/14 23:31
Sender: users@camel.apache.org
Subject: Re: How to setup a dynamic route using beans in Java w/o having a
spring ref to them?


Hi Claus,

I tried it, but it doesn't work.

The point is, that my dynamic Java-DSL route-builder does not know, what the
IDs of the beans are, which are added to the routes. It works, if I'm adding
the osgi:ref to one of the spring resource files, like this:

<osgi:reference id="myBean" interface="com.corp.MyIF"/>

Without this line, the bean is not found inside a bean step like this:

.to("bean:${beanName}?method=collect"),

where beanName=myBean. This is the dynamic part of this route-builder
(Groovy string).

What I'm looking for is a way to do the lookup like <osgi:ref...> statement
in my Java code during route construction.

klaus.
-- 
View this message in context:
http://camel.465427.n5.nabble.com/How-to-setup-a-dynamic-route-using-beans-i
n-Java-w-o-having-a-spring-ref-to-them-tp3304398p3304754.html
Sent from the Camel - Users mailing list archive at Nabble.com.



Re: How to setup a dynamic route using beans in Java w/o having a spring ref to them?

Posted by klausb <kl...@hp.com>.
Hi Claus,

I tried it, but it doesn't work.

The point is, that my dynamic Java-DSL route-builder does not know, what the
IDs of the beans are, which are added to the routes. It works, if I'm adding
the osgi:ref to one of the spring resource files, like this:

<osgi:reference id="myBean" interface="com.corp.MyIF"/>

Without this line, the bean is not found inside a bean step like this:

.to("bean:${beanName}?method=collect"),

where beanName=myBean. This is the dynamic part of this route-builder
(Groovy string).

What I'm looking for is a way to do the lookup like <osgi:ref...> statement
in my Java code during route construction.

klaus.
-- 
View this message in context: http://camel.465427.n5.nabble.com/How-to-setup-a-dynamic-route-using-beans-in-Java-w-o-having-a-spring-ref-to-them-tp3304398p3304754.html
Sent from the Camel - Users mailing list archive at Nabble.com.

Re: How to setup a dynamic route using beans in Java w/o having a spring ref to them?

Posted by Claus Ibsen <cl...@gmail.com>.
On Tue, Dec 14, 2010 at 12:04 PM, klausb <kl...@hp.com> wrote:
>
> I want to configure routing by an external configuration file.
> The routes are made of beans, which register themselves using the
> spring/osgi registry.
> Now the route builder, made with the Java DSL, wants to use the beans
> without knowing them in advance. That is, they are not configured in the
> spring config of the route component.
> My understanding is, that I cannot use "bean:myBean" URI without having
> myBean declared as osgi:reference in a corresponding spring xml file.
>
> Is there a way to use such a bean, by doing the osgi-resgistry lookup
> programatically?
>

Why dont you just try it?

When using Camel in OSGi it should lookup in the OSGi service registry
first, and then fallback to the spring app context afterwards.



> klaus.
> --
> View this message in context: http://camel.465427.n5.nabble.com/How-to-setup-a-dynamic-route-using-beans-in-Java-w-o-having-a-spring-ref-to-them-tp3304398p3304398.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/