尝试从远程EJB访问远程客户端时出错

时间:2016-03-12 09:40:47

标签: java glassfish ejb rmi

我已经被困了两天,试图解决我的单例会话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),但我仍然遇到错误,与此不同。

非常感谢任何帮助。 感谢

1 个答案:

答案 0 :(得分:0)

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

  1. 使客户端实现继承自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;工作,没有生成存根!!

  2. 在构造函数中导出对象(在您拥有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)进行静态引用,但是我需要找到存根。你也可以尝试,因为你有存根。

  3. 希望这有帮助!