2016-03-12 99 views
0

我一直坚持了两天,试图解决我的单例会话bean和独立(rmi)客户端之间的通信问题。 这里有一点:我有一个远程会话bean(LoadBalancer),它可以被客户端(ChatRoom)访问,也可以访问客户端...理论上。尝试从我的远程EJB访问我的远程客户端时出错

远程接口:

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和聊天室的存根和骨架,并把IChatRoom的存根在部署负载均衡器的目录后,我得到以下例外,它们是我的噩梦由于两个天数:

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 

例外告诉我,我还没有出口的聊天室,虽然我已经生成并放置在其存根在我想应该是的目录。 我试图通过PortableRemoteObject.exportObject(this)更改指令UnicastRemoteObject.exportObject(this),但我仍然收到一个错误,与此不同。

任何帮助将不胜感激。 谢谢

+0

我成功部分地获得了EJB的参考。如果我不查找其正确的JNDI名称,我会得到一个不同的明确错误。 但是,单例会话bean无法检索远程客户端的引用。我真的不知道为什么错误指出聊天室没有导出... – mnds

+0

有没有人可以帮忙? – mnds

回答

0

我有完全相同的问题(在Glassfish 4服务器上运行的EJB,带有RMI回调对象的客户端)并最终找到解决方案!招数是:•

  1. 让客户实现从PortableRemoteObject继承,即在你的榜样:

    public class ChatRoom extends PortableRemoteObject implements IChatRoom, Serializable 
    

    注: 有3个选择为PortableRemoteObject Eclipse提供的: javax.rmi中。 PortableRemoteObject - >没有工作,需要我为客户端对象生成的存根(错误消息:java.rmi.StubNotFoundException:未找到存根类) com.sun.corba.se.impl.javax.rmi.PortableRemoteObject - >相同的问题 com.sun.corba.ee.impl。 javax.rmi.PortableRemoteObject - > WORKED,不生成存根!

  2. 在构造函数中导出对象(在UnicastRemoteObject.exportObject(this);)的相同位置)。从com.sun.corba.ee.impl.javax.rmi扩展该类。PortableRemoteObject允许简单的使用方法:如果从javax.rmi.PortableRemoteObject中延伸,然后静止参考PortableRemoteObject.exportObject(这)是必要的,但随后一个人需要为我找到了存根:

    exportObject(this); // i.e. non-static reference is required 
    

    注意。你也可以尝试,因为你有存根。

希望这有助于!