2014-02-27 2 views
1

서버가 여러 개인 경우가 있습니다. 서버는 클라이언트에 작업을 위임 할 수 있어야하므로 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) 
+0

'호출 가능 '은 인터페이스 일 뿐이므로 직접 문제가 아닙니다. 객체를 제대로 직렬화 할 수있는 한 호출 가능 객체를 구현할 수 있어야합니다. 하지만 다른쪽에 실행 코드를 보내려고하는 것 같습니다. –

+0

실마리가되어야합니다.) – Yser

+1

가능한 한, 나는 당신이 보여준 것만 큼 쉽지는 않다고 생각합니다. .class (+ 모든 참조와 함께 모든 수퍼 유형과 함께) 코드 자체를 직렬화해야 할 것이다. 클래스 (및 참조를 제대로로드하기 위해 다른 측면에 사용자 정의 클래스 로더가 필요할 것이다.) –

답변

0

클래스를 클라이언트에 배포하지 않은 클라이언트에 객체를 보내려면 RMI 코드베이스 기능을 자세히 살펴야합니다.