30 сентября 2012 г.

Пример простого EJB 3.0 на JBoss 6.1.0

Рассмотрим пример создания простого компонента EJB (Enterprise JavaBean) версии 3.0, развёрнутого на сервере приложений JBoss 6.1.0. Пример состоит из самого компонента, а также клиентской части, которая его вызывает. Главное достоинство EJB заключается в том, что клиент взаимодействует с ним как с обычным классом, при этом EJB может находиться на удалённом сервере. При этом от клиента скрыта вся сложность сетевого взаимодействия.

Создадим компонент, который содержит единственный метод getCurrentDate. Этот метод возвращает текущее время. Для начала определим remote-интерфейс:
@Remote
public interface MyTestBeanRemote {
public Date getCurrentDate();
}
Метод EJB может возвращать абсолютно любой объект. Главное, чтобы на стороне клиента имелось описание этого объекта.

Далее создадим сам класс EJB, унаследованный от remote-интерфейса:
@Stateless
public class MyTestBean implements MyTestBeanRemote {
@Override
public Date getCurrentDate() {
return new Date();
}
}
Обратите внимание на аннотацию @Stateless перед определением класса. Она означает, что данный EJB не сохраняет своё состояние для каждого клиента. Иными словами, все клиенты работают с одним экземпляром этого компонента. В нашем примере это не имеет значения, а вот если бы у нашего класса имелось какое-нибудь свойство, тогда разумнее было бы вместо @Stateless поставить @Stateful. Тогда каждый клиент работал бы со своим экземпляром.

Также у EJB может быть определён local-интерфейс, похожий на remote-интерфейс, но в нашем примере это было бы лишним.

Для развёртывания EJB достаточно его скомпилировать в jar-файл и поместить в папку server/your_config/deploy в JBoss, где your_config - имя вашей конфигурации, например, all.

Теперь перейдём к созданию клиента. Если клиент и EJB развёрнуты на разных серверах, то на клиенте должен быть хотя бы интерфейс данного EJB. В качестве клиента создадим вспомогательный класс Invoker.
public class Invoker {
private InitialContext getContext() throws NamingException {
final Properties prop = new Properties();
prop.put(Context.INITIAL_CONTEXT_FACTORY,
"org.jnp.interfaces.NamingContextFactory");
prop.put(Context.PROVIDER_URL, "jnp://127.0.0.1:1099");
return new InitialContext(prop);
}
public Date getCurrentDate()
{
try {
InitialContext ctx = getContext();
MyTestBeanRemote myTestBeanRemote = (MyTestBeanRemote) ctx
.lookup("MyTestBean/remote");
return myTestBeanRemote.getCurrentDate();
} catch (NamingException e) {
e.printStackTrace();
}
return null;
}
}
Метод getContext устанавливает подключение к JNDI-сервису, который обычно работает на порту 1099 сервера с JBoss. В данном примере идёт обращение на локальный сервер. Если вы используете удалённый сервер для EJB, просто измените адрес сервера в этой строке:
prop.put(Context.PROVIDER_URL, "jnp://127.0.0.1:1099");
Метод getCurrentDate вызывает необходимый нам метод EJB. Для этого он получает его удалённый интерфейс при помощи метода lookup("MyTestBean/remote"). В качестве значения передаётся имя EJB, затем слеш, затем имя интерфейса (remote или local).

Наш пример готов. Теперь вспомогательный класс можно вызвать, например, с jsp-страницы для получения результата работы EJB.

P.S. В промышленных системах использовать null в качестве возвращаемого значения не рекомендуется. Это вынуждает использовать дополнительную проверку на неопределённом значение, а также ухудшает читаемость кода. Вместо этого можно возвращать пустой экземпляр объекта (в случае коллекций это будет список, не содержащий ни одного элемента) или генерировать исключение.

2 комментария:

  1. Как вызвать public Date getCurrentDate() с jsp страницы?

    ОтветитьУдалить
    Ответы
    1. Я правильно понимаю, что вы хотите делать remote-вызовы EJB с jsp-страницы?

      Удалить