Особые действия при использовании плагинов rmi + - PullRequest
0 голосов
/ 29 сентября 2010

У меня есть приложение FooApplication (код в foo.jar) с плагином BarPlugin (код в foo-bar-plugin.jar). Приложение создает экземпляр плагина динамически. Работает отлично.

FooApplication имеет некоторые функции, доступные через интерфейс RMI FooRemote. Это также прекрасно работает, за исключением одной вещи. У FooRemote есть метод доступа к Remote объектам, экспортируемым плагинами, и я получаю исключение java.rmi.UnmarshalException при попытке передать один из этих плагинов клиенту RMI.

public interface FooRemote extends Remote
{
    /* other methods */
    public RemoteControl getPluginRemoteControl(int i) throws RemoteException;
}
/** just a named Remote object for debugging purposes */
public interface RemoteControl extends Remote
{
    public String getName() throws RemoteException;
}

В FooRemoteImpl я делаю следующее:

/* just a test object */
private static class RC0 extends UnicastRemoteObject implements RemoteControl 
{
    public RC0() throws RemoteException { super(); }
    @Override public String getName() throws RemoteException { return "RC0"; }
}

@Override public RemoteControl getPluginRemoteControl(int i) 
       throws RemoteException 
{
    int j = i;
    if (j <= 0)
        return new RC0();

    Collection<RemoteControl> rclist = this.model.getApplicationPluginRemotes();
    for (RemoteControl rc : rclist)
    {
        if (--j == 0)
            return rc;
    }
    return null;
}

Когда я звоню FooRemote.getPluginRemoteControl(0), он передает экземпляр моего фиктивного класса RC0 и отлично работает с клиента. Когда я звоню FooRemote.getPluginRemoteControl(1), он пытается раздать один из реальных пультов плагинов, и он терпит неудачу:

??? Java exception occurred:
java.rmi.UnmarshalException: error unmarshalling return; nested exception is:
    java.lang.ClassNotFoundException: com.example.plugin.BarPluginRemoteControl (no security manager: RMI class loader disabled)

    at sun.rmi.server.UnicastRef.invoke(Unknown Source)

    at java.rmi.server.RemoteObjectInvocationHandler.invokeRemoteMethod(Unknown Source)

    at java.rmi.server.RemoteObjectInvocationHandler.invoke(Unknown Source)

    at $Proxy5.getPluginRemoteControl(Unknown Source)

Caused by: java.lang.ClassNotFoundException: com.example.plugin.BarPluginRemoteControl (no security manager: RMI class loader disabled)

[ more stuff deleted ] 

Что дает?

Ответы [ 3 ]

2 голосов
/ 04 октября 2010

Пожалуйста, пожалуйста, не помещайте классы в путь к классам RMI Registry. Это работает вокруг проблемы, но это не правильное решение. Это означает, что каждый раз, когда вы обновляете код своего сервера, вам нужно синхронизировать классы с вашим реестром RMI и всеми вашими клиентами . Правильным решением является предоставление необходимых классов в кодовой базе сервера с использованием URI http или ftp (не URI файла, пожалуйста!). Затем Реестр RMI и ваши клиенты смогут динамически обращаться к нужным классам через http или ftp.

Единственные классы, которые вы должны включить в базу кода, это удаленные интерфейсы к вашему серверу и любые классы, которые появляются в качестве параметров или возвращают значения из методов в этих интерфейсах, а также любые классы исключений, создаваемые этими интерфейсами. Я полагаю (но я не уверен), что для этого рекомендуется создать отдельный jar с суффиксом '-dl', который включает только эти файлы классов.

2 голосов
/ 29 сентября 2010

Возможно, вам нужно настроить SecurityManager. Ваш клиент не может найти класс com.example.plugin.BarPluginRemoteControl, потому что нет менеджера безопасности, чтобы дать ему доступ.

Попробуйте следующее:

К клиентскому коду добавить:

System.setSecurityManager(new java.rmi.RMISecurityManager());

Создайте файл политики с именем client.policy, содержащий:

grant{
    permission java.security.AllPermission;
};

Передайте файл политики в команду запуска клиента:

java -Djava.security.policy=client.policy  ... <main-class>...
1 голос
/ 29 сентября 2010

Реестру RMI также нужны классы в своем собственном пути к классам, если вы запускаете его в отдельной виртуальной машине.Я помню, что тратил слишком много времени на изучение этого трудного пути.

Рад, что смог помочь!

edit: очевидно, это не правильный подход, см. Ответ комментатора.

...