3 Replies Latest reply on May 18, 2006 5:11 PM by gavin.king

    Interceptors sort order

    denis-karpov

      Hi
      I have found that order of seam interceptors sometimes violates constraints, defined by @Within and @Around annotations.

      You can see it if You look at two beans in "booking" example, one with @LoggedIn interceptor another without. The relative position of ConversationInterceptor, BijectionInterceptor changes.
      ...... ConversationInterceptor, BijectionInterceptor ......
      ...... BijectionInterceptor, ConversationInterceptor ......

      ======================================
      I have fix it, by reimplementing sorter.
      Sorry, if i post it in wrong place.

      Changed file (modified function)
      org.jboss.seam.Component.java

      ....
       private void initInterceptors()
       {
       initDefaultInterceptors();
      
       for (Annotation annotation: beanClass.getAnnotations())
       {
       if ( annotation.annotationType().isAnnotationPresent(Interceptors.class) )
       {
       interceptors.add( new Interceptor(annotation, this) );
       }
       }
      
      // new Sorter<Interceptor>() {
      // protected boolean isOrderViolated(Interceptor outside, Interceptor inside)
      // {
      // Class<?> insideClass = inside.getUserInterceptor().getClass();
      // Class<?> outsideClass = outside.getUserInterceptor().getClass();
      // Around around = insideClass.getAnnotation(Around.class);
      // Within within = outsideClass.getAnnotation(Within.class);
      // return ( around!=null && Arrays.asList( around.value() ).contains( outsideClass ) ) ||
      // ( within!=null && Arrays.asList( within.value() ).contains( insideClass ) );
      // }
      // }.sort(interceptors);
       newSort(interceptors);
      
       log.trace("interceptor stack: " + interceptors);
       }
      ......
      


      Changed file (new function)
      org.jboss.seam.Component.java
      .......
       private List<Interceptor> newSort(List<Interceptor> list){
       List<SortItem<Interceptor>> siList = new ArrayList<SortItem<Interceptor>>();
       Map<Class<?>,SortItem<Interceptor>> ht = new HashMap<Class<?>,SortItem<Interceptor>>();
       for (Interceptor i : list){
       SortItem<Interceptor> si = new SortItem<Interceptor>(i);
       siList.add(si);
       ht.put(i.getUserInterceptor().getClass(),si);
       }
       for (SortItem<Interceptor> si : siList){
       Class<?> clazz = si.getObj().getUserInterceptor().getClass();
       Around around = clazz.getAnnotation(Around.class);
       Within within = clazz.getAnnotation(Within.class);
       if (around!=null){
       for (Class<?> cl : Arrays.asList( around.value() ) ){
       si.getAround().add( ht.get(cl) );
       }
       }
       if (within!=null){
       for (Class<?> cl : Arrays.asList( within.value() ) ){
       si.getWithin().add( ht.get(cl) );
       }
       }
       }
       //===========//
       SorterNew<Interceptor> sList = new SorterNew<Interceptor>();
       siList = sList.sort(siList);
       //siList = SortItem.sort(siList);
       //===========//
       list.clear();
       for (SortItem<Interceptor> si : siList){
       list.add(si.getObj());
       }
       return list ;
       }
      .......
      



      New file:
      org.jboss.seam.util.SorterNew
      package org.jboss.seam.util;
      
      import java.util.ArrayList;
      import java.util.List;
      
      public class SorterNew<T> {
       private List<SortItem<T>> list = null; //new ArrayList();
      
       public List<SortItem<T>> sort(List<SortItem<T>> lst){
       this.list = lst;
       List<SortItem<T>> res = new ArrayList<SortItem<T>>();
       SortItem<T> inmost = null;
       do{
       inmost = getInmost();
       if (inmost!=null){
       res.add(inmost);
       remove(inmost);
       }
       }while(list.size()>0 && inmost!=null);
       if (list.size()>0){
       throw new RuntimeException("Can not sort interceptors list:"+list.toString());
       }
       return res;
       }
       private void remove(SortItem<T> item){
       list.remove(item);
       for(SortItem<T> o : list){
       o.getAround().remove(item);
       }
       }
       private SortItem<T> getInmost() {
       SortItem<T> res=null;
       for(SortItem<T> o : list){
       if ((o.getAround().size()==0) && testNobodyWantsWithin(o) ){
       res = o;
       break;
       }
       }
       return res;
       }
       private boolean testNobodyWantsWithin(SortItem<T> item){
       boolean res = true;
       for (SortItem<T> o : list){
       if (o.getWithin().contains(item)){
       res = false;
       break;
       }
       }
       return res;
       }
      }
      


      [New file:
      org.jboss.seam.util.SortItem
      package org.jboss.seam.util;
      
      import java.util.ArrayList;
      import java.util.List;
      
      public class SortItem<T> {
       private T obj;
       private List<SortItem> around = new ArrayList<SortItem>();
       private List<SortItem> within = new ArrayList<SortItem>();
      
       public SortItem(T obj){
       this.obj = obj;
       }
       public T getObj(){
       return obj;
       }
      
       public List<SortItem> getAround() {
       return around;
       }
       public List<SortItem> getWithin() {
       return within;
       }
      }