5 Replies Latest reply on Apr 22, 2008 5:02 AM by Matt Drees

    Configurable Interceptor

    Pawel Wrzeszcz Novice

      Hi there,

      I'd like to pass a String parameter to my interceptor, but since interceptors are not Seam Components I can't configure it in a way described in Chapter 4.

      So far, I came to the following solution:

          public Object inject(InvocationContext invocation) throws Exception {
              String myParam = (String) Component.getInstance("myParam");
              return invocation.proceed();

      In the components.xml file, I define myParam component:

      <factory name="myParam" value="Hello interceptor!" scope="APPLICATION"/>

      It works fine, but I don't like the idea of creating a Seam Component (called myParam), which is actually a configuration stuff, not a real component. Anyone knows any nicer way to pass a configuration parameter to Seam Interceptor? :)


        • 1. Re: Configurable Interceptor
          Hans Schlegel Newbie

          You could use Annotations.... I spent some time to develop a tracking interceptor - not relay tested yet!

          First you define a marker Annotation for class level:

          public @interface Trackable {}

          Second for method level:

          public @interface Tracked {
               * @return special RequestTrack-Parameter or RequestTrack-Parameters to track
              TrackedValue[] values() default {};

          public @interface TrackedValue {
              String parameter() default "";
              String expr() default "";

          Your interceptor should look something similar to:

          @Interceptor(stateless = true, around = AsynchronousInterceptor.class)
          public class TrackingInterceptor extends AbstractInterceptor implements Serializable {
              private static final long serialVersionUID = 4284998401280292997L;
              public Object aroundInvoke(InvocationContext invocationContext) throws Exception {
                  Method method = invocationContext.getMethod();
                  if (method.isAnnotationPresent(Tracked.class)) {
                      EntityManager em = (EntityManager) Component.getInstance("entityManager");  // TODO: eigener trackingEM
                      FacesContext fc = FacesContext.getCurrentInstance();
                      ExternalContext ec = fc.getExternalContext();
                      RequestTrack rt = new RequestTrack();
                      rt.setRequestTime(new DateTime().toDate());
                      Tracked trackedAnnotaion = method.getAnnotation(Tracked.class);
                      String result = "";
                      for (TrackedValue trv : trackedAnnotaion.values()) {
                          Object eval = Expressions.instance().createValueExpression(trv.expr()).getValue();
                          if (eval != null) {
                              String param = trv.parameter();
                              String val = eval.toString();
                              if (!"".equals(param) && !"".equals(val)) {
                                  rt.addTrackedParameter(trv.parameter(), eval.toString());
                  return invocationContext.proceed();

          Now you can use it like this:

          public class MunicipalitySearchAction implements MunicipalitySearach, Serializable {
              @Tracked(values = {
                  @TrackedValue(parameter = "name", expr = "#{municipalitySearch.municipalitySearchForm.name}"),
                  @TrackedValue(parameter = "id", expr = "#{municipalitySearch.municipalitySearchForm.statisticNumber}")
              public void edit(Municipality municipality) {

          I used this approach with the following Tracking Entity-Bean:

          @Entity(name = "HTTPRequest")
          public class RequestTrack {
              @Column(name = "Id")
              private Long id;
              @Column(name = "SessionId")
              @org.hibernate.validator.Length(max = 150)
              private String sessionId;
              @Column(name = "UserId")
              private Long userId;
              @Column(name = "RequestTime")
              private Date requestTime;
              @Column(name = "ComponentName")
              @org.hibernate.validator.Length(max = 150)
              private String componentName;
              @Column(name = "MethodName")
              @org.hibernate.validator.Length(max = 150)
              private String methodName;
              @Column(name = "ViewId")
              @org.hibernate.validator.Length(max = 150)
              private String viewId;
              @JoinTable(name = "HTTPRequest_Parameter",
                      joinColumns = @JoinColumn(name = "HTTPRequest_Id")
                      columns = @Column(name = "Parameter", nullable = false, length = 150)
              @Column(name = "Value", nullable = false, length = 250)
              private Map<String, String> trackedParameters = new HashMap<String, String>();

          • 2. Re: Configurable Interceptor
            Pawel Wrzeszcz Novice

            Hi Hans,

            Thanks for your reply. Yeah, using annotation parameters is an option. I don't know why I didn't think about it ;)

            This of course only allows configuration in the java code, but I hope that sooner or later interceptors will be configurable in the components.xml.


            • 3. Re: Configurable Interceptor
              Clint Popetz Apprentice

              I created a delegating interceptor which just takes the name of a component you wish to intercept with, which must contain a method annotated @AroundInvoke like a normal interceptor.  Code follows.  You'd use it like this:

              public class ClassIWantToIntercept() { 


              public class MyClass { 
                   public Object intercept(InvocationContext invocation, Component component) throws Throwable { 

              Note that all methods are intercepted by default, but that you can also apply @InterceptWith(allMethods=false) and then also apply @InterceptWith to each method you want to intercept.

              In InterceptWith.java:

              import static java.lang.annotation.RetentionPolicy.RUNTIME;
              import java.lang.annotation.ElementType;
              import java.lang.annotation.Retention;
              import java.lang.annotation.Target;
              import org.jboss.seam.annotations.intercept.Interceptors;
               * Annotating a class with @InterceptWith will cause the component specified with the annotation
               * to be intercept the invocation of any method in the target class
               * The component specified must have a method annotated @AroundInvoke.  
               * If @InterceptWith(allMethods=false) is specified, then only individual methods annotated
               * with @InterceptWith will be logged.  Conversely, if allMethods=true, you can turn off 
               * logging for an individual method with @InterceptWith(ignore=true).  
              public @interface InterceptWith{ 
                    * The name of a component that contains a method annotetd with @AroundInvoke
                   String value() default "";
                    * If "cacheable" is true, the implementation will assume that the component can be cached once
                    * instantiated, i.e. it is an Application scoped component.  Otherwise the component will be looked up
                    * upon each invocation, which can be costly, so be careful.
                   boolean cacheable() default true;
                    * If allMethods is turned off, only methods that are also annotated with @InterceptWith will be logged
                   boolean allMethods() default true;
                    * If ignore is turned on, logging for this method is ellided, even if allMethods is true for the class.
                   boolean ignore() default false;

              import java.io.Serializable;
              import java.lang.reflect.Method;
              import java.util.HashSet;
              import java.util.Set;
              import javax.annotation.PostConstruct;
              import org.jboss.seam.Component;
              import org.jboss.seam.annotations.intercept.AroundInvoke;
              import org.jboss.seam.annotations.intercept.Interceptor;
              import org.jboss.seam.intercept.InvocationContext;
               * Any component annotated with @InterceptWith InterceptWith will have this interceptor installed for it.
               * We just delegate to the @AroundInvoke method on the component which is identified by the InterceptWith value annotation parameter
               * @author cpopetz
              public class DelegatingInterceptor implements Serializable {
                   private transient InterceptWith classAnnotation;
                   private transient Component component;
                   private transient Object cachedDelegate;
                   private transient Set<Method> filteredMethods = new HashSet<Method>();
                   private transient Method delegateInterceptMethod;
                   public void setAnnotation(InterceptWith annotation) { 
                        this.classAnnotation = annotation; 
                   public void setComponent(Component component) { 
                        this.component = component; 
                    * Hook into postConstruct to set up the list of methods we should actually intercept,
                    * saving them in the filteredMethods set
                   public void postConstruct(InvocationContext context) {
                        boolean all = classAnnotation.allMethods();
                        for (Class clazz = component.getBeanClass(); clazz!=Object.class; clazz = clazz.getSuperclass() ) {
                             for (Method m : clazz.getDeclaredMethods()) {
                                  InterceptWith methodLevel = m.getAnnotation(InterceptWith.class);
                                  if ((all && (methodLevel == null || !methodLevel.ignore())) ||
                                            (!all && (methodLevel != null && !methodLevel.ignore())))
                   public Object intercept(InvocationContext invocation) throws Exception {
                        if (!filteredMethods.contains(invocation.getMethod()))
                             return invocation.proceed();
                        Object delegate = cachedDelegate;
                        if (delegate == null) {
                             delegate = Component.getInstance(classAnnotation.value());
                             if (classAnnotation.cacheable())
                                  cachedDelegate = delegate;
                              * Scan the delegate and find its @AroundInvoke method
                             if (delegateInterceptMethod == null) {
                                  for (Method m : Component.forName(classAnnotation.value()).getBeanClass().getDeclaredMethods()) {
                                       if (m.isAnnotationPresent(AroundInvoke.class)) 
                                            if (delegateInterceptMethod != null)
                                                 throw new RuntimeException("Can't annotate two methods in " + delegate.getClass().getName() 
                                                           + " with @AroundInvoke");
                                                 delegateInterceptMethod = m;
                                  if (delegateInterceptMethod == null)
                                       throw new RuntimeException("Must annotate a method in " + delegate.getClass().getName() 
                                                 + " with @AroundInvoke");
                        if (delegate != null) 
                             return delegateInterceptMethod.invoke(delegate, invocation, component);
                        else {
                             System.err.println("No delegate component for InterceptWith(\"" + classAnnotation.value() + "\") on invocation of " 
                                       + invocation.getMethod() + " on " + invocation.getTarget());
                             return invocation.proceed();

              • 4. Re: Configurable Interceptor
                Clint Popetz Apprentice

                I failed to mention that this of course means you can define your interceptors in components.xml, and annotate the methods you wish to intercept with @InterceptWith.