RMI server: rmiregistry or LocateRegistry.createRegistry
Asked Answered
L

4

14

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?

Lamson answered 19/9, 2008 at 3:19 Comment(0)
R
8

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.

Rank answered 19/9, 2008 at 3:27 Comment(3)
Is there a way for createRegistry to work on an interface besides "localhost"?Manuel
Update: The documentation says ''createRegistry'' exports a registry on Localhost. However, the Registry is able to accept connections from outward-facing interfaces as well.Manuel
@Manuel Exports a Registry running in the localhost. There is no implication that it is only listening to 127.0.0.1.Eunaeunice
R
4

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.

Rhythmical answered 12/6, 2009 at 9:43 Comment(0)
E
0

If you are writing a standalone java application you would want to start your own rmiregistry but if you are writing a J2EE app that obviously runs inside a J2EE container then you want to "LocateRegistry" as there is already one running on the app server!

Essive answered 19/9, 2008 at 3:53 Comment(1)
Untrue and unmotivated. You might want to use LocateRegistry in a standalone program too.Eunaeunice
U
0

If you use Spring to export your RMI services, it automatically starts a registry if one is not already running. See RmiServiceExporter

Unyoke answered 20/9, 2008 at 3:57 Comment(1)
can you edit this to include a link to the documentation for this feature?Rem

© 2022 - 2024 — McMap. All rights reserved.