I think that a) I may not have correctly outlined the problem, or b) I am simply not understanding the proposed solutions. Here is the problem stated very simply:
OSGi Bundles A, B, C contain consumers (Ac, Bc, Cc) of a service provided by a class Zs in Bundle Z, asynchronously. Yes, service Zs returns a value to the consumers. I don't want the call in Ac, Bc, or Cc to block. Therefore, service Zs should reply to consumers asynchronously. Return value needs to be via callback rather than forcing consumers to poll a Future.
Consumers Ac, Bc, Cc use a gateway proxy to place the service request onto a Spring Integration request channel defined in Z, and exported via osgi:service.
Bundle A, B, C:
Code:
<bean id="consumer" class="foo.client.Consumer">
<property name="requestGateway" ref="requestGateway"/>
</bean>
<!-- Requests go to the requestGateway, which puts messages onto the requestChannel (exposed by some other bundle via OSGi), and replies from the RequestHandler come back to the consumer -->
<si:gateway id="requestGateway"
service-interface="foo.server.RequestHandler"
default-request-channel="requestChannel"
default-reply-channel="replyChannel"/>
<osgi:reference id="requestChannel" bean-name="requestChannel" interface="org.springframework.integration.core.SubscribableChannel"/>
Bundle Z:
Code:
<si:channel id="requestChannel">
<si:dispatcher task-executor="requestExecutor"/>
</si:channel>
<task:executor id="requestExecutor" pool-size="10"/>
<si:service-activator input-channel="requestChannel" ref="requestHandlerImpl"/>
<bean id="requestHandlerImpl" class="foo.server.RequestHandlerImpl"/>
<osgi:service interface="org.springframework.integration.core.SubscribableChannel" ref="requestChannel"/>
Now this all seems to work if I'm willing to accept either a) blocking in the consumer (in this case the foo.RequestHandler interface gateway method returns a simple value), or b) Future polling in the consumer (in this case the foo.RequestHandler gateway method returns a Future implementation, or c) by having the service return a custom FutureTask that executes the callback in done(), and the callback is itself passed as a message header in the request.
Solutions a) and b) work but are no good because I don't want blocking or polling, and c) does what I need but is messy. What I am looking for is the "right" way to do this using Spring Integration.
I hope that clarifies things...