The Scenario
A client needs to invoke a service interface with the following restrictions:
- The service implementation is running on a remote machine.
- This fact is transparent to the client, i.e. any service method invocation is just like a local method invocation.
- The service methods are executed asychronously on the server, method invocations on the client return immediately (fire-and-forget).
- All service methods have void return types.
The Solution with Java EE 6
With Java EE 6, the solution is quite simple, thanks to the
@Asynchronous
annotation introduced in EJB 3.1. You simply create a remote session bean and add this annotation to any business method or to the entire class. The container will then execute the given methods asynchronously.Patrick Champion has a complete example in his blog, so there's no need for me to provide any sample code.
When your client is also a Java EE 6 application, you can simply
@Inject
the service interface and use a @Produces
annotation on an @EJB
reference somewhere else to direct the client to the appropriate implementation.In addition, to avoid hardcoding the service URL in your client, you should define a local JNDI alias in your Java EE 6 container for the address of the remote service implementation, so you can move the remote implementation to another host without recompiling your client.
The Solution with Spring 3.0
Spring does not have an out-of-the box solution for this scenario. Spring Remoting provides transparent proxies for remote services, but these proxies are always synchronous. Since Spring 3.0, there annotation support for asynchronous execution, but this only applies to local beans.
However, it is not hard to combine these two features with some glue code to implement a solution for our scenario.