Michael Scharhag

About Michael Scharhag

Michael Scharhag is a Java Developer, Blogger and technology enthusiast. Particularly interested in Java related technologies including Java EE, Spring, Groovy and Grails.

Two things to remember when using Java RMI

This is a short blog post about two common pitfalls you should be aware of when using Java RMI.

Setting java.rmi.server.hostname

If you are getting strange Connection refused to host: error messages on the RMI client and you are sure the connection should work (you double checked all the standard things like network configuration etc.) the RMI system property java.rmi.server.hostname is something to look at.

To call a method on a remote object the RMI client has first to retrieve a remote stub object from the RMI registry. This stub object contains the server address that is later used to connect to the remote object when a remote method should be called (the connection to the RMI registry and the connection to the remote object are two completely different things). By default the server will try to detect his own address and pass it to the stub object. Unfortunatelly the algorithm that is used to detect the server address doesn’t always produce a useful result (depending on the network configuration).

It is possible to override the server address that is passed to the stub object, by setting the system property java.rmi.server.hostname on the RMI server.

This can either be done in Java code 

System.setProperty("java.rmi.server.hostname", "<<rmi server ip>>"); 

or by adding a Java command line parameter: 

-Djava.rmi.server.hostname=<<rmi server ip>>

Setting RMI service ports

If you have trouble making RMI calls through a firewall you should make sure you set specific ports for remote objects. By default port 1099 used by the RMI registry so make sure you opened this port in the firewall. However, this port is only used by the client to connect to the RMI registry and not for the communication between the stub and the remote object. For the later one random ports are used by default. Since you don’t want to open all ports in your firewall you should set a specific port for RMI remote objects.

This can be done by overriding the createServerSocket() method of RMISocketFactory:

public class MyRMISocketFactory extends RMISocketFactory {
  private static final int PREFERED_PORT = 1234;
  public ServerSocket createServerSocket(int port) throws IOException {
    if (port == 0) {
      return new ServerSocket(PREFERED_PORT);
    }
    return super.createServerSocket(port);
  }
}

By default createServerSocket() chooses a free random port if 0 is passed as parameter. In this modified version of createServerSocket() a specific port (1234) is returned when 0 is passed as parameter.

If you are using Spring’s RmiServiceExporter you can use the setServicePort() method to export services on a specific port:

<bean class="org.springframework.remoting.rmi.RmiServiceExporter">
  <property name="servicePort" value="1234"/>
  ...
</bean>

Note that multiple remote objects/services can share the same port. After you set a specific port, you just have to open this port in your firewall.
 

Related Whitepaper:

Functional Programming in Java: Harnessing the Power of Java 8 Lambda Expressions

Get ready to program in a whole new way!

Functional Programming in Java will help you quickly get on top of the new, essential Java 8 language features and the functional style that will change and improve your code. This short, targeted book will help you make the paradigm shift from the old imperative way to a less error-prone, more elegant, and concise coding style that’s also a breeze to parallelize. You’ll explore the syntax and semantics of lambda expressions, method and constructor references, and functional interfaces. You’ll design and write applications better using the new standards in Java 8 and the JDK.

Get it Now!  

Leave a Reply


× 5 = thirty



Java Code Geeks and all content copyright © 2010-2014, Exelixis Media Ltd | Terms of Use | Privacy Policy
All trademarks and registered trademarks appearing on Java Code Geeks are the property of their respective owners.
Java is a trademark or registered trademark of Oracle Corporation in the United States and other countries.
Java Code Geeks is not connected to Oracle Corporation and is not sponsored by Oracle Corporation.

Sign up for our Newsletter

20,709 insiders are already enjoying weekly updates and complimentary whitepapers! Join them now to gain exclusive access to the latest news in the Java world, as well as insights about Android, Scala, Groovy and other related technologies.

As an extra bonus, by joining you will get our brand new e-books, published by Java Code Geeks and their JCG partners for your reading pleasure! Enter your info and stay on top of things,

  • Fresh trends
  • Cases and examples
  • Research and insights
  • Two complimentary e-books