Pratik K. Shah
Pratik K. Shah

Reputation: 457

JAVA Intercept mechanism works only with CDI

I was trying to create a sample of Intercept mechanism in JAVA. The questions I have is,

1) Why it only works with injected object but not using simple constructor ?

2) How can I intercept without CDI and using constructors only ? Because I want to use constructors with some arguments (Not default constructor).

Working code

    public class StartingPoint extends HttpServlet 
    {

      private static final long serialVersionUID = 1L;
      // With CDI
      @Inject
      SimpleGreeting greeting;

      public void doGet(HttpServletRequest request,HttpServletResponse response) throws ServletException, IOException
      {
          System.out.println("Started");
          System.out.println(greeting.abc());
      }

    }

Not working code

    public class StartingPoint extends HttpServlet 
    {

      private static final long serialVersionUID = 1L;

      public void doGet(HttpServletRequest request,HttpServletResponse response) throws ServletException, IOException
      {
          // With simple constructor
          SimpleGreeting greeting = new SimpleGreeting();
          System.out.println("Started");
          System.out.println(greeting.abc());
      }

    }

Other classes (Same in both cases)

SimpleGreeting.java

    @MyInterceptorBinding
    public class SimpleGreeting 
    {

      public SimpleGreeting()
      {

      }

      public String abc() 
      {
          return "Greet";
      }

    }

MyInterceptorBinding.java

    @Inherited
    @InterceptorBinding
    @Retention(RUNTIME)
    @Target({ METHOD, TYPE })
    public @interface MyInterceptorBinding {
    }

MyInterceptor.java

    @Interceptor
    @MyInterceptorBinding
    public class MyInterceptor 
    {

        public MyInterceptor()
        {

        }

        @AroundInvoke
        public Object log(InvocationContext context) throws Exception 
        {
            System.out.println("Intercepted");
            return context.proceed();
        }
    }

Upvotes: 1

Views: 1042

Answers (3)

Adrian Shum
Adrian Shum

Reputation: 40066

  1. I believe it is because the interception mechanism is Proxy-base. Which means, although you think you are referring to a Foo, it is actually a proxy of Foo, for which do the interception logic, and delegate the call to the real Foo instance.

    Hence the container will need to manage the injection of beans (so it can create the proxy and inject the proxy instead of the actual bean). If you are instantiating by yourself, there is no way the container can do such work.

  2. Yes there is. For example for AspectJ, you can have runtime weaving to add those interception code into the classes in effect.

Upvotes: 0

Rouliboy
Rouliboy

Reputation: 1377

If you take a look at the javadoc : http://docs.oracle.com/javaee/6/api/javax/interceptor/InterceptorBinding.html , you will notice that @InterceptorBinding is an annotation associated to beans (i.e instances managed by the container as EJB, managed beans, etc.) :

Interceptor bindings are intermediate annotations that may be used to associate interceptors with target beans

Upvotes: 1

Andy Guibert
Andy Guibert

Reputation: 42966

1) Why it only works with injected object but not using simple constructor ?

When the greeting is injected using CDI, there is some "magic" happening under the covers. If CDI was only capable of calling a simple constructor, it wouldn't be a very useful technology.

So if you have the following code:

  @Inject
  SimpleGreeting greeting;

What's effectively happening under the covers is something like this:

SimpleGreeting greeting = injectGreeting();

private SimpleGreeting injectGreeting() {
  if ( /* MyInterceptorBinding annotation present on SimpleGreeting class */)
    new MyInterceptor().log(context); // this prints "Intercepted"
  return new SimpleGreeting();
}

2) Is there any way to intercept without CDI and using constructors only?

Technically yes, but interceptors are the easiest way. The only other way I can think of off the top of my head is a bytecode manipulation framework such as ASM.

Upvotes: 0

Related Questions