Thursday, December 12, 2013

Write Your Own Seam 2 Interceptors

When using Seam2, there are two main ways to implement a backing bean component:
  1. EJB3 - If EJB3 is available, this is a good choice.   Not only do you get all the Seam capabilities (@In, etc.) you also get all the EJB3 capabilties such as Interceptors.
  2. POJO - This is a good choice when EJB3 is not available, or if for some reason you are EJB-averse (you should see a doctor about that).
Today I was working with some existing POJO Seam components that could not use the nice EJB3 interceptors that I had already created.   I usually just convert these to stateful session beans, but I decided I'd try my hand at using a Seam interceptor.

What you need to create a Seam interceptor

  1. An interceptor class, annotated with  org.jboss.seam.annotations.intercept.Interceptor.   Usually the @Interceptor annotation will specify the interceptor order, for example:

    @Interceptor(around = {
            BijectionInterceptor.class,
            MethodContextInterceptor.class,
            ConversationInterceptor.class,
            SynchronizationInterceptor.class,
            ConversationalInterceptor.class,
            RemoveInterceptor.class,
            SeamInterceptor.class,
            SecurityInterceptor.class,
            TransactionInterceptor.class,
            EventInterceptor.class,
            HibernateSessionProxyInterceptor.class,
            ManagedEntityInterceptor.class
    })
    public class MyInterceptor {
    ...
        @AroundInvoke
        public Object aroundInvoke(InvocationContext invocation) throws Exception
        {
    ...    
    }
    
    Note: This uses org.jboss.seam.annotations.intercept.AroundInvoke, not the EJB3 annotation.
  2. Extend AbstractInterceptor to simplify getting access to the Component (the meta-data) for the intercepted object.
  3. An annotation that allows you to apply the interceptor to components.

    import org.jboss.seam.annotations.intercept.Interceptors;
    
    import java.lang.annotation.ElementType;
    import java.lang.annotation.Retention;
    import java.lang.annotation.RetentionPolicy;
    import java.lang.annotation.Target;
    
    @Target(ElementType.TYPE)
    @Retention(RetentionPolicy.RUNTIME)
    @Interceptors(MyInterceptor.class)
    public @interface MyInterceptorAnnotation {}
    
    
  4. The component class, with the custom annotation on it.

    @Name("myBackingBean")
    @Scope(ScopeType.CONVERSATION)
    @MyInterceptorAnnotation
    public class MyBackingBean implements Serializable
    {
       ...
    

Similarities and Differences between Seam Interceptors and EJB3 Interceptors

  • In both systems, the interceptor instance is scoped to the component.   That is, there is one instance of the interceptor for each intercepted component by default.
  • Seam interceptors can be forced to be stateless, so you can have stateless interceptor instances used with stateful components.
  • EJB3 interceptors have specific lifecycle methods.   With Seam Interceptors, you need to determine this in the @AroundInvoke method.
  • It's not as easy to apply Seam Interceptors to all components.   With an EJB3 interceptor, you can specify default interceptor bindings in META-INF/ejb-jar.xml.   (I'm not currently sure how you apply custom Seam interceptors implicitly)

No comments:

Post a Comment