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.
Related
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.
Is it possible use #Service/#Component instead of #Controller annotation in Spring MVC
( I checked this out and it doesn't work) but why?
The #Controller annotation is a specific type that, like all spring annotations, is derived from the #Component annotation. Note that, depending on use case, it may work, and it may not. Controller classes are often used for mapping server requests to responses.
You can view this Geeks for Geeks article for more info on when to use the #Controller annotation. If you have #RequestMapping annotations in your class, you will not get the same behavior with a Component as you will with Controller.
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
In my Spring application I have controllers with two annotations:
#Controller - Spring annotation
#AdminPanelController - my annotation
Is it possible change my annotation so I can used if with out the need to place #Controller in addition?
I want that Spring will process my annotation as #Controller annotation.
Your question is missing some detailed explanation on your needs, but my assumption is that you do not want to bother putting both your annotation and #Controller on your admin panel controllers. You want Spring-MVC you understand that any #AdminPanelController is-a #Controller.
This is exactly what #RestController annotation in Spring 4.0 any #RestController is-a #Controller (See the source code).
So your #AdminPanelController annotation should be similar to the one below
#Target(ElementType.TYPE)
#Retention(RetentionPolicy.RUNTIME)
#Documented
#Controller
public #interface AdminPanelController {
String value() default "";
}
So although java annotation does not support inheritance in the sense we expect (see Why is not possible to extend annotations in Java?) this will work for spring-mvc thanks to meta-annotation (I tested this with 4.1).
I'm reasonably sure that all you need is to annotate the AdminPanelController with #Controller
org.springframework.stereotype;
or
org.springframework.web.servlet.mvc;
I had been using the stereotype but just noticed I have another option ?
org.springframework.stereotype.Controller
Is an annotation. It indicates that the annotated class is a controller as well as a candidate for auto-detection (like a #Component). This is the annotation you want to use.
org.springframework.web.servlet.mvc.Controller
Is an interface for implementing controllers. In most simple cases you probably don't want to be using this.