Статьи

Написание свернутых приложений EAR и CDI с помощью SIwpas

SIwpas, Сервер приложений простого веб-профиля — это сервер, совместимый с веб-профилем Java EE, который содержит проекты Apache Software Foundation. Цель SIwpas — интегрировать проекты Apache Software Foundation (ASF) JavaTM, Enterprise Edition 6 (Java EE 6), связанные со спецификацией веб-профиля, в Apache Tomcat 7 для создания сервера, совместимого с веб-профилем Java EE 6.

 В этой статье я покажу простой пример калькулятора JSF 2.0 с изложением:

  • Как использовать EJB-компоненты в управляемых компонентах CDI с помощью внедрения зависимостей, 
  • Как использовать CDI Interceptors и Decorators для сессионных компонентов EJB
  • Как использовать управляемые компоненты CDI в среде выполнения JSF 2

Если вы хотите попробовать пример, загрузите SIwpas с http://code.google.com/p/siwpas/ , пример веб-проекта Eclipse «siwpas-sample-collapse» с http://siwpas.googlecode.com/svn / trunk / samples / siwpas-sample-collapse /   и развернуть его в SIwpas !. Нажмите на ссылку http: // localhost: 8080 / siwpas-sample-collapse / Calculate.jsf.

Примеры экранов

Начальный экран

Записать 5 в X и 5 в Y и нажать Рассчитать

Давайте начнем кодировать!

У нас будет страница JSF, которая добавляет два числа и печатает результат на странице.

JSF 2 CDI Managed Bean

У нас есть JSF CDI Managed bean, который мы будем использовать на нашей странице JSF через выражения EL. Наш управляемый bean-компонент имеет @RequestScoped, что означает, что он будет создан в начале запроса и отброшен в конце запроса контейнером CDI OpenWebBeans. Его имя — «калькулятор, который явно определен аннотацией @Named. Если нам нужно имя по умолчанию для нашего управляемого компонента, просто аннотируйте его, используя @Name без« значения ». 

Наш управляемый бин внедряет сессионный EJB-компонент, используя два разных подхода;

  1. Использование аннотации @Inject: предоставляется CDI. Здесь OpenWebBeans внедряет сессионный компонент CDI, который проксирует фактический прокси экземпляра сессионного компонента.
  2. Использование аннотации @EJB: это обеспечивается Java EE. Здесь OpenWebBeans напрямую внедряет экземпляр прокси-сервера Session Beans.

Результат тот же. Обе инъекционные техники работают в SIwpas. 

@Named(value="calculator")
@RequestScoped
public class CalculatorBean
{
//Inject using OpenWebBeans
private @Inject ICalculator calculator;

//Inject using @EJB with default interface type of field injection
private @EJB ICalculator injectViaEjbAnnotation;

private int x;

private int y;

private int result;

public String add()
{
this.result = calculator.add(x, y);
System.out.println(injectViaEjbAnnotation.add(x, y) == this.result);
return null;
}

public int getX()
{
return this.x;
}

public void setX(int x)
{
this.x = x;
}

public int getY()
{
return y;
}

public void setY(int y)
{
this.y = y;
}

public int getResult()
{
return this.result;
}

public void setResult(int rESULT)
{
this.result = rESULT;
}
}

 Написание нашего сессионного компонента

У нас будет сессионный компонент без сохранения состояния. Сначала напишите локальный интерфейс,

@Local
public interface ICalculator
{
public int add(int x,int y);
}

 Затем реализация

@Stateless
@Log
@Interceptors(value={OldTypeInterceptor.class})
public class Calculator implements ICalculator
{
private @Inject SimpleBean simpleBean;

public int add(int x, int y)
{
System.out.println(simpleBean);
return x+y;
}

@PostConstruct
public void postConstruct()
{
System.out.println("In post construct Bean");
}
}

Здесь вы видите некоторые аннотации на бине сеанса калькулятора @Stateless — это маркерная аннотация, в которой говорится, что класс является сессионным компонентом. @Interceptors определяется спецификацией EJB, которая добавляет перехватчики к сессионному компоненту. 

CDI Interceptors

Интересная вещь здесь — аннотация @Log. @Log — аннотация привязки перехватчика CDI. Он добавляет связанный с CDI экземпляр перехватчика в стек перехватчика сессионного компонента. Он вызывается после экземпляра перехватчика старого типа.

Вот код для @Log

@InterceptorBinding
@Retention(RetentionPolicy.RUNTIME)
@Target(value={ElementType.TYPE,ElementType.METHOD})
public @interface Log
{

}

 @InterceptorBinding — это маркерная аннотация для привязок перехватчиков. 

Давайте посмотрим на фактический перехватчик

@Interceptor
@Log
public class LogInterceptor
{
private @Inject SimpleBean simple;

@PostConstruct
public void postConstruct(InvocationContext context)
{
System.out.println(simple);
System.out.println("Post Construct");
}

@PreDestroy
public void preDestroy(InvocationContext context)
{
System.out.println("Pre Destroy");
}

@AroundInvoke
public Object around(InvocationContext ctx) throws Exception
{
System.out.println("Logging");
return ctx.proceed();
}
}

Это класс перехватчиков на основе CDI. Он аннотирован @Interceptor и @Log. Это относится ко всем bean-компонентам, аннотированным @Log, например, к нашему bean-компоненту калькулятора

 CDI Декораторы

 CDI-декораторы похожи на CDI-перехватчики. Основное отличие состоит в том, что их методы уникальны для некоторых классов бинов. Давайте посмотрим на класс декоратора

@Decorator
public class AddDecorator implements ICalculator
{
private @Inject @Delegate ICalculator calculator;

public int add(int x, int y)
{
return calculator.add(x, y);
}

}

Здесь мы аннотируем класс AddDecorator с помощью @Decorator. Класс AddDecorator реализует ICalculator и внедряет экземпляр делегата с помощью @Inject @Delegate. Здесь, @Delegate важен, потому что он предоставляет информацию контейнеру CDI относительно того, какие экземпляры бинов будут иметь этот декоратор в своем стеке декораторов. Здесь AddDecorator применяется ко всем экземплярам бинов, которые имеют ICalculator в своих типах API. Мы также можем добавить qulifier в точки ввода @Delegate. В этом случае декоратор будет доступен для bean-компонентов, имеющих одинаковый тип API и спецификатор. Если явного квалификатора нет, как указано выше, квалификатор — @Default.

CalculatorBean имеет тип API ICalculator и квалификатор @Default. Следовательно, AddDecorator добавляется в его стек декоратора. Декораторы называются после перехватчиков. 

Включение Интерпреторов и Декораторов

Чтобы использовать перехватчики и декораторы, мы должны включить их в архиве компонентов. Поэтому мы включаем их в файл WEB-INF / beans.xml.

<beans>
<interceptors>
<class>siwpas.sample.interceptor.LogInterceptor</class>
</interceptors>

<decorators>
<class>siwpas.sample.decorator.AddDecorator</class>
</decorators>
</beans>

 Теперь их можно использовать внутри архива бинов.

Наша страница JSF

Давайте посмотрим на нашу страницу JSF, посмотрим, как мы используем выражения EL с именем управляемого компонента, «калькулятор»

<html xmlns="http://www.w3.org/1999/xhtml" xmlns:h="http://java.sun.com/jsf/html">
<h:head>
<title>Collapsed EAR</title>
</h:head>
<h:body>
<h:form>
<h:outputText>X :</h:outputText>
<h:inputText value="#{calculator.x}"></h:inputText>
<h:outputText>Y :</h:outputText>
<h:inputText value="#{calculator.y}"></h:inputText>

<h:commandButton value="Calculate" action="#{calculator.add}"></h:commandButton>
</h:form>
<div>
<h:outputText value="Result : #{calculator.result}"></h:outputText>
</div>
</h:body>
</html>

Наш web.xml для некоторых вещей JSF

<web-app xmlns="http://java.sun.com/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd"
version="3.0">

<context-param>
<param-name>javax.faces.DEFAULT_SUFFIX</param-name>
<param-value>.jsp</param-value>
</context-param>

<servlet>
<servlet-name>Faces Servlet</servlet-name>
<servlet-class>javax.faces.webapp.FacesServlet</servlet-class>
<load-on-startup>1</load-on-startup>
</servlet>

<servlet-mapping>
<servlet-name>Faces Servlet</servlet-name>
<url-pattern>*.jsf</url-pattern>
</servlet-mapping>

</web-app>

 Как это работает

Когда запрос поступает из браузера, контейнер CDI ищет компонент с именем «калькулятор». Он находит CalculatorBean и смотрит его объем. В нашем примере наша область действия — @RequestScoped. Он создает свой экземпляр и сохраняет его в области запроса. Контейнер CDI внедряет все свои зависимости (как CDI, так и Java EE. Вы также можете добавить компоненты @Resource, @WebServiceRef, @PersistenceContext, @PersistenceUnit Java EE.)

Когда EL-метод «add» выполняется, контейнер CDI выполняет все перехватчики, декораторы EJB-компонента и, наконец, выполняет метод «add». После завершения запроса область действия запроса уничтожается, и все его экземпляры отбрасываются. Ответ отправляется в браузер.

Вывод

Java EE 6 упрощает разработку веб-приложений. Это основная мотивация Java EE 6! Он также предоставляет веб-профиль Java EE, содержащий только стандарты для реализации веб-приложений Java EE.

Дальнейшая информация

Страница SIwpas: http://code.google.com/p/siwpas/

Apache OpenWebBeans: http://openwebbeans.apache.org

Apache MyFaces: http://myfaces.apache.org

Apache OpenJPA: http://openjpa.apache.org

Apache OpenEJB: http://openejb.apache.org

Apache Tomcat: http://tomcat.apache.org

Веб-профиль Java EE 6: http://jcp.org/en/jsr/detail?id=316