2012-06-09 3 views
1

У меня есть сервер RMI работает на локальном хосте, экспорт объекта типа Message:NotBoundException на локальном хосте

try { 
    MessageServer obj = new MessageServer(); 
    Message stub = (Message) UnicastRemoteObject.exportObject(obj, 0); 
    Registry registry = LocateRegistry.getRegistry(); 
    registry.bind("M", stub); 
} catch (RemoteException e) { 
} catch (AlreadyBoundException e) { 
} 

Тогда я хочу, чтобы начать клиент и получить заглушку для этого объекта. Кажется, что в реестре обнаруживается, но затем в try блоке NotBoundException брошено:

java.rmi.NotBoundException: M на sun.rmi.registry.RegistryImpl.lookup (RegistryImpl.java:136) at sun.rmi.registry.RegistryImpl_Skel.dispatch (Неизвестный источник) at sun.rmi.server.UnicastServerRef.oldDispatch (UnicastServerRef.java:409) at sun.rmi.server.UnicastServerRef.dispatch (UnicastServerRef.java:267) at sun.rmi.transport.Transport $ 1.run (Transport.java:177) at java.security.AccessController.doPrivileged (родной метод) at sun.rmi.transport.Transport.serviceCa ll (Transport.java:173) at sun.rmi.transport.tcp.TCPTransport.handleMessages (TCPTransport.java:553) at sun.rmi.transport.tcp.TCPTransport $ ConnectionHandler.run0 (TCPTransport.java:808) в sun.rmi.transport.tcp.TCPTransport $ ConnectionHandler.run (TCPTransport.java:667) в java.util.concurrent.ThreadPoolExecutor.runWorker (ThreadPoolExecutor.java:1110) в java.util.concurrent.ThreadPoolExecutor $ Worker.run (ThreadPoolExecutor.java:603) at java.lang.Thread.run (Thread.java:679) at sun.rmi.transport.StreamRemoteCall.exceptionReceivedFromServer (StreamRemoteCall.java:273) at sun.rmi. transport.StreamRemoteCall.executeCall (StreamRemoteCall.java:251) at sun.rmi.server.UnicastRef.invoke (UnicastRef.java:377) в sun.rmi.registry.RegistryImpl_Stub.lookup (Unknown Source) в rmitest.MessageClient.main (MessageClient.java:23)

public static void main(String args[]) { 
     //String host = "localhost"; 
     Registry registry; 
     Message stub = null; 
     try { 
      registry = LocateRegistry.getRegistry(); 
      stub = (Message) registry.lookup("M"); //NotBoundException thrown here 
     } catch (NotBoundException ex) { 
     } catch (AccessException ex) { 
     } catch (RemoteException ex) { 
     } 
     try { 
      stub.insert("TestString"); //NullPointerException here 
     } catch (RemoteException ex) { 
     } 

} 

Почему "M" не найден? Как сервер, так и клиент запускаются внутри Netbeans, реестр запускается через терминал заранее.

+0

Вы никогда не узнаете, пока не напишете правильную обработку исключений. – EJP

+0

Как вы это понимаете? Я улавливаю все возможные исключения и при отладке только исключение с показанным сообщением бросается в позицию, помеченную в коде. – user905686

+0

Я имею в виду, что отправленный вами код игнорирует все исключения. Я включаю код сервера, который явно забросил какое-то исключение, исключающее выполнение bind(). Если у вас есть другой код, напишите этот код, а не этот код. – EJP

ответ

2

RMI - своего рода зверь, это всегда проблема, как запустить его.

Прежде всего, сделайте правильную обработку исключений, поскольку рекомендуется @EJP: причина может быть в том, что вы получаете таймаут соединения или что-то подобное - поэтому поставьте e.printStackTrace() в блоки catch и давайте посмотрим, получим ли мы сообщение об ошибке (кстати, вы прекратите создавать пустые catch блоки очень быстро, когда вы отлаживаете подавленное исключение на 2 дня). Не может быть ваш брандмауэр, который ловит соединение?

Я хотел бы также изменить getRegistry() к createRegistry() и bind() к rebind() (это может сэкономить вам немного времени).

Исключением, которое вы получаете, является то, что ваше основное приложение не смогло связать (зарегистрировать) требуемую услугу и отсутствует (недоступно) из реестра по умолчанию.

RMI можно сделать несколькими способами. Подход, который вы выбрали, абсолютно крут для разработки и тестирования, но вам нужно будет внести некоторые изменения, если вы хотите поставить его под производство (например, вероятно, будет запущен обычный rmiregistry, вам придется использовать файл политики и некоторые свойства, такие как java.rmi.codebase=..., вам понадобится надлежащий менеджер безопасности и т. д.)

+0

Я не согласен с вашим последним абзацем. Вам нужен только файл политики, если вам нужен диспетчер безопасности, и вам нужен только менеджер безопасности для целей RMI и java.rmi.server.codebase, если вам нужна функция кодовой базы, и вам это совсем необязательно , Обычно я рекомендую запустить реестр через LocateRegistry.createRegistry(), * особенно *, если вы используете функцию codebase. – EJP

+0

Использование 'createRegistry()' решило проблему. Почему я не смог использовать уже запущенную reigstry? – user905686

+0

@ user905686 Это совершенно невозможно ответить окончательно, не видя исключения, которое ваш код игнорирует, но, скорее всего, он вообще не запускался на сервере. – EJP

Смежные вопросы