我正在尝试编写一个接受REST服务调用的应用程序层,并在RMI服务器上执行它们,检索响应并在格式化后将其发回。
我正在使用Jersey实现服务类并在Tomcat上运行它。我创建了一个在不同VM实例上运行的测试RMI服务器,以及在localhost上运行的rmiregistry。现在,当我调用REST URL时:
http://localhost:8080/Rest2RMI/rmi/getServerTime
我明白了:
java.rmi.UnmarshalException: error unmarshalling return; nested exception is:
java.lang.ClassNotFoundException: com.desmond.rmitest.ServerTimeImpl_Stub (no security manager: RMI class loader disabled)
at sun.rmi.registry.RegistryImpl_Stub.lookup(Unknown Source)
at java.rmi.Naming.lookup(Unknown Source)
at com.desmond.rmitest.ServiceClass.getMessage(ServiceClass.java:55)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
at java.lang.reflect.Method.invoke(Unknown Source)
at com.sun.jersey.spi.container.JavaMethodInvokerFactory$1.invoke(JavaMethodInvokerFactory.java:60)
at com.sun.jersey.server.impl.model.method.dispatch.AbstractResourceMethodDispatchProvider$TypeOutInvoker._dispatch(AbstractResourceMethodDispatchProvider.java:185)
at com.sun.jersey.server.impl.model.method.dispatch.ResourceJavaMethodDispatcher.dispatch(ResourceJavaMethodDispatcher.java:75)
at com.sun.jersey.server.impl.uri.rules.HttpMethodRule.accept(HttpMethodRule.java:302)
at com.sun.jersey.server.impl.uri.rules.RightHandPathRule.accept(RightHandPathRule.java:147)
at com.sun.jersey.server.impl.uri.rules.ResourceClassRule.accept(ResourceClassRule.java:108)
at com.sun.jersey.server.impl.uri.rules.RightHandPathRule.accept(RightHandPathRule.java:147)
at com.sun.jersey.server.impl.uri.rules.RootResourceClassesRule.accept(RootResourceClassesRule.java:84)
at com.sun.jersey.server.impl.application.WebApplicationImpl._handleRequest(WebApplicationImpl.java:1542)
at com.sun.jersey.server.impl.application.WebApplicationImpl._handleRequest(WebApplicationImpl.java:1473)
at com.sun.jersey.server.impl.application.WebApplicationImpl.handleRequest(WebApplicationImpl.java:1419)
at com.sun.jersey.server.impl.application.WebApplicationImpl.handleRequest(WebApplicationImpl.java:1409)
at com.sun.jersey.spi.container.servlet.WebComponent.service(WebComponent.java:409)
at com.sun.jersey.spi.container.servlet.ServletContainer.service(ServletContainer.java:540)
at com.sun.jersey.spi.container.servlet.ServletContainer.service(ServletContainer.java:715)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:728)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:303)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:208)
at org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:51)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:241)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:208)
at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:221)
at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:107)
at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:504)
at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:155)
at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:76)
at org.apache.catalina.valves.AccessLogValve.invoke(AccessLogValve.java:934)
at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:90)
at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:515)
at org.apache.coyote.http11.AbstractHttp11Processor.process(AbstractHttp11Processor.java:1012)
at org.apache.coyote.AbstractProtocol$AbstractConnectionHandler.process(AbstractProtocol.java:642)
at org.apache.coyote.http11.Http11NioProtocol$Http11ConnectionHandler.process(Http11NioProtocol.java:223)
at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.doRun(NioEndpoint.java:1597)
at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.run(NioEndpoint.java:1555)
at java.util.concurrent.ThreadPoolExecutor.runWorker(Unknown Source)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(Unknown Source)
at java.lang.Thread.run(Unknown Source)
Caused by: java.lang.ClassNotFoundException: com.desmond.rmitest.ServerTimeImpl_Stub (no security manager: RMI class loader disabled)
at sun.rmi.server.LoaderHandler.loadClass(Unknown Source)
at sun.rmi.server.LoaderHandler.loadClass(Unknown Source)
at java.rmi.server.RMIClassLoader$2.loadClass(Unknown Source)
at java.rmi.server.RMIClassLoader.loadClass(Unknown Source)
at sun.rmi.server.MarshalInputStream.resolveClass(Unknown Source)
at java.io.ObjectInputStream.readNonProxyDesc(Unknown Source)
at java.io.ObjectInputStream.readClassDesc(Unknown Source)
at java.io.ObjectInputStream.readOrdinaryObject(Unknown Source)
at java.io.ObjectInputStream.readObject0(Unknown Source)
at java.io.ObjectInputStream.readObject(Unknown Source)
... 44 more
我认为Tomcat使用自己的安全管理器,但是,我不确定是否需要它。当我在与Service类相同的包中运行客户端类时,它会毫无问题地输出日期,即使它位于与RMI服务器类不同的VM实例上。我查了一切,我无法理解我错过了什么。请检查我的代码和帮助。
我的代码如下:
ServerTimeInterface:
package com.desmond.rmitest;
import java.rmi.Remote;
import java.rmi.RemoteException;
public interface ServerTimeInterface extends Remote{
public String getServerTime() throws RemoteException;
}
ServerTimeImpl:
package com.desmond.rmitest;
import java.rmi.RemoteException;
import java.rmi.server.UnicastRemoteObject;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.Date;
public class ServerTimeImpl extends UnicastRemoteObject implements ServerTimeInterface{
/**
*
*/
private static final long serialVersionUID = 1L;
public ServerTimeImpl() throws RemoteException {
super();
}
@Override
public String getServerTime() throws RemoteException {
System.out.println("Inside getServerTime() Implementation.");
Date date = new Date();
DateFormat dateFormat = new SimpleDateFormat("dd-MM-yyyy hh:mm:ss");
String d = dateFormat.format(date);
System.out.println("Data returned: "+d);
return d;
}
}
的RMIServer:
package com.desmond.rmitest;
import java.rmi.Naming;
import java.rmi.RMISecurityManager;
import java.rmi.registry.LocateRegistry;
import java.rmi.registry.Registry;
public class RMIServer {
public static void main(String[] args){
if(System.getSecurityManager() == null){
System.setSecurityManager(new RMISecurityManager());
}
try{
ServerTimeInterface stub = new ServerTimeImpl();
System.out.println("Before rebinding");
Naming.rebind("//localhost/serverdate", stub);
System.out.println("Server started and rebind done");
}catch(Exception e){e.printStackTrace();}
}
}
ServiceClass(在Tomcat上运行,此处定义的REST服务):
package com.desmond.rmitest1;
import java.net.MalformedURLException;
import java.rmi.Naming;
import java.rmi.NotBoundException;
import java.rmi.RemoteException;
import javax.ws.rs.GET;
import javax.ws.rs.Path;
import javax.ws.rs.Produces;
import javax.ws.rs.core.MediaType;
@Path("/rmi")
public class ServiceClass {
@GET
@Path("/test")
@Produces(MediaType.TEXT_PLAIN)
public String test(){
return "All ok!";
}
@GET
@Path("/getServerTime")
@Produces(MediaType.TEXT_PLAIN)
public String getServerTime(){
String response = null;
//Registry registry;
try {
ServerTimeInterface sti = (ServerTimeInterface) Naming.lookup("rmi://127.0.0.1:1099/serverdate");
response = sti.getServerTime();
} catch (RemoteException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (NotBoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (MalformedURLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
System.out.println(response);
return response;
}
}
上面的类在Tomcat中抛出异常。但是,如果我运行以下操作,它会毫无问题地执行。:
RMIClient(与上面的Service类相同的包,作为普通的java应用程序运行):
package com.desmond.rmitest1;
import java.net.MalformedURLException;
import java.rmi.Naming;
import java.rmi.NotBoundException;
import java.rmi.RMISecurityManager;
import java.rmi.RemoteException;
public class RMIClient {
public static void main(String[] args){
if(System.getSecurityManager()==null){
System.setSecurityManager(new RMISecurityManager());
}
String jsonDate;
String date;
try {
ServerTimeInterface stub = (ServerTimeInterface) Naming.lookup("rmi://localhost:1099/serverdate");
date = stub.getServerTime();
System.out.println("Data received: "+date);
jsonDate = "{\"Server date\":\""+date+"\"}";
System.out.println("Data in JSON format: "+jsonDate);
} catch (MalformedURLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (RemoteException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (NotBoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}