This lightweight, Spring-friendly, broker independent library provides a simple way to make remote calls via JMS API, allows RMI over JMS. The library supports synchronous and asynchronous remote method invocations as well as remote callbacks and remote exception handing.

   Once you download the archive with the library you will find everything you need to compile it and use: sources, third-party jars, build.properties and build.xml files. The usage principals and setup is pretty similar to the Spring remoting or Lingo use. You simply put in the Spring application context all definitions like those shown below.
   The remote method is considered as a synchronous if it returns a value and/or it throws an exception. This way the client code will wait for the remote result or an exception to be passed from the server side taking into account the timeout value. If the method doesn’t return any value and it does not throw any exception it is considered as asynchronous and will be called asynchronously.
    If the method argument is an instance of java.util.EventListener or java.rmi.Remote type it will be sent to the server side as a special remote delegate containing an identifier of the real object on the client side. Being passed to the server side it turns into a proxy delegating all the method calls back to the client side's object that it represents remotely.
   It’s also important to take into account that the listener object you pass to the client side as an argument turns into a dynamic proxy so the methods like equals and hashCode are not implemented except your remote object implements these methods.
   A reference to the remote listener on the client side as well as to a proxy object on the server side are held as a weak reference and it's a programmer's responsibility to keep an object alive. On the server side it's just a matter of performance because it acts as a simple cache and destroyed objects can cause just a repetitive creation of new proxies as overhead costs. But for the client side it can lead to a serious problem because a server's calls will refer to non-existent objects.
   All methods are called by names and so a method overloading is not supported from considerations of performance.

   Here is the usage example (taken from examples):

      AbstractApplicationContext ctx = 
        new ClassPathXmlApplicationContext ("context.xml");

      // ########################################
      //  CLIENT SIDE CODE
      // ########################################
      
      MathService helper = (MathService)ctx.getBean ("client");

      //// YOUR CODE HERE

      ctx.destroy ();

   There's an example configuration file of both client and server sides here (taken from examples):

<!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN//EN" 
    "http://www.springframework.org/dtd/spring-beans.dtd"
>
<beans>

  <!-- Server side -->
  <bean id="server" class="org.jmsrmi.spring.RemoteServiceProviderBean">
    <property name="connectionFactory" ref="jmsFactory"/>
    <property name="serviceDestination" ref="destination"/>
    <property name="service" ref="serviceImpl"/>
  </bean>
    
  <!-- Client side -->
  <bean id="client" class="org.jmsrmi.spring.RemoteServiceConsumerFactory">
    <property name="connectionFactory" ref="jmsFactory"/>
    <property name="serviceDestination" ref="destination"/>
    <property name="serviceInterface" value="org.jmsrmi.test.MathService"/>
  </bean>
  
  <!-- Service implementation -->
  <bean id="serviceImpl" class="org.jmsrmi.test.MathServiceImpl" singleton="true"/>
  
  <!-- JMS connection factory -->
  <bean id="jmsFactory" class="org.apache.activemq.ActiveMQConnectionFactory">
    <property name="brokerURL" value="vm://localhost?broker.persistent=false"/>
  </bean>
  
  <!-- JMS destination -->
  <bean id="destination" class="org.apache.activemq.command.ActiveMQQueue">
    <constructor-arg index="0" value="MathService"/>
  </bean>
  
</beans>

   It's also possible to use this library without Spring (taken from examples):

      ConnectionFactory cf = new ActiveMQConnectionFactory (
      "vm://localhost?broker.persistent=false");
      
      // ########################################
      //  SERVER SIDE CODE
      // ########################################

      RemoteServiceProvider rsp = new RemoteServiceProvider (
          cf, new MathServiceImpl ()new ActiveMQQueue ("MathService"));
      
      // ########################################
      //  CLIENT SIDE CODE
      // ########################################
      
      RemoteServiceConsumer rsc = new RemoteServiceConsumer (
          cf, MathService.class, new ActiveMQQueue ("MathService")30);
      
      MathService serv = (MathService)rsc.createService ();

      //// YOUR CODE HERE
      
      rsc.release ();
      rsp.release ();

Vitaly Tsaplin, 2007
E-mail: Vitaly.Tsaplin@gmail.com