Differences between #Interceptors and #InterceptorBinding + #Logged? - java

Seems there are two ways to binding interceptor to target class/method:
#Interceptors on target class/method
Declare a interceptor binding type(aka, a custom annotation annotated with #InterceptorBinding itself, for example #Logged), and using it on target class/method
I am using interceptor in CDI environment. My question is, does it is completely unnecessary to declare a extra interceptor binding type if I using #Interceptors to binding interceptor to my target methods?
If answer is yes, then why IntelliJ IDEA constantly complaint me a error
#Interceptor must specify at least one interceptor binding
when I am not annotating interceptor binding type on my interceptor?
If answer is no, I already binding my interceptor to target class/method with #Interceptors(arrayOfMyInceptor) directly, why declare a extra interceptor binding type and using it on my interceptor?
I search the web but cannt found anything about difference of this two approaches, hope SO can solve my problem.
Thank you for your patience.

The annotations #Interceptor and other costum annotations like #Logged are supposed to be invoked on a interceptor class, e.g.
#Logged
#Interceptor
#Priority(Interceptor.Priority.APPLICATION)
public class LoggedInterceptor implements Serializable { ... }
The annotation #InterceptorBinding has to be invoked on the annotation you want to create to make clear it's somewhat of a "interceptor qualifier".
#Inherited
#InterceptorBinding
#Retention(RUNTIME)
#Target({METHOD, TYPE})
public #interface Logged {
}
Then you can invoke the interceptor-binding annotation on a (managed) bean or its methods.
#Logged
public String pay() {...}
#Logged
public void reset() {...}
See the java tutorial for more help https://docs.oracle.com/javaee/7/tutorial/cdi-adv006.htm
EDIT
Because I misread your question, here's my edit:
The annotation #Interceptors is like a collection of interceptors.
By passing several interceptor classes (e.g. LoggedInterceptor from #Logged) to the value variable of the applied #Interceptors annotation all those inteceptor bindings are invoked:
#Interceptors({LoggedInterceptor.class,
OtherInterceptor.class,.....})
Thus you need at least one interceptor binding for #Interceptors
So you need an interceptor binding for the interceptor class itself but not for the target class since it's already mentioned in the #Interceptors annotation.
See the API documentation https://docs.oracle.com/javaee/7/api/javax/interceptor/Interceptors.html

Related

#Around advice is not working with package level annotations

I want to add API versions across all log statements. To achieve that, I have created a custom annotation and its corresponding interceptor.
#Retention(RetentionPolicy.RUNTIME)
#Target({ElementType.METHOD, ElementType.TYPE, ElementType.PACKAGE})
#Around
#Documented
public #interface LogAPIVersion {
String apiVersion() default "";
}
Things are working fine if I place annotation on a method or a class.
But, I want to apply this annotation at a package level (for all classes and their methods). I've created a package-info.java file and decorated my custom annotation onthe package name.
#LogAPIVersion(apiVersion = "v1")
package com.example.controllers.v1;
Unfortunately, my logging interceptor is not getting invoked. How do I make this work?
The simple answer is: Neither native AspectJ nor simpler AOP frameworks such as Spring AOP provide any means to intercept package-level annotations.
What you could do is use native AspectJ's annotation processing support in order to generate annotations for all classes or methods you wish to target during your build and then intercept them using an aspect. Here are some of my old answers showing examples of how to use the feature:
https://stackoverflow.com/a/29877757/1082681
https://stackoverflow.com/a/40449796/1082681
https://stackoverflow.com/a/29437129/1082681
It might need to be annotated with #Inherited.

Custom Annotation works only for ElementType.METHOD

I'm practising with customs annotations and I want to create a custom annotation that set a Math.random() value to an #Entity field (I know that I can do this in the constructor but I want to do with an annotation)
My Annotation:
#Retention(RetentionPolicy.RUNTIME)
#Target(ElementType.CONSTRUCTOR)
public #interface SetRandomPin {}
2.My Aspect
#Around("#annotation(com.testingAnnotations.annotattions.SetRandomPin)")
public void setUserPin(ProceedingJoinPoint joinPoint) throws NoSuchMethodException {....}
}
In my #Entity when I put #SetRandomPin in the constructor, the method setUserPin is not firing.
Only If I change to ElementType.METHOD and I move my annotation to the UserService.class the method is firing.
I'm stuck here and I can't understand why is working with an ElmentType but not with another one.
Default Spring AOP doesn't offer constructor interception or private/protected methods. You can do it using AspectJ.
From docs
If your interception needs include method calls or even constructors within the target class, consider the use of Spring-driven native AspectJ weaving instead of Spring’s proxy-based AOP framework.

Is there a way to filter only a particular type of ServerResponse using PostProcessInterceptor?

PostProcessInterceptor will intercept all types of response. But in my case I have two categories of response. I have to intercept one kind and let go the other kind untouched (as a plain json string result).
Is there a way by which I skip the interception of the other response kind. May be some kind of marking? Or is there a way of doing this thing differently?
With JAX-RS 2 you could use a name binding for a ContainerResponseFilter. Define an annotation:
#NameBinding
#Retention(RetentionPolicy.RUNTIME)
#Target({ElementType.TYPE, ElementType.METHOD})
public #interface Special {}
And mark the filter:
#Provider
#Special
public class SpecialFilter implements ContainerResponseFilter {}
The filter will only be executed if the resource class or method is also annotated #Special.
If you need to use the deprecated PostProcessInterceptor you can't use name binding. But a simple if in the postProcess method will do the same.

#Stereotype annotation in Java

What's the purpose of #Stereotype annotation in Java EE?
I saw the documentation, but could not get much from it. Can someone point out with the help of an clear example.
Sterotypes are "roles" of software architectural components. For example a Service class or a Repository bean.
The #Sterotype annotation is a meta annotation and it is used to annotate annotation "classes" to state that the particular annotation is a stereotype definition.
#Stereotype
#Target(TYPE)
#Retention(RUNTIME)
public #interface Action {}
This example from the documentation shows how the annotation Action is annotated with #Sterotype. You could then annotate classes with #Action to make use of the Action stereotype.
Just check the Java EE API for Stereotype, which explains it. It is used in architecture to name reoccurring patterns. One example is the predefined Model annotation.

Writing interceptors for parameter annotations using Guice

Main References for My Question:
Writing Method Interceptors for Google Guice: http://code.google.com/p/google-guice/wiki/AOP
The JavaDoc for the MethodInterceptor interface: http://aopalliance.sourceforge.net/doc/org/aopalliance/intercept/MethodInterceptor.html
General references about Java annotations: http://docs.oracle.com/javase/tutorial/java/javaOO/annotations.html and http://docs.oracle.com/javase/1.5.0/docs/guide/language/annotations.html
Now My Question:
I am writing a Java application that heavily relies on Google Guice for creating objects and handling dependency injection. I am trying to use interceptors to run pre-processing code before certain annotated methods are executed. So far, I have successfully been able to execute interceptors (using the MethodInterceptor interface) on methods that have been annotated, using Guice's instructions. However, I want to now write interceptors that will execure on Parameter Annotations.
Here is an example scenario. First, I create my own annotation. For example::
#BindingAnnotation
#Retention(RetentionPolicy.RUNTIME)
#Target(ElementType.PARAMETER)
public #interface MyParameterAnnotation {
}
Next, I write my own interceptor for this annotation:
public class MyParameterAnnotationInterceptor implements MethodInterceptor {
#Override
public Object invoke(MethodInvocation invocation) throws Throwable {
// Do some stuff
return invocation.proceed();
}
}
Here's an example of how I intend on using #MyParameterAnnotation:
public class ExampleObject {
public String foo(#MyParameterAnnotation String param) {
...
}
}
Finally, I need to create a Guice Injector and use it to create an instalce of ExampleObject, or else I cannot use a method interceptor in this project. I configure the Injector so that the MyParameterAnnotationInterceptor is bound to #MyParameterAnnotation, like so:
final MethodInterceptor interceptor = new MyParameterAnnotationInterceptor();
requestStaticInjection(MyParameterAnnotationInterceptor.class);
bindInterceptor(Matchers.any(), Matchers.annotatedWith(MyParameterAnnotation.class), interceptor);
When I follow the above steps and execute a call to ExampleObject.foo(), unfortunately the interceptor is not executed despite the parameter being marked by #MyParameterAnnotation. Note that these similar steps will work if the annotation was placed at the method level instead.
This leads me to come up with two possible conclusions: either Guice cannot support binding an interceptor to a parameter annotation, or I am doing something completely incorrect (perhaps I should use another AOP Alliance interface for the interceptor, like FieldInterceptor, but I highly doubt it because the JavaDoc for Guice's AbstractModule suggests that the bindInterceptor() method can only use a MethodInterceptor parameter).
Nonetheless, all help us much appreciated :)
The matcher is for method annotations not method parameter annotations.
There is no matcher provided by Guice for method parameter annotations--you either have to write one yourself or use some other scheme. Note that this is a bit of an odd use case--Generally you can get away with
public class ExampleObject {
#MyAnnotation
public String foo(String param) {
...
}
}
You have the right Guice interceptor config for the above example.

Categories

Resources