我已经被困了两天,试图解决我的单例会话bean和独立(rmi)客户端之间的通信问题。 这就是重点:我有一个远程会话bean(LoadBalancer),它可以被客户端(ChatRoom)访问,并且理论上也可以访问客户端。
远程接口:
public interface ILoadBalancer{
public void addChatRoom( IChatRoom chatRoom );
public void removeChatRoom( IChatRoom chatRoom );
}
会话bean:
@Remote(ILoadBalancer.class)
@Singleton
public class LoadBalancer implements ILoadBalancer {
/**
* List of available chat rooms
*/
private Map<String, IChatRoom> chatRooms;
private static final Logger logger = Logger.getLogger("loadBalancerLogger");
@PostConstruct
public void init() {
chatRooms = new HashMap<String, IChatRoom>();
}
@Override
public void addChatRoom(IChatRoom chatRoom) {
// Adding a new chat room to the list of available chat rooms
try {
chatRooms.put(chatRoom.getName(), chatRoom);
logger.log(Level.INFO, "Enregistrement d'un salon de discussion {0}", chatRoom.getName());
} catch (RemoteException ex) {
Logger.getLogger(LoadBalancer.class.getName()).log(Level.SEVERE, null, ex);
}
}
@Override
public void removeChatRoom(IChatRoom chatRoom) {
// Removing a chat room from the list of available chat rooms
try {
chatRooms.remove(chatRoom.getName());
logger.log(Level.INFO, "Suppression du salon de discussion {0}", chatRoom.getName());
} catch (RemoteException ex) {
Logger.getLogger(LoadBalancer.class.getName()).log(Level.SEVERE, null, ex);
}
}
这些部署在glassfish服务器(4.1)中。
现在使用RMI的独立客户端:
public interface IChatRoom extends Remote {
public int postMessage( String pseudo, String message) throws RemoteException;
public int subscribe( String pseudo) throws RemoteException;
public List<String> getNewMessages(String pseudo, int sequenceNumber) throws RemoteException;
public String getName() throws RemoteException;
}
实施它的课程:
public class ChatRoom implements IChatRoom, Serializable {
private String name;
private List<String> users;
private List<String> messages;
private static final Logger logger = Logger.getLogger("chatRoomLogger");
/**
* A reference to the load balancer
*/
private ILoadBalancer loadBalancer;
public ChatRoom(String name) throws RemoteException, NamingException {
this.name = name;
users = new ArrayList<String>();
messages = new ArrayList<String>();
// Making the chat room available via RMI
UnicastRemoteObject.exportObject(this);
// Retrieving a reference to the loadBalancer
Properties props = new Properties();
props.setProperty(Context.INITIAL_CONTEXT_FACTORY, "com.sun.enterprise.naming.impl.SerialInitContextFactory");
props.setProperty(Context.STATE_FACTORIES, "com.sun.corba.ee.impl.presentation.rmi.JNDIStateFactoryImpl");
props.setProperty(Context.URL_PKG_PREFIXES, "com.sun.enterprise.naming");
props.setProperty("org.omg.CORBA.ORBInitialHost", "localhost");
props.setProperty("org.omg.CORBA.ORBInitialPort", "3700");
Context ctx = new InitialContext(props);
loadBalancer = (ILoadBalancer) ctx.lookup("java:global/loadBalancer/LoadBalancer!sn.esp.dgi.core.ILoadBalancer");
loadBalancer.addChatRoom(this);
}
@Override
public int postMessage(String pseudo, String message) throws RemoteException {
// Not relevant to the problem
}
@Override
public int subscribe(String pseudo) throws RemoteException {
// Not relevant to the problem
}
@Override
public List<String> getNewMessages(String pseudo, int sequenceNumber) throws RemoteException {
// Not relevant to the problem
}
@Override
public String getName() throws RemoteException {
// Not Relevant to the problem
}
}
如您所见,客户端具有对会话bean的远程引用,并且会话bean还具有对已订阅它的所有客户端的远程引用。
使用以下代码启动客户端:
public class ChatRoomLauncher {
public static void main( String[] args ) {
if( args.length < 1 ) {
System.out.println("Usage: java ChatRoomLauncher <nomChatRoom>");
System.exit(-1);
}
String chatRoomName = args[0];
try {
IChatRoom chatRoom = new ChatRoom(chatRoomName);
System.out.println("Salon de discussion "+ chatRoomName +" démarré ");
} catch (RemoteException ex) {
Logger.getLogger(ChatRoomLauncher.class.getName()).log(Level.SEVERE, null, ex);
} catch (NamingException ex) {
Logger.getLogger(ChatRoomLauncher.class.getName()).log(Level.SEVERE, null, ex);
}
}
}
分别生成IChatRoom和ChatRoom的存根和骨架,并将IChatRoom的存根放在LoadBalancer部署的目录中后,我得到以下例外,这是我两天以来的噩梦:
Exception in thread "main" javax.ejb.NoSuchEJBException
at sn.esp.dgi.core._ILoadBalancer_Wrapper.addChatRoom(sn/esp/dgi/core/_ILoadBalancer_Wrapper.java)
at sn.esp.dgi.server.ChatRoom.<init>(ChatRoom.java:76)
at sn.esp.dgi.server.ChatRoomLauncher.main(ChatRoomLauncher.java:29)
Caused by: java.rmi.NoSuchObjectException: CORBA INV_OBJREF 1330447539 No; nested exception is:
org.omg.CORBA.INV_OBJREF: WARNING: 00511203: Class sn.esp.dgi.server.ChatRoom not exported, or else is actually a JRMP stub vmcid: OMG minor code: 1203 completed: No
at com.sun.corba.ee.impl.javax.rmi.CORBA.Util.mapSystemException(Util.java:260)
at com.sun.corba.ee.impl.presentation.rmi.StubInvocationHandlerImpl.privateInvoke(StubInvocationHandlerImpl.java:211)
at com.sun.corba.ee.impl.presentation.rmi.StubInvocationHandlerImpl.invoke(StubInvocationHandlerImpl.java:150)
at com.sun.corba.ee.impl.presentation.rmi.codegen.CodegenStubBase.invoke(CodegenStubBase.java:226)
at sn.esp.dgi.core.__ILoadBalancer_Remote_DynamicStub.addChatRoom(sn/esp/dgi/core/__ILoadBalancer_Remote_DynamicStub.java)
... 3 more
Caused by: org.omg.CORBA.INV_OBJREF: WARNING: 00511203: Class sn.esp.dgi.server.ChatRoom not exported, or else is actually a JRMP stub vmcid: OMG minor code: 1203 completed: No
at com.sun.proxy.$Proxy54.objectNotExported(Unknown Source)
at com.sun.corba.ee.impl.util.Utility.autoConnect(Utility.java:160)
at com.sun.corba.ee.impl.javax.rmi.CORBA.Util.writeRemoteObject(Util.java:473)
at com.sun.corba.ee.impl.presentation.rmi.DynamicMethodMarshallerImpl$12.write(DynamicMethodMarshallerImpl.java:356)
at com.sun.corba.ee.impl.presentation.rmi.DynamicMethodMarshallerImpl.writeArguments(DynamicMethodMarshallerImpl.java:465)
at com.sun.corba.ee.impl.presentation.rmi.StubInvocationHandlerImpl.privateInvoke(StubInvocationHandlerImpl.java:196)
... 6 more
异常告诉我,我没有导出chatRoom,虽然我已经生成并将其存根放在我认为应该存在的目录中。 我试图通过PortableRemoteObject.exportObject(this)更改指令UnicastRemoteObject.exportObject(this),但我仍然遇到错误,与此不同。
非常感谢任何帮助。 感谢
答案 0 :(得分:0)
我遇到了完全相同的问题(在Glassfish 4服务器上运行的EJB,带有RMI回调对象的客户端),最后找到了解决方案!诀窍是:
使客户端实现继承自PortableRemoteObject,即在您的示例中:
public class ChatRoom extends PortableRemoteObject implements IChatRoom, Serializable
注意: Eclipse提供的PortableRemoteObject有3种选择: javax.rmi.PortableRemoteObject - &gt;不起作用,想要我没有为客户端对象生成的存根(错误消息:java.rmi.StubNotFoundException:找不到存根类) com.sun.corba.se.impl.javax.rmi.PortableRemoteObject - &gt;同样的问题 com.sun.corba.ee.impl.javax.rmi.PortableRemoteObject - &gt;工作,没有生成存根!!
在构造函数中导出对象(在您拥有UnicastRemoteObject.exportObject(this)的相同位置;)。从com.sun.corba.ee.impl.javax.rmi.PortableRemoteObject扩展类只允许使用:
exportObject(this); // i.e. non-static reference is required
注意:如果从javax.rmi.PortableRemoteObject扩展,则需要对PortableRemoteObject.exportObject(this)进行静态引用,但是我需要找到存根。你也可以尝试,因为你有存根。
希望这有帮助!