You are viewing a plain text version of this content. The canonical link for it is here.
Posted to users@camel.apache.org by Cristiano Costantini <cr...@gmail.com> on 2013/05/17 14:57:19 UTC

Bean as Consumer Endpoint

Hi All,

I'm trying to find the best way to consume messages produced from a bean
that produce messages sending them to a 'delegate' field.

I've not found the ideal solution for my scenario as feasible, I've found
quite good alternative but with a big limit. I would like you to confirm me
my ideal solution is not feasible and to suggest me a strategy to handle
this limit.


The beans I use implements the delegation concept when producing events
(I've not found some equivalent EIP, the concept implemented is like this
one:
http://developer.apple.com/library/ios/#documentation/general/conceptual/CocoaEncyclopedia/DelegatesandDataSources/DelegatesandDataSources.html
)

That is, my bean has a setter for the delegate that when != null it is used
for sending "events". Quick and simplified example:

public class SmileController implements Runnable {

  // The delegate interface
  public interface FaceDelegate {
    void smile();
  }

  // The delegate property
  private FaceDelegate delegate = null;

  // The delegate setter
  public void setDelegate(FaceDelegate delegate) {
    this.delegate = delegate;
  }

  @Override
  public void run() {
    if (delegate != null) {
      delegate.smile();
    } else {
      // log error or queue the message or something else
    }
  }
}

I use this bean in Spring and I pass a class FaceImpl implements
FaceDelegate  {...} as delegate for SmileController in this way:

<bean id="face" class="org.example.FaceImpl" />
<bean id="smileController" class="org.example.SmileController">
      <property name="delegate" ref="face"/>
</bean>

I desire to decouple FaceImpl and SmileController with Camel, and ideally
my solution would be to write a route this way:

<bean id="smileController" class="org.example.SmileController" />

<camelContext id="camelContext" xmlns="http://camel.apache.org/schema/spring
">
<route>
   <from uri="bean:smileController"/>
   <to uri="direct:face"/>
</route>
</camelContext>

but I can't as the bean component can't be used for consumer endpooints.

I could annotate with @Produce the field FaceDelegate delegate, but this
create for me a dependency with org.apache.camel APIs and sometime I can't
change the code.

So I've found I can use a camel proxy created in a Spring Bean
configuration file:
<camel:proxy id="faceProxy" serviceUrl="direct:face"
serviceInterface="org.example.FaceDelegate" />

<bean id="smileController" class="org.example.SmileController">
<property name="delegate" ref="faceProxy" />
</bean>

This solve most of my problems and in this way I don't have to modify the
java code.

I'm not yet fully satisfied as I still have a coupling I want to get rid
off. I want to deploy my FaceController bean as an OSGi service and consume
its events in another bundle. I would define the service with spring and
spring-osgi in this way:
--- beans_bundle_1.xml ---
<!-- At the beginning, my SmileController will have a null delegate. Note:
I've added a "startSmiling" method to the service which start timer that
call run every 10 seconds. -->
<bean id="smileController" class="org.example.SmileController"
init-method="startSmiling"/>

<!-- I publish it to OSGi. Note: I've made the service implements a super
interface for resolving it in OSGi -->
<osgi:service id="smileControllerService" ref="smileController"
interface="org.example.SmileControllerInterface"/>

And in another OSGi bundle I want to use camel to add a proxy to this
service and start receiving his 'smiles':
--- beans_bundle_2.xml ---
<osgi:reference id="smileControllerService"
interface="org.example.SmileControllerInterface"
bean-name="smileController"/>

<!-- what can I do here???? -->


What do you think it is best to do to handle this deployment configuration?
Am I missing some other camel feature that could allow me to better
implement this scenario?

I hope I've explained clearly my context, sorry if I've been long, if I had
more time I would have been shorter message.

Thank you,

Cristiano