Writing Collapsed EAR and CDI Applications With SIwpas
SIwpas, Simple Web Profile Application Server is a Java EE Web Profile compatible server that contains the Apache Software Foundation projects. SIwpas aim is to integrate Apache Software Foundation(ASF) JavaTM Platform, Enterprise Edition 6 (Java EE 6) Web Profile Specification related projects into the Apache Tomcat 7 for producing a Java EE 6 Web Profile compatible server.
In this article, I will show a simple Calculator JSF 2.0 example outlining:
- How to use EJBs in CDI Managed Beans using dependency injection,
- How to use CDI Interceptors and Decorators for EJB session beans
- How to use CDI Managed beans in JSF 2 runtime
If you would like to try the example, download SIwpas from http://code.google.com/p/siwpas/ , sample Eclipse Web Project "siwpas-sample-collapse" from http://siwpas.googlecode.com/svn/trunk/samples/siwpas-sample-collapse/ and deploy it into the SIwpas!. Hit the URL, http://localhost:8080/siwpas-sample-collapse/calculate.jsf
Example Screens
Initial Screen

Writing 5 to X and 5 to Y, and click Calculate
Let's start to code!
We will have a JSF page that adds two numbers and prints result to page.
JSF 2 CDI Managed Bean
We have a JSF CDI Managed bean that we will use it from our JSF page via EL expressions. Our managed bean has @RequestScoped, means that it will be instantiated at the start of request and discard at end of request by OpenWebBeans CDI container. It's name is "calculator that is explicitly defined by @Named annotation. If we would want default name for our managed bean, just annotate it using @Name without "value".
Our managed bean injects an EJB session bean using two different approaches;
- Using @Inject annotation : This is provided by the CDI. Here OpenWebBeans injects CDI Session Bean that proxies the actual session bean instance proxy.
- Using @EJB annotation : This is provided by the Java EE. Here OpenWebBeans directly injects Session Beans proxy instance.
@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;
}
}
Writing Our Session Bean
We will have stateless session bean. First write an local interface,
@Local
public interface ICalculator
{
public int add(int x,int y);
}
Then, implementation
@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");
}
}
Here, you see some annotations on the Calculator Session Bean. @Stateless is a marker annotation that states class is a session bean. @Interceptors is defined by the EJB specification that adds interceptors to the session bean.
CDI Interceptors
Interesting thing here is @Log annotation. @Log is the CDI interceptor binding annotation. It adds CDI related interceptor instance to the session bean interceptor stack. It is called after old type interceptor instance.
Here is the code for @Log
@InterceptorBinding
@Retention(RetentionPolicy.RUNTIME)
@Target(value={ElementType.TYPE,ElementType.METHOD})
public @interface Log
{
}
@InterceptorBinding is a marker annotation for interceptor bindings.
Let's look at the actual interceptor
@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();
}
}
This is CDI based interceptor class. It is annotated with @Interceptor and @Log. It applies to all beans that are annotated with @Log, like our calculator bean.
CDI Decorators
CDI decorators are similar to CDI interceptors. Basic difference is that their methods are unique to some bean classes. Let's look at decorator class
@Decorator
public class AddDecorator implements ICalculator
{
private @Inject @Delegate ICalculator calculator;
public int add(int x, int y)
{
return calculator.add(x, y);
}
}
Here, we annotate AddDecorator class with @Decorator. AddDecorator class implements ICalculator and injects delegate instance with @Inject @Delegate. Here, @Delegate is important, because it provides information to CDI container regarding which bean instances will have this decorator in their's decorator stack. Here, AddDecorator is applied to all bean instances that have ICalculator in their API types. We can also add qulifier into the @Delegate injection points. In this case, decorator will be available for beans that have both same API type and qualifier. If there is no explicit qualifier, like above, qualifier is @Default.
CalculatorBean has an API type ICalculator and qualifier @Default. Therefore,AddDecorator is added into its decorator stack. Decorators are called after interceptors.
Enabling Intereptors and Decorators
To use interceptors and decorators, we have to enable them in the bean archive. Therefore we include them into WEB-INF/beans.xml file.
<beans>
<interceptors>
<class>siwpas.sample.interceptor.LogInterceptor</class>
</interceptors>
<decorators>
<class>siwpas.sample.decorator.AddDecorator</class>
</decorators>
</beans>
Now, they can be used inside the bean archive.
Our JSF Page
Let's look at our JSF page, look at how we use EL expressions with managed bean name, "calculator"
<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>
Our web.xml for some JSF stuff
<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>
How it Works
When a request comes from browser, CDI container looks for a bean with name "calculator". It finds the CalculatorBean and looks it's scope. In our example, our scope is @RequestScoped. It instantiates its instance and save it in the request scope. CDI container injects all of its dependencies (both CDI and Java EE dependencies. You can also inject @Resource, @WebServiceRef, @PersistenceContext, @PersistenceUnit Java EE components.)
When EL method "add" is executed, CDI container executes all interceptors, decorators of the EJB bean and finally execute the bean "add" method. After request is completed, request scoped is destroyed and all of its instances are discarded. Response is sent to the browser.
Conclusion
Java EE 6 simplifies the development of the web applications. That is the main motivation behind Java EE 6! It also provides Java EE Web Profile that contains only standards for implementing Java EE web applications.
Further Info
SIwpas Page : 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 Web Profile :http://jcp.org/en/jsr/detail?id=316

(Note: Opinions expressed in this article and its replies are the opinions of their respective authors and not those of DZone, Inc.)





Comments
Michal Huniewicz replied on Thu, 2010/07/22 - 4:58am
Gurkan, thanks for the article.
I got a question though. You said:
Our managed bean has @RequestScoped, means that it will be instantiated at the start of request and discard at end of request by OpenWebBeans CDI container.
From my observations, it isn't so, as I get TWO instances of a @RequestScoped bean per request, it's just that submitted properties are copied (but regular instance variable are gone).
Could you please clarify on that?
EDIT: Nah, my bad. Used @Named instead of @ManagedBean and it gave me strange behaviors. :)