Close

Spring - Support for RMI Service/Client

[Last Updated: Aug 16, 2017]

With Spring, we can transparently expose any Java interface as a standard RMI service. For that, we need to register RmiServiceExporter as a bean. The exposed service can be accessed by any plain RMI client or we can use Spring's RmiProxyFactoryBean, which makes things much easier on the client side as well. In following example, we will write two projects, first one for the RMI server and other one for the client.

RMI server example

Service Interface

public interface OrderService{

  void placeOrder(String item, int quantity);

  List<Order> getOrderList();

}
public class Order implements Serializable{
  private String item;
  private int qty;
  private LocalDateTime orderDate;
  //getters/setters
}

Service implementation

public class OrderServiceImpl implements OrderService {
  private List<Order> orders = new ArrayList<>();

  @Override
  public void placeOrder(String item, int quantity) {
      Order order = new Order();
      order.setItem(item);
      order.setQty(quantity);
      order.setOrderDate(LocalDateTime.now());
      System.out.println("placing order: "+order);
      orders.add(order);
  }

  @Override
  public List<Order> getOrderList() {
      return new ArrayList<>(orders);
  }
}

Registering RmiServiceExporter and starting the service

@Configuration
public class ExampleApp {

  @Bean
  public OrderService orderService() {
      return new OrderServiceImpl();
  }

  @Bean
  public RmiServiceExporter exporter() throws UnknownHostException {
      RmiServiceExporter rse = new RmiServiceExporter();
      rse.setServiceName("OrderService");
      rse.setService(orderService());
      rse.setServiceInterface(OrderService.class);
      rse.setRegistryPort(2099);
      return rse;
  }

  public static void main(String[] args) {
      new AnnotationConfigApplicationContext(ExampleApp.class);
  }
}

Running the main class, will start the RMI service which will be waiting for the requests.

May 29, 2017 11:07:47 PM org.springframework.context.annotation.AnnotationConfigApplicationContext prepareRefresh
INFO: Refreshing org.springframework.context.annotation.AnnotationConfigApplicationContext@2e0fa5d3: startup date [Mon May 29 23:07:47 CDT 2017]; root of context hierarchy
May 29, 2017 11:07:48 PM org.springframework.remoting.rmi.RmiServiceExporter getRegistry
INFO: Looking for RMI registry at port '2099'
May 29, 2017 11:07:49 PM org.springframework.remoting.rmi.RmiServiceExporter getRegistry
INFO: Could not detect RMI registry - creating new one
May 29, 2017 11:07:49 PM org.springframework.remoting.rmi.RmiServiceExporter prepare
INFO: Binding service 'OrderService' to RMI registry: RegistryImpl[UnicastServerRef [liveRef: [endpoint:[192.168.1.38:2099](local),objID:[0:0:0, 0]]]]

Server Project

Dependencies and Technologies Used:

  • spring-context 4.3.8.RELEASE: Spring Context.
  • JDK 1.8
  • Maven 3.3.9

Rmi Server Project Select All Download
  • rmi-service-exporter
    • src
      • main
        • java
          • com
            • logicbig
              • example
                • order
                • ExampleApp.java

    RMI client

    For the client project, we will be using same OrderService interface. A proxy implementation of the service will be provided by RmiProxyFactoryBean.

    A bean accessing the remote service

    public class OrderBean {
    
      @Autowired
      private OrderService orderService;
    
      public void placeOrder() {
          System.out.println("-- placing orders --");
          orderService.placeOrder("ABC Tablet", 2);
          orderService.placeOrder("XYZ Desktop", 3);
      }
    
      public void listOrders() {
          System.out.println("-- getting order list from service --");
          List<Order> orderList = orderService.getOrderList();
          System.out.println(orderList);
      }
    }

    Registering RmiProxyFactoryBean and running the main method

    @Configuration
    public class ExampleClient {
    
      @Bean
      public OrderBean orderBean() {
          return new OrderBean();
      }
    
      @Bean
      public RmiProxyFactoryBean exporter() throws UnknownHostException {
          RmiProxyFactoryBean rpfb = new RmiProxyFactoryBean();
          rpfb.setServiceInterface(OrderService.class);
          String hostAddress = Inet4Address.getLocalHost()
                                           .getHostAddress();
          rpfb.setServiceUrl(String.format("rmi://%s:2099/OrderService", hostAddress));
          return rpfb;
      }
    
      public static void main(String[] args) {
          AnnotationConfigApplicationContext context =
                  new AnnotationConfigApplicationContext(ExampleClient.class);
          OrderBean bean = context.getBean(OrderBean.class);
          bean.placeOrder();
          bean.listOrders();
      }
    }

    Output

    -- placing orders --
    -- getting order list from service --
    [Order{item='ABC Tablet', qty=2, orderDate=2017-06-12T21:13:02.454}, Order{item='XYZ Desktop', qty=3, orderDate=2017-06-12T21:13:02.470}, Order{item='ABC Tablet', qty=2, orderDate=2017-06-12T21:13:13.516}, Order{item='XYZ Desktop', qty=3, orderDate=2017-06-12T21:13:13.517}]

    Client Project

    Dependencies and Technologies Used:

    • spring-context 4.3.8.RELEASE: Spring Context.
    • JDK 1.8
    • Maven 3.3.9

    Rmi Client Project Select All Download
    • rmi-service-client
      • src
        • main
          • java
            • com
              • logicbig
                • example
                  • order
                  • ExampleClient.java

      See Also