Quantcast

Observer Pattern using Camel

classic Classic list List threaded Threaded
5 messages Options
Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

Observer Pattern using Camel

krishy
I am working on a abstraction library that would allow a bunch of our web-apps to include that library and
publish and subscribe to JMS destinations (and do other magical things). Publication works fine (at least on
the POC I have!) but I am having trouble wrapping my head around subscriptions.

The following method should allow clients to dynamically register for events from a JMS endpoint. My
current implementation looks like this:

<code>
public void addListener(Event event, Listener listener){
    try {
        camelContext.addRoutes(new RouteBuilder() {
            @Override
            public void configure() throws Exception {
                from(event.from()).bean(listener);
            }
        });
    } catch (Exception exception) {
        exception.printStackTrace();
    }

}
</code>

event.from() above would identify the endpoint from which the message would be consumed
("activemq:topic:market.stocks.update.ibm") and listener would be an implementation of a Listener
interface.

I had envisaged a typical invocation as:

<code>
notifications.addListener(updateEvent, new Listener(){
    void listen(){
        System.out.println("Hey! Something got updated");
    }
});
</code>

In theory, I like this approach since this frees me from having to worry about who is subscribed to which
queue, on what selectors etc, and I can have Camel automagically route these messages to the interested
listeners.

Except, of course, none of the above works since the camel route seems to expect a concrete bean as the
recipient and hence camel context fails to start-up. The actual error:

Caused by: org.springframework.beans.factory.NoSuchBeanDefinitionException: No matching bean of type
[com.example.Listener] found for dependency: expected at least 1 bean which qualifies as autowire
candidate for this dependency. Dependency annotations: {}

Am I shoe-horning Camel into something it was not supposed to do? Though, the Event Message EIP seems
to suggest this should work (except that the examples don't seem to address the dynamic nature of the listeners)

http://camel.apache.org/event-message.html

Being a Camel newbie, there is another aspect of this which I don't understand. This route even though
part of a method seems to get started when the Camel context starts up. How does the route get added
when the method that is supposed to add it to the context has not been invoked?

Thanks for your help and pointers.
Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

Re: Observer Pattern using Camel

Ashwin Karpe
Hi,

Please check out the camel-cache component. It is capable of sending exchanges along a route when the cache is added to, updated and/or deleted. It supports the eventing model and could be a way to dynamically propagate changes in the cache. From that point onwards dispatching to the right route endpoints, subscribers etc based on the nature of the event...

Cheers,

Ashwin...
---------------------------------------------------------
Ashwin Karpe
Apache Camel Committer & Sr Principal Consultant
Red Hat
http://www.redhat.com

Blog:http://opensourceknowledge.blogspot.com
---------------------------------------------------------
Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

Re: Observer Pattern using Camel

Claus Ibsen-2
In reply to this post by krishy
Try extending some base class for your anonymous listener interface,
so there is a class.

public class MyListener implements Listener {
   ..
}

The class may even be abstract.

And use new MyListener to instantiate the class. This may work then.



On Wed, Jun 15, 2011 at 6:01 PM, krishy <[hidden email]> wrote:

> I am working on a abstraction library that would allow a bunch of our
> web-apps to include that library and
> publish and subscribe to JMS destinations (and do other magical things).
> Publication works fine (at least on
> the POC I have!) but I am having trouble wrapping my head around
> subscriptions.
>
> The following method should allow clients to dynamically register for events
> from a JMS endpoint. My
> current implementation looks like this:
>
> <code>
> public void addListener(Event event, Listener listener){
>    try {
>        camelContext.addRoutes(new RouteBuilder() {
>            @Override
>            public void configure() throws Exception {
>                from(event.from()).bean(listener);
>            }
>        });
>    } catch (Exception exception) {
>        exception.printStackTrace();
>    }
>
> }
> </code>
>
> event.from() above would identify the endpoint from which the message would
> be consumed
> ("activemq:topic:market.stocks.update.ibm") and listener would be an
> implementation of a Listener
> interface.
>
> I had envisaged a typical invocation as:
>
> <code>
> notifications.addListener(updateEvent, new Listener(){
>    void listen(){
>        System.out.println("Hey! Something got updated");
>    }
> });
> </code>
>
> In theory, I like this approach since this frees me from having to worry
> about who is subscribed to which
> queue, on what selectors etc, and I can have Camel automagically route these
> messages to the interested
> listeners.
>
> Except, of course, none of the above works since the camel route seems to
> expect a concrete bean as the
> recipient and hence camel context fails to start-up. The actual error:
>
> Caused by: org.springframework.beans.factory.NoSuchBeanDefinitionException:
> No matching bean of type
> [com.example.Listener] found for dependency: expected at least 1 bean which
> qualifies as autowire
> candidate for this dependency. Dependency annotations: {}
>
> Am I shoe-horning Camel into something it was not supposed to do? Though,
> the Event Message EIP seems
> to suggest this should work (except that the examples don't seem to address
> the dynamic nature of the listeners)
>
> http://camel.apache.org/event-message.html
>
> Being a Camel newbie, there is another aspect of this which I don't
> understand. This route even though
> part of a method seems to get started when the Camel context starts up. How
> does the route get added
> when the method that is supposed to add it to the context has not been
> invoked?
>
> Thanks for your help and pointers.
>
> --
> View this message in context: http://camel.465427.n5.nabble.com/Observer-Pattern-using-Camel-tp4491726p4491726.html
> Sent from the Camel - Users mailing list archive at Nabble.com.
>



--
Claus Ibsen
-----------------
FuseSource
Email: [hidden email]
Web: http://fusesource.com
Twitter: davsclaus, fusenews
Blog: http://davsclaus.blogspot.com/
Author of Camel in Action: http://www.manning.com/ibsen/
Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

Re: Observer Pattern using Camel

Ashwin Karpe
In reply to this post by krishy
Good idea, Claus...

Writing a small custom component with an event listener to deal with event handlng and sending an exchange down a route will do the trick.

You can look at how the camel-cache accomplishes the same and come up with your own event listener against a given resource.

Cheers,

Ashwin...
---------------------------------------------------------
Ashwin Karpe
Apache Camel Committer & Sr Principal Consultant
Red Hat
http://www.redhat.com

Blog:http://opensourceknowledge.blogspot.com
---------------------------------------------------------
Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

Re: Observer Pattern using Camel

krishy
In reply to this post by Claus Ibsen-2
Thanks for the inputs.

I was able to get my original example working after tweaking the packageScan configuration.

The original reason the camel context failed to start was that it complained that the bean 'Listener' could not
be found. I removed the class, which had the above addListener method, from the packageScan of the camel
context and the context started up just fine. Subsequently, I was able add routes using implementations of
the Listener and all is well.

I suppose, since the anonymous class ends up in the classpath as being part of the package, the scanner
finds it and tries to inject the bean.
Loading...