2014-12-09 3 views
0

по теме: Passing remote parameters in RMIRMI Remote Collection без сериализации локали объектов

Здравствуйте,

Я ищу решение для следующей задачи: У меня есть региональные объекты (позволяет сказать, типа MyObject), которые представлены удаленно с помощью RemoteObject с ссылкой на эти объекты.

public class RemoteMyObject extends UnicastRemoteObject implements MyRemoteInterface { 

    MyObject refToLocale; 

    protected RemoteMyObject(MyObject locale) throws RemoteException { 
    super(); 
    refToLocale = locale; 
    } 

    @Override // MyRemoteInterface 
    public void doSomething() throws RemoteException { 
    System.out.println("did it!"); 
    } 

    public MyObject getLocale() { 
    return refToLocale; 
    } 
} 

Это работает как ожидалось. Я не хочу сериализовать MyObject, потому что он имеет ссылки на другие классы, не связанные с классом, и файлы классов являются enyrypted. Теперь у меня есть коллекции MyObject, и я хочу управлять ими удаленно. Поэтому я внедрил RemoteCollection.

public class MyRemoteCollection extends UnicastRemoteObject implements 
RemoteCollection<MyRemoteInterface> { 

    Collection<MyObject> localeCollection; 

    public MyRemoteCollection(Collection<MyObject> locale) throws RemoteException { 
    super(); 
    localeCollection = locale; 
    } 

    @Override 
    public Collection<RemoteMyObject> getItems() throws RemoteException { 
    ArrayList<RemoteMyObject> result = new ArrayList<RemoteMyObject>(); 
    for (MyObject locale : localeCollection) { 
     result.add(new RemoteMyObject(locale)); 
    } 
    return result; 
    } 

    @Override 
    public void delete(MyRemoteInterface obj) { 
    MyObject locale = ((RemoteMyObject)obj).getLocale(); 
    localeCollection.remove(locale); 
    } 

} 

Проблема теперь, что клиент вызывает getItems() через RMI обеспечением и получает Коллекцию Remote/прокси-объектов. Эти объекты могут быть использованы как обычные (я могу позвонить doSomething()), но как только я хочу удалить один из этих объектов, у меня есть проблема: delete() -Метод ожидает объект, который он может наложить на RemoteMyObject, чтобы получить ссылку на локаль, но поставленный аргумент - это просто заглушка, и поэтому сбой не выполняется.

Поскольку объект был первоначально создан на сервере, мой вопрос теперь, если я могу вернуть объект locale или если есть более элегантное решение для решения проблемы?

Благодарим за понимание.

Для полноты интерфейсов и сервером и клиентом:

public interface MyRemoteInterface extends Remote { 

    void doSomething() throws RemoteException; 

} 

public interface RemoteCollection<REM> extends Remote { 

    Collection< ? extends REM> getItems() throws RemoteException; 

    void delete(REM obj) throws RemoteException; 

} 

public class MainServer { 

    public static void main(String[] args) { 
    try { 
     Registry registry = java.rmi.registry.LocateRegistry.createRegistry(1099); 
     Collection<MyObject> coll = new ArrayList<>(); 
     coll.add(new MyObject()); 
     coll.add(new MyObject()); 
     coll.add(new MyObject()); 
     MyRemoteCollection remCol = new MyRemoteCollection(coll); 
     registry.rebind("mylist", remCol); 

    } catch (RemoteException e) { 
     e.printStackTrace(); 
    } 
    } 

} 

public class MainClient { 

    public static void main(String[] args) { 
    try { 
     Registry registry = LocateRegistry.getRegistry("localhost", 1099); 
     RemoteCollection<MyRemoteInterface> remCol = (RemoteCollection<MyRemoteInterface>)registry.lookup("mylist"); 
     for (MyRemoteInterface item : remCol.getItems()) { 
     item.doSomething(); 
     remCol.delete(item); 
     } 
    } catch (RemoteException | NotBoundException e) { 
     e.printStackTrace(); 
    } 
    } 
} 

ответ

0

Как сказал @EJP в комментариях, вам нужна карта для отображения шлейфов к реальным/местным объектам. Я добавил новый интерфейс

interface IdentifieableRemoteObject { 

    ObjID getObjectID(); 

} 

Затем я создал карту из ObjID к конкретному экземпляру реализующего класса.

class RemoteObjectCache { 

    private static WeakHashMap<ObjID, WeakReference<IdentifieableRemoteObject>> cache = new WeakHashMap<>; 

    public static void register(IdentiefieableRemoteObject iro) { 
    cache.put(iro.getID(), iro); 
    } 

    public IdentifieableRemoteObject lookUp(ObjID id) { 
    chache.get(id); 
    } 

} 

Я использую WeakHashMap со слабыми ссылками, так что (распределенный) процесс сбора мусора удалит неиспользуемые удаленные объекты, даже если они находятся на карте. Мои удаленные объекты регистрируют себя, вызывая RemoteObjectCache.register(this) в конструкторе theire.

0

Идея в RMI состоит в определении удаленных параметров метода и возвращаемых значений, как удаленный интерфейс, а не удаленного объекта.

Таким образом, отливка в способе delete() должна соответствовать MyRemoteInterface, а не RemoteMyObject.

Аналогично:

public Collection<RemoteMyObject> getItems() throws RemoteException { 

Изменить что подпись:

public Collection<MyRemoteInterface> getItems() throws RemoteException { 
+0

Благодарим за ответ, к сожалению, это не решило проблему. На самом деле я могу передать аргумент 'MyRemoteInterface', но тогда я не могу получить доступ к« MyObject », который я хочу удалить из коллекции на сервере.'RemoteCollectionInterface' определяет сигнатуру метода как ограниченный подстановочный знак' getItems() ', поэтому эта часть работает красиво, и я могу использовать этот метод. – Joachim

+0

Вам нужна карта, чтобы вы могли перейти от заглушек, которые вы получите в качестве параметров к фактическим экспортированным объектам, к которым они принадлежат. – EJP

+0

Спасибо, вот что я сделал наконец. – Joachim

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