我会尽量保持这篇文章尽可能小,所以如果需要,我会添加更多信息和代码。
场景:我正在编写一个服务器/客户端应用程序来跟踪我们在公司的一些流程,因此用户将根据工作流程创建从一个用户屏幕到另一个用户屏幕的小标签(用 Swing 编写的客户端)。
我正在运行本地 Glasfish 3.1 服务器(在 Eclipse 中)和 MySql。在服务器上,我正在运行 Spring MVC 和 Spring Data + Hibernate。
属性文件保存此信息以便于更改:
rmi.serverPort = 1971
rmi.clientPort = 2010
在服务器启动期间,有一个 bean 设置 RMI 环境,如下所示:
@Autowired
private RmiData rmiData;
@Autowired
private DataRequestHandler dataRequestHandler;
@Autowired
private ConnectionRequestHandler connectionRequestHandler;
.
.
.
LocateRegistry.createRegistry(rmiData.getServerPort());
String rmiUrl = "rmi://" + rmiData.getHost() + ":" + rmiData.getServerPort() + "/";
Naming.rebind(rmiUrl + "ConnectionRequestHandler", connectionRequestHandler);
Naming.rebind(rmiUrl + "DataRequestHandler", dataRequestHandler);
服务器包含两个处理程序的接口和实现,而客户端只有接口。
这是在没有 SecurityManager 和 Policy 文件的情况下工作的。尽管我必须将 Hibernate jar 包含到客户端中以解决其他异常(在 SO 上找到的解决方案)。
在使客户端连接到服务器并请求数据工作之后,我开始编写对客户端的回调(服务器也必须将数据推送到客户端)。所以这就是我现在卡住的地方。
这是我进行回调的方式(客户端就像服务器一样):
private ClientCallbackHandler clientCallbackHandler = new ClientCallbackHandlerImpl();
.
.
.
LocateRegistry.createRegistry(rmiData.getClientPort());
String rmiUrl = "rmi://localhost:" + rmiData.getClientPort() + "/";
Naming.rebind(rmiUrl + "ClientCallbackHandler", clientCallbackHandler);
服务器只包含客户端接口,客户端同时拥有处理程序的接口和实现。
所以当服务器执行
String rmiUrl = "rmi://" + clientHost + ":" + clientPort + "/";
clientCallbackHandler = (ClientCallbackHandler)Naming.lookup(rmiUrl + "ClientCallbackHandler");
我在服务器上收到以下异常:
SEVERE: java.rmi.UnmarshalException: error unmarshalling return; nested exception is:
java.lang.ClassNotFoundException: br.com.affair.socontrol.rmi.ClientCallbackHandlerImpl (no security manager: RMI class loader disabled)
我正在避免安装 SecurityManager 和 Policy 文件(也尝试过但没有成功),我被困在这里。
我不明白为什么服务器只需要接口就抱怨实现类。任何帮助深表感谢。谢谢。