Сериализация Java и совместное использование экземпляров с использованием удаленных сервисов - PullRequest
0 голосов
/ 03 февраля 2009

В настоящее время я думаю о некоторых деталях проектирования удаленного взаимодействия / сериализации между приложением Java Swing WebStart (Fat Client) и некоторыми удаленными службами, работающими на Tomcat. Я хочу использовать HTTP-совместимый транспорт для связи с сервером, и, поскольку я уже использую Spring, я предполагаю, что Spring Remoting - хороший выбор. Но я открыт для других альтернатив здесь. Моя проблема дизайна лучше всего проиллюстрирована на небольшом примере

Клиент вызовет некоторые службы на удаленной стороне. Пример сервисного интерфейса:

public interface ServiceInterface extends Serialiazable {
    // Get immutable reference data
    public List<Building> getBuildings();
    public List<Office> getOffices();

    // Create, read and update Employee objects
    public insertEmployee(Employee employee);
    public Employee getEmployee();
    public void updateEmployee(Employee employee);
}

Здание и Офис являются неизменяемыми объектами справочных данных, например,

public Building implements Serializable {
    String name;
    public Building(String name) { this.name = name; }
    public String getName() { return name; }
}

public Office implements Serializable {
    Building building;
    int maxEmployees;
    public Office(Building building, int maxEmployess) {
        this.building = building;
        this.maxEmployees = maxEmployees;
    }
    public Building getBuilding() { return building; }
    punlic int getMaxEmployees() { retrun maxEmployees; }
}

Доступные здания и офисы не изменятся во время выполнения, и клиент должен предпочесть наличие списка выбора, условия фильтра, ... Я хочу, чтобы на клиенте был только один экземпляр каждого конкретного здания и офиса и один экземпляр на стороне сервера. На стороне сервера это не большая проблема, но на мой взгляд, проблема начинается здесь, когда я вызываю getOffices () после getBuildings (). Здания, возвращаемые getOffices (), используют один и тот же экземпляр Buildings (если им назначено одно и то же здание), но здания, возвращаемые getOffices () (на которые ссылаются объекты Office), не совпадают с теми зданиями, которые возвращает getBuildings ().

Это может быть решено с помощью некоторого метода getReferenceDate (), возвращающего обе информации в одном и том же вызове, но тогда проблема возникнет, если у меня есть Сотрудники, ссылающиеся на Офисы.

Я думал о какой-то пользовательской сериализации (readObject, writeObject), передающей только первичный ключ, и о том, как получить экземпляр объекта из некоторого класса, содержащего объекты ссылочных данных. Но является ли это лучшим решением этой проблемы? Я предполагаю, что эта проблема не является редкостью, но ничего не нашел в Google. Есть ли лучшее решение? Если нет, то как лучше всего это осуществить?

Ответы [ 2 ]

1 голос
/ 03 февраля 2009

Если вы собираетесь сериализоваться, вам, вероятно, потребуется реализовать readResolve, чтобы гарантировать, что вы не создаете дополнительные экземпляры:

Из Javadoc для Сериализуемых:

Классы, которые необходимо обозначить замена, когда экземпляр этого читать из потока следует реализовать этот специальный метод с точным подпись.

Объект ЛЮБОЙ ДОСТУП-МОДИФИКАТОР readResolve () выбрасывает ObjectStreamException;

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

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

Однако на более базовом уровне я бы поставил под сомнение весь подход - вместо того, чтобы пытаться гарантировать идентичность объекта по сети, что звучит, по крайней мере, как кошмар параллелизма, почему бы просто не пропустить необработанный данных и ваша логика определяет личность по идентификатору, как мы делали это во времена моего дедушки? Ваш бэкэнд имеет строительный объект, он получает его от внешнего интерфейса, сравнивает по идентификатору (если вы изменили объект на внешнем интерфейсе, вам нужно будет передать свой объект в центральное хранилище данных и определить, что изменилось, что может быть проблема синхронизации с несколькими клиентами, но у вас все равно будет эта проблема).

Передача данных удаленно через Spring-httpclient приятна и проста, чуть менее низкоуровнева, чем RMI.

0 голосов
/ 03 февраля 2009

Во-первых, я бы порекомендовал использовать RMI для удаленного взаимодействия, которое можно проксировать по HTTP (IIRC). Во-вторых, если вы сериализуете ServiceInterface, я считаю, что механизм сериализации будет поддерживать относительные ссылки, когда он десериализуется в удаленной JVM.

...