6 Replies Latest reply on Feb 7, 2011 10:49 AM by alesj

    Adding interceptor at runtime / dynamically

    alesj

      I'm trying to add EJB' AOP intreceptor for Weld, in some deployer.

      Should this work? Or when does EJB container assemble its AOP interceptors?

       

      As I tried debugging, but the interceptor is never hit.

      This is the test: https://github.com/alesj/core/compare/weld-848

       

      public class WeldEjbLifecycleInterceptorDeployer extends WeldAwareMetadataDeployer<JBossMetaData>
      {
         private Boolean done;
      
         public WeldEjbLifecycleInterceptorDeployer()
         {
            super(JBossMetaData.class, false);
            setStage(DeploymentStages.PRE_REAL);
         }
      
         @Override
         protected void internalDeploy(VFSDeploymentUnit unit, JBossMetaData jbmd, Collection<VirtualFile> wbXml) throws DeploymentException
         {
            if (done != null)
               return;
      
            try
            {
               AspectDefinition def = new AspectDefinition("weld-aspect", Scope.PER_INSTANCE, new GenericAspectFactory(WeldLifecycleInterceptor.class.getName(), null));
               AdviceFactory advice = new AdviceFactory(def, "invoke");
               PointcutExpression pointcut = new PointcutExpression("weld-pointcut", "execution(* @" + PostActivate.class.getName() + "->*(..)) OR execution(* @" + PrePassivate.class.getName() + "->*(..))");
               InterceptorFactory[] interceptors = {advice};
               AdviceBinding binding = new AdviceBinding("weld-binding", pointcut, null, null, interceptors);
      
               AspectManager manager = AspectManager.getTopLevelAspectManager();
               DomainDefinition dd = manager.getContainer("Intercepted Bean");
               AspectManager domain = dd.getManager();
               domain.addAspectDefinition(def);
               domain.addInterceptorFactory(advice.getName(), advice);
               domain.addPointcut(pointcut);
               domain.addBinding(binding);
      
               done = true;
            }
            catch (Exception e)
            {
               done = false;
               throw DeploymentException.rethrowAsDeploymentException("Error setting Weld lifecycle interceptor", e);
            }
         }
      
         public static class WeldLifecycleInterceptor extends SessionBeanInterceptor implements Interceptor
         {
            public String getName()
            {
               return WeldLifecycleInterceptor.class.getName();
            }
      
            public Object invoke(final Invocation invocation) throws Throwable
            {
               return aroundInvoke(new InvocationContext()
               {
                  public Object getTarget()
                  {
                     return invocation.getTargetObject();
                  }
      
                  public Method getMethod()
                  {
                     return null;
                  }
      
                  public Object[] getParameters()
                  {
                     return new Object[0];
                  }
      
                  public void setParameters(Object[] params)
                  {
                  }
      
                  public Map<String, Object> getContextData()
                  {
                     return Collections.emptyMap();
                  }
      
                  public Object getTimer()
                  {
                     return null;
                  }
      
                  public Object proceed() throws Exception
                  {
                     try
                     {
                        return invocation.invokeNext();
                     }
                     catch (Throwable t)
                     {
                        throw new Exception(t);
                     }
                  }
               });
            }
         }
      }
      
      
        • 1. Adding interceptor at runtime / dynamically
          wolfc

          It's probably better if you modify JBossMetaData that adds an interceptor. This might require some transformation if interceptor-orders are used and such.

           

          Adding an interceptor that modifies the actual type of InvocationContext will probably fail, because we use custom InvocationContext types.

          • 2. Adding interceptor at runtime / dynamically
            alesj
            It's probably better if you modify JBossMetaData that adds an interceptor. This might require some transformation if interceptor-orders are used and such.

            We already do this, but it looks like our interceptor doesn't get hit for @PrePassivate / @PostActivate, hence no proper context.

            No idea why it doesn't get hit. Should it?

            Adding an interceptor that modifies the actual type of InvocationContext will probably fail, because we use custom InvocationContext types.

            Shouldn't this work as it is?

            Since original invocation::proceed will eventually be invoked, which has no knowledge of temp in-lined impl.

            • 3. Adding interceptor at runtime / dynamically
              wolfc

              The WeldEjbInterceptorMetadataDeployer only defines an aroundInvoke callback. It doesn't define any prePassivate/postActivate callbacks.

              • 4. Adding interceptor at runtime / dynamically
                alesj

                It doesn't define any prePassivate/postActivate callbacks.

                How do you do this? :-)

                • 5. Re: Adding interceptor at runtime / dynamically
                  wolfc

                  First SessionBeanInterceptor needs to have proper lifecycle callback methods which adhere to the following signature:

                  void <METHOD>(InvocationContext)
                  • 6. Re: Adding interceptor at runtime / dynamically
                    alesj

                    Which changes to metadata (in deployer) I need to make / add?