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