Showing posts with label EJB 3. Show all posts
Showing posts with label EJB 3. Show all posts

Wednesday, March 16, 2011

AOP (Aspect Oriented Programming) and EJB 3: Interceptors

An AOP system allows the separation of crosscutting concerns into their own modules. These modules are then applied across the relevant cross section of application code, such as the beginning of a method call.

EJB 3 supports AOP-like functionality by providing the ability to intercept business methods and lifecycle callbacks. EJB 3 interceptors are object that are automatically triggered when an EJB method is called. They do not provide all the functionality that a full-scale AOP package such as AspectJ offers but are easier to use.
These interceptors are called at the beginning of the bean method and when the method returns and it can inspect the return value or any exception thrown by the method.
Interceptors can be applied both on session beans and message driven beans.
Interceptors could be used for logging purposes or for any other purpose such as transaction or security informations.
In my application I created a logging interceptor that is called every time a user calls the login bean and I print in my business interceptor the username of the user.
This is the method that is called every time a user press the login button and calls the login bean. This method is annotated with the AroundInvoke metadata annotation. We can take the parameters passed to the method called by using the InvocationContext object and his getParameters() method. As you can see I got the Account parameter from the first position of the parameters array because I know that the first parameter that I passed to the authentication method is the Account object. 
After the logging of the user in this method I move on with the real method invocation using the method proceed() from the InvocationContext object.
Beyond these methods, the InvocationContext object has other interesting methods: the getTarget() method retrieves the bean instance of the intercepted method, the getMethod() retrieves the method name intercepted. We just saw the getParameters() method, there is also the setParameters that allows us to modify any parameter passed to the method intercepted. 
The getContextData() method allows us to share data, name-value pairs, between interceptors and retrieve these data in the interceptors chain. 
In the business method interceptor you can throw or handle checked and runtime exceptions. If an exception is thrown before the method is called, then the intercepted method will not be called at all. 

It is also possible to create interceptor lifecycle callback methods that intercept the lifecycle transition of the bean registered for the interceptor. These methods cannot throw checked exceptions and have to invoke the proceed() method of the InvocationContext at the end of the method to proceed the chain of interceptor lifecycle callback methods or the bean lifecycle callback method. In the next picture I show you mi entire Interceptor class: 



To register an interceptor to be called every time a bean's method is called we have to specify it in the bean class:


This is the annotation to be used for an interceptor on level class: it means that for every method called on my LoginBean class my interceptor CheckUserLogin will be called and the method annotated with the AroundInvoke annotation is executed. If we want this interceptor to be called for only one method in our bean we can move this annotation before the method signature. 
There could be three levels of interceptors: default, class level and method level. The default level interceptors will be called first, then the class level and finally the method level interceptors. 
In the @Interceptors annotation there could be a list of different interceptors and these are called in the order they appear on the list.  If we want to exclude a level of interceptors to be called for a given method or a class we could use the annotation @ExcludeDefaultInterceptors for both class and method level or @ExcludeClassInterceptors for the method we want to exclude these.

Monday, March 7, 2011

EJB 3 Lifecycle Callback Methods

Session beans have a lifecycle. This means that beans go through a predefined set of state transitions.
The container manages almost every aspect of session beans, from the creation, through to the injection of resources as you saw on my last post with the @Resource annotation, to the distruction of the bean.
Managing those actions allows the container to provide the abstractions that are some of the real value of using EJBs, like DI, transaction management, AOP, security, etc.
The lifecycle of a session bean has at least 2 events: the creation and the destruction. Stateful session beans have other 2 phases: activation and passivation.
The first phase of a bean lifecycle is the bean creation; it happens when a client receives an instance of a bean. During this phase a new instance of a bean is created an, it is initialized by calling its constructor and, if any resource is required, those will be injected in the newly created instance.
The last phase of a bean lifecycle is the bean destruction: it occurs when the container determines that the instance is no longer needed and all the resources previously injected in the bean will be released.

Lifecycle callbacks are bean methods, not exposed by the business interface, that the container uses to notify the bean about a lifecycle transition or an event. These methods could be used to perform business logic or to initialize or cleanup the injected resources.

 The callback methods common to all session beans are annotated with metadata annotations @PostConstruct and @PreDestroy.
The method annotated with the @PostConstruct annotation will be called by the container just after the creation of the bean, while the callback method annotated with the @PreDestroy annotation will be called by the container just before the destruction of the bean.
In the following picture you can see an example of these 2 methods in which I initialized and cleanup the resources I used on my LoginBean: the connection to the dataSource.


As you can see, the bean on the previous picture is a stateless session bean so I only have the callback methods inherent to the construction and the destruction of the bean, annotated as @PostConstruct and @PreDestroy. The only think I did in these methods is open the connection to the dataSource in the initialize method, and close the same connection to the dataSource in the cleanUp method that is called before the bean destruction by the container.

The stateful session bean, could have other two callback methods because of the other other two phases of its lifecycle. As you know the stateful session bean can maintain state to serve the same client during his session. If the client is inactive for a while, the stateful session bean is passivated, and when the client is back active the bean is re-activated. During these phases the container could call the other two callback methods to manage the resources of the bean or doing any other business logic. The methods associated with these two phases are annotated with the metadata annotations @PostActivate that will be called after the activation of the bean, and the @PrePassivate metadata annotation.


In the previous picture I have a stateful session bean. I used the same method for the @PostConstruct and @PostActivate lifecycle phase because I do need the same resources in both the phases: I open the connection to the dataSource. I also have only one method for @PreDestroy and @PrePassivate phases and in this method I close the connection to the dataSource.
If I want to do any other thing before or after one of the lifecycle phases I could create another method just for that phase.
Thats all for the callback methods, in the next method I will talk about the stateful session beans.