서버가 여러 개인 경우가 있습니다. 서버는 클라이언트에 작업을 위임 할 수 있어야하므로 RMI를 구현하려고했습니다. this 튜토리얼을 따라 갔고 String을 param- 및/또는 return-value로 사용하면 모든 것이 잘 작동합니다.호출 가능한 Java RMI
이제 서버에서 클라이언트에 정의되지 않은 작업을 보내야합니다. 따라서 Callable을 param로 사용하려고 시도했지만 프로그램이 NotSerializableException
과 충돌했습니다. Callable은 내가 예상 한 결과 인 Serializeable 인터페이스를 구현하지 않기 때문에.
이제 Callable 및 Runnable을 params로 사용하는 여러 소스가 있는데 혼란 스럽습니다. 작동 시키려면 어떤 트릭이 있습니까? 아니면 뭔가 중요한 걸 놓치지? 어쩌면 더 잘 맞는 기술일까요?
Resource1 S. 33
Resource2 S. 5
그리고 heres는 내 코드 :
// Client
public static void main(String[] args) throws InterruptedException {
App app = new App();
app.startClient();
Thread.sleep(20000);//just for test purpose
}
private void startClient() {
try {
// create on port 1099
Registry registry = LocateRegistry.createRegistry(1099);
// create a new service named myMessage
registry.rebind("calcClient", new CalculateRemoteImpl<String>());
} catch (RemoteException e) {
e.printStackTrace();
}
System.out.println("System is ready");
}
// RemoteInterface
public interface CalculateRemote<T> extends Remote {
public T hello(Callable<T> hello) throws RemoteException;
}
// RemoteInterfaceImpl
public class CalculateRemoteImpl<T> extends UnicastRemoteObject implements CalculateRemote<T> {
public T hello(Callable<T> hello) throws RemoteException {
return (T) ("Hello " + hello);// just print address of object
}
}
.
// Server
public static void main(String[] args) {
App app = new App();
app.doTest();
}
private void doTest() {
try {
// fire to localhost port 1099
Registry myRegistry = LocateRegistry.getRegistry("127.0.0.1", 1099);
// search for myMessage service
CalculateRemote<String> impl = (CalculateRemote<String>) myRegistry.lookup("calcClient");
// call server's method
System.out.println("Message: " + impl.hello(new Callable<String>() {
public String call() throws RemoteException, Exception {
return "hello";
}
}));
System.out.println("Message Sent");
} catch (NotBoundException e) {
e.printStackTrace();
} catch (RemoteException e) {
e.printStackTrace();
}
}
// And the same RemoteInterface
public interface CalculateRemote<T> extends Remote {
public T hello(Callable<T> hello) throws RemoteException;
}
.
// stacktrace
java.rmi.MarshalException: error marshalling arguments; nested exception is:
java.io.NotSerializableException: de.fhb.rmicalcserver.App$1
at sun.rmi.server.UnicastRef.invoke(UnicastRef.java:156)
at java.rmi.server.RemoteObjectInvocationHandler.invokeRemoteMethod(RemoteObjectInvocationHandler.java:194)
at java.rmi.server.RemoteObjectInvocationHandler.invoke(RemoteObjectInvocationHandler.java:148)
at $Proxy0.hello(Unknown Source)
at de.fhb.rmicalcserver.App.doTest(App.java:30)
at de.fhb.rmicalcserver.App.main(App.java:18)
Caused by: java.io.NotSerializableException: de.fhb.rmicalcserver.App$1
at java.io.ObjectOutputStream.writeObject0(ObjectOutputStream.java:1180)
at java.io.ObjectOutputStream.writeObject(ObjectOutputStream.java:346)
at sun.rmi.server.UnicastRef.marshalValue(UnicastRef.java:292)
at sun.rmi.server.UnicastRef.invoke(UnicastRef.java:151)
'호출 가능 '은 인터페이스 일 뿐이므로 직접 문제가 아닙니다. 객체를 제대로 직렬화 할 수있는 한 호출 가능 객체를 구현할 수 있어야합니다. 하지만 다른쪽에 실행 코드를 보내려고하는 것 같습니다. –
실마리가되어야합니다.) – Yser
가능한 한, 나는 당신이 보여준 것만 큼 쉽지는 않다고 생각합니다. .class (+ 모든 참조와 함께 모든 수퍼 유형과 함께) 코드 자체를 직렬화해야 할 것이다. 클래스 (및 참조를 제대로로드하기 위해 다른 측면에 사용자 정의 클래스 로더가 필요할 것이다.) –