Getting Started With JINI 2.0

Common JINI Questions

  1. Dynamic permission grants are not supported
  2. Configuration files and Classpath
  3. Service Registration/Discovery problems (or Where's my Service?)
  4. Service Registration Lease Renewal
  5. Configuration Overrides Explained
  6. JINI and Tomcat
  7. ClassCastException using one Proxy from another?
  8. NotSerializableException when using JoinManager?
  9. I'm using an Exporter and ServiceStarter, but my proxy is still null!
  10. I've got problems invoking secure methods from AWT/Swing
  11. I'm getting java.lang.NoSuchMethodException: invalid method hash
  12. Why have the RMI semantics for automatic stub replacement not been honoured in JINI 2.0?

java.lang.SecurityException: Dynamic permission grants are not supported

This occurs when the JDK being used to run the code in question does not have jsk-policy.jar installed in the jre/lib/ext directory. The solution is to copy the jsk-policy.jar into the jre/lib/ext directory of your distribution. See here for full details.

Note 1: It's also possible that you simply forgot to place the appropriate overrides on your command-line to install the contents of jsk-policy.jar as the default security policy. This is done by adding:

-Djava.security.properties=dynamic-policy.properties

Where dynamic-policy.properties should contain:

# Java security properties file to install the dynamic
# security policy provider

policy.provider=net.jini.security.policy.DynamicPolicyProvider

Note 2: If the above still doesn't solve your problem and you're running on Win32, try checking the JAVA_HOME and PATH settings to verify that you're using the JDK with the jsk-policy.jar installed. You can determine the current settings by compiling and running the following:

// File: JVM.java
import java.io.*;
import java.util.Properties;
public class JVM {
    public static void main(String[] a) {
        Properties p =System.getProperties();
        p.list(System.out);
    }
}

Which will produce something like:

sun.boot.library.path=C:\Program Files\Java\j2re1.4.2_05\bin
java.endorsed.dirs=C:\Program Files\Java\j2re1.4.2_05\li...
java.home=C:\Program Files\Java\j2re1.4.2_05
java.ext.dirs=C:\Program Files\Java\j2re1.4.2_05\li...
sun.boot.class.path=C:\Program Files\Java\j2re1.4.2_05\li...

To force usage of the JDK in which you have installed jsk-policy.jar, you should:

  1. Add JAVA_HOME to your ENVIRONMENT's System variables
  2. Add PATH=%JAVA_HOME%\bin;%PATH% to your ENVIRONMENT's System variables

See this picture for an example


Configuration and Classpath

Let's say that you've just modified the lookup attributes of your Outrigger config to include a Name:
	  ...
   import net.jini.core.entry.Entry;
   import net.jini.lookup.entry.Name;

   com.sun.jini.outrigger {
          initialLookupAttributes = new Entry[] {new Name("MySpaceName")};
     ...

This presents a problem because the configuration now requires a class that may not be available on the classpath. The brute force approach to this problem is to add appropriate .jars to your classpath but this can be troublesome.

Michael Warres describes a better solution in this posting.


Service Registration Lease Renewal

A good article appears in the archives.


Configuration Overrides Explained

Tim Blackman's posting can be found here.


JINI and Tomcat

Check out Ronald J. Mann's
posting and his personal web-page

Also see this posting from the archives.


ClassCastException using one Proxy from another?

Loading one proxy from another via lookup presents some specific problems. The solution is discussed here.


NotSerializableException when using JoinManager?

Many people moving from JINI 1.x to 2.0 or those using JINI for the first time write code like this to export their service implementation:

LookupDiscoveryManager mgr = new LookupDiscoveryManager
	(LookupDiscovery.ALL_GROUPS, null, null);
JoinManager(service, entries, serviceIDListener, mgr, null);

Where service is a UnicastRemoteObject. On running their code they see something like:

java.rmi.MarshalException: error marshalling arguments; nested exception is:
java.io.NotSerializableException:
edu.wisc.trace.v2.server.net.jini.JiniNetworking
at com.sun.jini.reggie.Item.(Item.java:142)
at com.sun.jini.reggie.RegistrarProxy.register(RegistrarProxy.java:115)
at net.jini.lookup.JoinManager$ProxyReg.register(JoinManager.java:1098)
at net.jini.lookup.JoinManager$RegisterTask.run(JoinManager.java:771)
at net.jini.lookup.JoinManager$ProxyRegTask.tryOnce(JoinManager.java:594)
at com.sun.jini.thread.RetryTask.run(RetryTask.java:145)
at com.sun.jini.thread.TaskManager$TaskThread.run(TaskManager.java:324)
A key change was made between JINI 1.x and JINI 2.0 known as the removal of "automatic stub replacement". When using standard RMI, references to RemoteObject's passed outside of the instantiating JVM are automatically converted to stubs. JINI 2.0 introduced JERI (an RMI replacement) which uses a different concept,Exporter's, for making RemoteObject's available remotely. Exporter's require the programmer to explicitly convert a RemoteObject to a stub by calling the export method. The JINI 2.0 libraries expect, therefore, to be passed a stub rather than a remote object. One can fix the above code by changing it as follows:
LookupDiscoveryManager mgr = new LookupDiscoveryManager
	(LookupDiscovery.ALL_GROUPS, null, null);
JoinManager(java.rmi.server.RemoteObject.toStub(service), entries, serviceIDListener, mgr, null);

For more details, see Stop Relying on Automatic Stub Replacement.


I'm using an Exporter and ServiceStarter, but my proxy is still null!

Likely as not, you've forgotten to have your service implement ServiceProxyAccessor or ProxyAccessor.

If your service is transient/non-activatable, it should implement ServiceProxyAccessor which should return the proxy your service wishes to export. If you export a smart proxy, return a reference to that proxy otherwise you should return the remote reference created during the export stage.

If you wish to support activation, your service should implement ProxyAccessor. This method should always return the remote reference of your service whether that reference would be published as is or inside a smart proxy.


I've got problems invoking secure methods from AWT/Swing

The basic problem (here's an example) is usually related to the fact that non-user threads such as the AWT Event thread do not have the correct security (and possibly classloader) contexts associated with them. The ultimate choice of solution depends on your particular situation:


I'm getting java.lang.NoSuchMethodException: invalid method hash

This particular symptom is most often seen in cases of interface evolution however, there is a more obscure case which can produce similar behaviour. For coverage of both problems see this posting from the list.


Why have the RMI semantics for automatic stub replacement not been honoured in JINI 2.0?

RMI automatically replaces local references to a remote object implementation with the appropriate stub when they are passed outside of the JVM. JERI, doesn't provide support for this behaviour. Find out why, here.

If you'd like to replicate the old RMI/JRMP behaviour, try this:

class MyImpl implements MyRemoteInterface, Serializable {    private Exporter exporter;    private Remote proxy;
    /*
     Create the remote reference at construction time as would be done by
     the implicit super() call when extending UnicastRemoteObject
     */    MyImpl() throws ... {       exporter = ...;       proxy = exporter.export(this);    }
    /*
     When a reference is passed outside of the JVM, replace it with
     a reference to the proxy
     */    private Object writeReplace() {       return proxy;    }}
Getting Started With JINI 2.0