Saturday, February 13, 2010

EJB 3.0 introduced a standard interceptor model for session bean components. Interceptors are a great way of performing extra functionality. I will not go into detail of what Interceptors are. If you want to know more, google is your friend.

Prerequisites you should know:

Seam has a few built in Interceptors, these include but are not limited to:

BijectionInterceptor

MethodContextInterceptor

ConversationInterceptor

SynchronizationInterceptor

ConversationalInterceptor

RemoveInterceptor

SeamInterceptor

SecurityInterceptor

TransactionInterceptor

EventInterceptor

HibernateSessionProxyInterceptor

@BypassInterceptors will skip Interceptors

In this example I will show you two examples on how you can use your own interceptor as a way to enhance your security domain and measure how long each method takes to execute.

First example
Imagine this simple model. A user is connected to one organization, and only the user connected to that Organization is allowed to view information about that organization.

Let's say you print out the users organization, and you have a page with detailed information about that organization like this:

Now, imagine changing the organizationId in the request to show information about an organization you should initially not be allowed to see.

This is obviously very bad. We have restricted the component to role user, but another user can easily change the request to another id, and get hold of another organization.To fix this, you can add this extra security check:

Voila! Now if an authorized user tries to "hack" the system, you will throw a SecurityException. This is fine and works just fine. However, it is cumbersome to do and you have to remember to do this everywhere where these exploits exists. Wouldn't it be nice to just do this:

Note the @Interceptors(MyInterceptor.class). It is here we register this annotation to the Interceptor MyInterceptor.AnnotationHandler.java
Note that this is just an interface that all our custom annotations will inherit from

BasicHandler.java An abstract class all handler will extend from. Read javadoc and comments in code to get real understanding of what's going on. Much of this code is really not necessary for this simple example. But this is a good portion of the one we are using, and it is quite flexible.

Thats it! Now you can easily add new annotation and handlers and just add login in BasicHandler. If you look closely you will see that we automatically give all privileges to admin, but only check user's organization if they are role user. You can modify and do whatever fits your need.

Second Example

Finally I want to also mention the other Seam interceptor.This is taken directly from the Seam forum (Link here). Which will print something like this:

Lastly, we will create a simple filter that will print out the result. The filter is only installed in debug mode so that it doesn't run on production. Be aware that the interceptor will still run if you don't forget to uncomment the interceptor.TimingFilter.java

Finally create an annotation where you register the interceptor.@MeasureCalls

/**
* This is an annotation that is used with the Interceptor TimingInterceptor,
* that will measure time it takes to execute each method in a seam component.
*
* The filter that uses this interceptor only works in debug mode and you will need to set value to true
* on the TimingFilter. Otherwize you will not see anything when running this in production or test.
* However, the interceptor will still run, so be "careful" where you put this annotation.
*
* Usage:
* @AutoCreate
* @Name("theBeanILikeToInvestigate")
* @MeasureCalls
* public class TheBeanILikeToInvestigare
*
*
*/
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Interceptors(TimingInterceptor.class)
public @interface MeasureCalls {}

Just put @MeasureCalls on your component and all methods on that component will be invoked on.