public abstract String getCity();
public abstract String getState();
public abstract String getZipCode();
public abstract void setStreetAddr1(String street1);
public abstract void setStreetAddr2(String street2);
public abstract void setCity(String city);
public abstract void setState(String state);
public abstract void setZipCode(String zip);
public abstract Collection getAccounts();
public abstract void setAccounts(Collection accounts);
public void addAccount(AccountDTO accountDTO) {
InitialContext context = new InitialContext();
AccountHomeLocal accountHome = context.lookup("AccountHomeLocal");
AccountLocal account = accountHome.create(accountDTO);
Collection accounts = getAccounts();
accounts.add(account);
}
// Логика контейнера EJB
public abstract void setId(Integer id);
public abstract Integer getId();
public Integer ejbCreate(Integer id) { ... }
public void ejbPostCreate(Integer id) { ... }
// Остальные методы должны быть реализованы, но обычно остаются пустыми:
public void setEntityContext(EntityContext ctx) {}
public void unsetEntityContext() {}
public void ejbActivate() {}
public void ejbPassivate() {}
public void ejbLoad() {}
public void ejbStore() {}
public void ejbRemove() {}
}
В листинге не приведен ни соответствующий интерфейс LocalHome (по сути — фабрика, используемая для создания объектов), ни один из возможных методов поиска Bank, которые вы можете добавить.
Наконец, вы должны написать один или несколько дескрипторов в формате XML, которые определяют подробности соответствия между объектом и реляционными данными, желаемое транзакционное поведение, ограничения безопасности и т.д.
Бизнес-логика тесно привязана к «контейнеру» приложения EJB2. Вы должны субклассировать контейнерные типы, а также предоставить многие методы жизненного цикла, необходимые для контейнера.
Привязка к тяжеловесному контейнеру затрудняет изолированное модульное тестирование. Приходится либо имитировать контейнер, что непросто, либо тратить много времени на развертывание EJB и тестов на реальном сервере. Повторное использование за пределами архитектуры EJB2 практически невозможно из-за жесткой привязки.
Наконец, такое решение противоречит принципам объектно-ориентированного программирования. Один компонент не может наследовать от другого компонента. Обратите внимание на логику добавления нового счета. В EJB2 компоненты часто определяют «объекты передачи данных» (DTO), которые фактически представляют собой «структуры без поведения». Обычно это приводит к появлению избыточных типов, содержащих по сути одинаковые данные, и необходимости использования стереотипного кода для копирования данных между объектами.
Поперечные области ответственности
В некоторых областях архитектура EJB2 приближается к полноценному разделению ответственности. Например, желательное поведение в области транзакционности, безопасности и сохранения объектов объявляется в дескрипторах независимо от исходного кода.
Такие области, как сохранение объектов, выходят за рамки естественных границ объектов предметной области. Например, все объекты обычно сохраняются по одной стратегии, с использованием определенной СУБД[37] вместо неструктурированных файлов, с определенной схемой выбора имен таблиц и столбцов, единой транзакционной семантикой и т.д.