Reputation:
I have the following EJB class instantiated in an application running in JBoss 5
public interface ISlaveServer {
public String getId();
public String getName();
}
@Remote
public interface IMasterServer {
public String getId();
public void addSlave(ISlaveServer slaveServer);
public void removeSlave(ISlaveServer slaveServer);
}
@Stateless
@RemoteBinding(jndiBinding = "MasterServer")
public class MasterServer implements IMasterServer, Serializable {
UUID id = UUID.randomUUID().toString();
public String getId() { return id.toString(); }
public void addSlave(ISlaveServer slaveServer) { ... }
public void removeSlave(ISlaveServer slaveServer) { ... }
}
I Have the following class instantiated in an application running in Tomcat 6
public static class SlaveServer implements ISlaveServer, Serializable {
UUID id = UUID.randomUUID().toString();
public String getId() { return id.toString(); }
public String getName() { return "SlaveServer"; }
}
Finally I have the following code also running in the Tomcat based application...
Properties properties = new Properties();
properties.put("java.naming.factory.initial", "org.jnp.interfaces.NamingContextFactory");
properties.put("java.naming.factory.url.pkgs", "org.jboss.naming.client");
properties.put("java.naming.provider.url", "jnp://localhost:1099");
try {
Context ctx = new InitialContext(properties);
IMasterServer masterServer = (IMasterServer) ctx.lookup("MasterServer");
String masterId = masterServer.getId();
masterServer.addVideoServer(new SlaveServer());
}
catch(NamingException e) {
e.printStackTrace();
}
Everything is working fine up until the call to
masterServer.addVideoServer(new SlaveServer());
at which time I get the following exception...
java.lang.ClassNotFoundException: org.test.SlaveServerTest$SlaveServer (no security manager: RMI class loader disabled)
From what I can tell this exception might be originating from the remote JBoss server because the remote calls are working ( masterServer.getId() works fine ). Just the call where I am passing a locally implemented object is failing.
What do I need to do to get this working?
Upvotes: 2
Views: 4658
Reputation: 483
To get this working I needed to implement the ISlaveServer interface as an RMI remote interface.
public interface ISlaveServer extends java.rmi.Remote {
...
}
and make sure that the SlaveServer class was a proper RemoteObject...
public class SlaveServer extends java.rmi.RemoteObject implements ISlaveServer {
}
Finally I had to make sure the SlaveServer was exported through RMI before using it...
static SlaveServer slaveServer = new SlaveServer();
Properties properties = new Properties();
properties.put("java.naming.factory.initial", "org.jnp.interfaces.NamingContextFactory");
properties.put("java.naming.factory.url.pkgs", "org.jboss.naming.client");
properties.put("java.naming.provider.url", "jnp://localhost:1099");
try {
Context ctx = new InitialContext(properties);
IMasterServer masterServer = (IMasterServer) ctx.lookup("MasterServer");
String masterId = masterServer.getId();
masterServer.addVideoServer((ISlaveServer)UnicastRemoteObject.exportObject(slaveServer, 0));
}
catch(NamingException e) {
e.printStackTrace();
}
This correctly communicates with the Remote EJB and passes a reference to my SlaveServer object which the EJB can use to communicate back with the calling VM.
FYI SlaveServer is static because in RMI it is your responsibility to hold on to a reference to the real object since RMI only holds weak-references. If you don't you will get "Object not in table" errors from RMI.
Upvotes: 0
Reputation: 33936
The SlaveServer class is Serializable. This means that this class must be made available to both the client (the JNDI snippet) and the server (MasterServer). When a class cannot be found on the server, RMI has the capability of downloading code from a remote location. However, executing code downloaded from a remote client is a potentially dangerous operation, this is only allowed if a security manager has been installed.
You'll need to either include the SlaveServer class in the application containing MasterServer (or some server class path), or you'll need to stop using Serializable.
Upvotes: 2
Reputation: 483
The "static" was there because the original SlaveServer class was a nested class.
I have moved the class to the top-level (thus removing the static) and it is still a no go; I get the same exception.
It seems to me I need to do something like CORBA's "activation" to my SlaveServer. That way the JBoss server should be able to get the stubs for my SlaveServer inside Tomcat.
/Edit There is no implementation of ISlaveServer in the JBoss application. I want it to pass a "remote reference" from the Tomcat application to the JBoss application so it shouldn't really be serializing it anyway (just a reference to it).
Upvotes: 0