В зависимости от того, откуда клиент станет вызывать сессионный EJB-компонент, классу EJB-компонента потребуется реализовывать удаленный или локальный интерфейсы либо не реализовывать вообще никакого интерфейса. Если ваша архитектура включает клиентов, которые находятся вне экземпляра виртуальной машины Java EJB-контейнера, то они должны использовать удаленный интерфейс. Как показано на рис. 7.3, это касается клиентов, работающих на отдельной виртуальной машине Java, в контейнере клиентского приложения (Application Client Container — ACC), или во внешнем веб-контейнере, или в EJB-контейнере. В этом случае клиентам придется вызывать методы сессионных EJB-компонентов с использованием удаленного вызова методов. Вы можете прибегнуть к локальному вызову, если EJB-компонент и клиент будут функционировать на одной и той же виртуальной машине Java. Это может быть вызов одним EJB-компонентом другого EJB-компонента или веб-компонента (сервлета, JSF), работающего в веб-контейнере на той же самой виртуальной машине Java. Кроме того, ваше приложение может использовать как удаленные, так и локальные вызовы в случае с одним и тем же сессионным EJB-компонентом.
Сессионный EJB-компонент может реализовывать несколько интерфейсов или не реализовывать ни одного. Бизнес-интерфейс — это стандартный Java-интерфейс, который не расширяет никаких EJB-специфичных интерфейсов. Как и любой Java-интерфейс, бизнес-интерфейсы определяют список методов, которые будут доступны для клиентского приложения. Для них могут использоваться следующие аннотации:
• @Remote — обозначает удаленный бизнес-интерфейс. Параметры методов передаются по значению и нуждаются в том, чтобы быть сериализуемыми как часть протокола RMI;
Рис. 7.3. Сессионные EJB-компоненты, вызываемые клиентами нескольких типов
• @Local — обозначает локальный бизнес-интерфейс. Параметры методов передаются по ссылке от клиента к EJB-компоненту.
Вы не сможете пометить один и тот же интерфейс несколькими аннотациями. Сессионные EJB-компоненты, которые вы видели до сих пор в этой главе, не имеют интерфейса. Представление без интерфейса является вариацией локального представления, которая обеспечивает все открытые бизнес-методы класса EJB-компонента локально без использования отдельного бизнес-интерфейса.
В листинге 7.2 показаны локальный (ItemLocal) и удаленный интерфейс (ItemRemote), реализуемые сессионным EJB-компонентом без сохранения состояния ItemEJB. Благодаря этому коду клиенты смогут вызывать метод findCDs() локально или удаленно, поскольку он определен в обоих интерфейсах. Метод createCd() будет доступен только удаленно с помощью RMI.
@Local
public interface ItemLocal {
··List
··List
}
@Remote
··public interface ItemRemote {
··List
··List
··Book createBook(Book book);
··CD createCD(CD cd);
}
@Stateless
public class ItemEJB implements ItemLocal, ItemRemote {
··//…
}
В качестве альтернативы коду из листинга 7.2 вы могли бы указать интерфейс в классе EJB-компонента. При этом вам пришлось бы включить имя интерфейса в аннотации @Local и @Remote, как показано в листинге 7.3. Это удобно, когда у вас имеются унаследованные интерфейсы, для которых вы не можете добавить аннотации, поэтому вынуждены использовать их в своем сессионном EJB-компоненте.
public interface ItemLocal {
··List
··List
}
public interface ItemRemote {
··List
··List
··Book createBook(Book book);
··CD createCD(CD cd);
}
@Stateless
@Remote(ItemRemote.class)
@Local(ItemLocal.class)
@LocalBean
public class ItemEJB implements ItemLocal, ItemRemote {
··//…
}
Если EJB-компонент обеспечивает хотя бы один интерфейс (локальный или удаленный), то он автоматически теряет представление без интерфейса. Тогда потребуется явным образом указать, что он обеспечивает представление без интерфейса, с помощью аннотации @LocalBean в отношении класса EJB-компонента. Как вы можете видеть в листинге 7.3, ItemEJB сейчас обладает локальным и удаленным интерфейсами, а также представлением без интерфейса.
Интерфейсы веб-служб