Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

RMI server: rmiregistry or LocateRegistry.createRegistry

For RMI on server-side, do we need to start rmiregistry program, or just call LocateRegistry.createRegistry? If both are possible, what are the advantages and disadvantages?

like image 737
Randy Sugianto 'Yuku' Avatar asked Sep 19 '08 03:09

Randy Sugianto 'Yuku'


People also ask

What is Rmiregistry used for?

DESCRIPTION. A remote object registry is a bootstrap naming service that is used by RMI servers on the same host to bind remote objects to names. Clients on local and remote hosts can then look up remote objects and make remote method invocations.

What is an RMI server?

An RMI server is a program that hosts remote objects. An RMI registry is a separate program that binds remote object names to instances. An RMI server makes remote objects accessible to clients by registering them in the registry; clients then obtain access via that same registry.

What is RMI registry port?

By default, the RMI Registry uses port 1099. Client and server (stubs, remote objects) communicate over random ports unless a fixed port has been specified when exporting a remote object.

What is RMI registry Why RMI registry is needed?

A Java RMI registry is a simplified name service that allows clients to get a reference (a stub) to a remote object. In general, a registry is used (if at all) only to locate the first remote object a client needs to use.


2 Answers

They're the same thing... rmiregistry is a separate program, which you can run from a command line or a script, while LocateRegistry.createRegistry does the same thing programatically.

In my experience, for "real" servers you will want to use rmiregistry so that you know it's always running regardless of whether or not the client application is started. createRegistry is very useful for testing, as you can start and stop the registry from your test as necessary.

like image 144
user17250 Avatar answered Nov 15 '22 15:11

user17250


If we start rmiregistry first, RmiServiceExporter would register itself to the running rmiregistry. In this case, we have to set the system property 'java.rmi.server.codebase' to where the 'org.springframework.remoting.rmi.RmiInvocationWrapper_Stub' class can be found. Otherwise, the RmiServiceExporter would not be started and got the exception " ClassNotFoundException class not found: org.springframework.remoting.rmi.RmiInvocationWrapper_Stub; nested exception is: ..."

If your rmi server, rmi client and rmiregistry can access the same filesystem, you may want the system property to be automatically configured to where the spring.jar can be found on the shared filesystem. The following utility classes and spring configuration show how this can be achieved.

abstract public class CodeBaseResolver { 
  static public String resolveCodeBaseForClass(Class<?> clazz) {
    Assert.notNull(clazz);
    final CodeSource codeSource = clazz.getProtectionDomain().getCodeSource();
    if (codeSource != null) {
      return codeSource.getLocation().toString();
    } else {
      return "";
    }
  }
}

public class SystemPropertyConfigurer {
  private Map<String, String> systemProperties;
  public void setSystemProperties(Map<String, String> systemProperties) {
    this.systemProperties = systemProperties;
  }

  @PostConstruct
  void init() throws BeansException {
    if (systemProperties == null || systemProperties.isEmpty()) {
      return;
    }
    for (Map.Entry<String, String> entry : systemProperties.entrySet()) {
      final String key = entry.getKey();
      final String value = SystemPropertyUtils.resolvePlaceholders(entry.getValue());
      System.setProperty(key, value);
    }
  }
}


<bean id="springCodeBase" class="org.springframework.beans.factory.config.MethodInvokingFactoryBean">
  <property name="staticMethod" value="xx.CodeBaseResolver.resolveCodeBaseForClass" />
  <property name="arguments">
    <list>
      <value>org.springframework.remoting.rmi.RmiInvocationWrapper_Stub</value>
    </list>
  </property>
</bean>

<bean id="springCodeBaseConfigurer" class="xx.SystemPropertyConfigurer"
  depends-on="springCodeBase">
  <property name="systemProperties">
    <map>
      <entry key="java.rmi.server.codebase" value-ref="springCodeBase" />
    </map>
  </property>
</bean>

<bean id="rmiServiceExporter" class="org.springframework.remoting.rmi.RmiServiceExporter" depends-on="springCodeBaseConfigurer">
  <property name="serviceName" value="XXX" />
  <property name="service" ref="XXX" />
  <property name="serviceInterface" value="XXX" />
  <property name="registryPort" value="${remote.rmi.port}" />
</bean>

The above example shows how system property be set automatically only when rmi server, rmi client and rmi registry can access the same filesystem. If that is not true or spring codebase is shared via other method (e.g. HTTP), you may modify the CodeBaseResolver to fit your need.

like image 37
William Wong Avatar answered Nov 15 '22 16:11

William Wong