[JAVA] – CDI with beans and interceptors by examples

What is it ?

The “Context and Dependency Injection for the Java EE platform” (CDI) is a specification that says how we work with our facilities. It takes over management of them, defines how long they live and when you create.

How to configure CDI to work with Beans?

  • Within the WebContent / META-INF folder create a new context.xml file (or open the file if already exists). Add the contents below:
<?xml version="1.0" encoding="UTF-8"?>
<Context>
    <Resource name="BeanManager"
        auth="Container"
        type="javax.enterprise.inject.spi.BeanManager"
        factory="org.jboss.weld.resources.ManagerObjectFactory"/>
</Context>

Through this configuration Tomcat register CDI BeanManager when it will be starting. The BeanManager CDI is an internal class required to manage objects.

  • In WebContent / WEB-INF folder create a new beans.xml file with the following XML:
<beans>
</beans>

This file represents the CDI configuration file.

  • Download the JAR implementation of the CDI:

Here I will show for you an example using a servlet container .So, in this case use :weld-servlet.jar

Place the jar in the WebContent / WEB-INF / lib

Look, in this example for you understand we don’t use MAVEN and we are showing for you how to do the download and where you need put the .jar . However, I will recommend you use a package manager like MAVEN in a real situation.

 

Managing Beans with CDI

ATTENTION : Be very careful when importing the new annotation @ViewScoped:

@Named
@ViewScoped //javax.faces.view.ViewScoped
public class AutorBean implements Serializable{

 

@Named
@SessionScoped //javax.enterprise.context.SessionScoped
public class TemaBean implements Serializable {

@Named
@RequestScoped //javax.enterprise.context.RequestScoped
public class TemaBean implements Serializable {

 

 

@RequestScoped: Legacy request scope of the Servlet API, or begins when the client (eg .: Internet browser) makes a request to the application and ends when such a request is answered by the server;

@SessionScoped: Inherited session scope of Servlets API, is the user’s session. It begins the first request that a particular user is and ends when the client is idle for too long or when manually terminated by the application. Sessions are not shared by different users, which means that the same computer running two different browsers open has two different sessions with the application;

 

 

Callback methods

The @PostConstruct annotation indicates that this method should be called after the creation and injection. This method is also called Callback. The method is part of the object’s life cycle, here when the object is born.

As there is a note that indicates the beginning of the cycle, there is also a method that indicates the end of the life cycle!

@Named
@ViewScoped //javax.faces.view.ViewScoped
public class MyBean implements Serializable{

    @PostConstruct
    void init() {
        System.out.println("MyBean is borning ....");
    }

    @PreDestroy
    void death() {
        System.out.println("MyBean is dying ....");
    }

As MyBean is the scope of the screen (ViewScoped), he will die when the screen dies.

How to create annotations ?

What is an annotation ?

Enables metadata statement in our objects, that is, settings of a class can get into it. Metadata is often used for configuration attached to that class features. For example, we use the annotation Test to configure the JUnit understand that method as a test.

Example  :

The goal here is to create a note to be able to configure which methods need a transaction. In this example we will create just the annotation.

  • In the src folder of your project to create a new note with the Transactional name (right-click the src folder -> New -> Annotation). The note should be in the package tx:
package br.com.myproject.example.tx;

public @interface Transacional {
}
  • Now define that the annotation can be used on the class and method (Target):
@Target({ElementType.METHOD,ElementType.TYPE}) 
public @interface Transacional { }
  • Make sure the quote is valid during execution (Retention):
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.METHOD,ElementType.TYPE})
public @interface Transacional {

}
  • Retention and Target are generic settings that any annotation features. Now we declare that this annotation is associated with an interceptor (binding -Below we will speak about interception):
@InterceptorBinding
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.METHOD,ElementType.TYPE})
public @interface Transacional {

}

Now you can write down the methods of our assets which needed a transaction!

How to create Interceptors ?

What is an interceptor ?

An interceptor is a class used to interpose in method invocations or lifecycle events that occur in an associated target class.

An digram for you understand  :

Below you will see a digram with the Struts 2 interceptores for ActionInvocation class.

actioninvocation

More Information about interceptors: http://docs.oracle.com/javaee/6/tutorial/doc/gkigq.html

Example :

  • In the package “br.com.myproject.example.tx;” create a new class with the name “MyTrasactionManager”:
public class MyTrasactionManager implements Serializable {

}
  • The class will also use the notation @Transacional beyond the @Interceptor:
@Transacional
@Interceptor
public class MyTrasactionManager implements Serializable {
  • To manage the transaction inject the EntityManager:
@Inject
EntityManager manager;
  • Now we implement the method that actually calls begin and commit:
@AroundInvoke
public Object executeTX(InvocationContext context) throws Exception {
    manager.getTransaction().begin();
    Object result = context.proceed();
    manager.getTransaction().commit();
    return result;    
}
  • Finally, declare the interceptor beans.xml:
<beans>
    <interceptors>
        <class>br.com.myproject.example.tx.MyTrasactionManager</class>
    </interceptors>
</beans>

 

Example : Log Interceptor

 

Imagine you would like to measure the execution time of the methods. To make a measurement sufficient use currentTimeMillis () method of the System class in all methods;

long before = System.currentTimeMillis();
//your code
long after = System.currentTimeMillis();
System.out.println(after - before);
  • @Log Create a note that will be used in the methods:

@Log public List<T> getAllMyObjects() {  }

  • Create an interceptor “TimeExecutionInterceptor” and associate it with the @Log note. In interceptor method measures the time and prints on the console.

Annotation code :

 

//a anotação @Log:
@Target({ ElementType.METHOD, ElementType.TYPE })
@Retention(RetentionPolicy.RUNTIME)
@InterceptorBinding
public @interface Log {
}

Interception Code:

@Interceptor
@Log
public class TimeExecutionInterceptor implements Serializable{

    @AroundInvoke
    public Object log(InvocationContext contexto) throws Exception {
        long startTime = System.currentTimeMillis();
        String nameMethod = contexto.getMethod().getName();
        Object proceedContext = contexto.proceed();
        long endTime = System.currentTimeMillis();
        long result = endTime - startTime;
        System.out.println("Method Name: " + nameMethod 
                                + " Execution Time: " + result);
        return proceedContext;    
    }    
}

 

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s