Why #Component is used in Controller annotation - java

Below is source code of For Component Interface
#Target(ElementType.TYPE)
#Retention(RetentionPolicy.RUNTIME)
#Documented
public #interface Component {
and for Spring Controller annotation is as below
#Target({ElementType.TYPE})
#Retention(RetentionPolicy.RUNTIME)
#Documented
#Component
public #interface Controller {
Why #Component is added in Controller annotation ? What is its purpose ? What if I remove this line ?
I am clear about below annotation types which are used to create custom annotations.
#Documented Whether to put the annotation in Javadocs
#Retention When the annotation is needed
#Target Places the annotation can go
#Inherited Whether subclasses get the annotation

#Controller is a #Component (just like #Service, #Repository, #Endpoint etc.).
The #Component is used as a meta-annotation here so that it can be picked-up using component-scanning. Next to that the #Controller is a special component which will have some added functionality (Spring MVC takes care of that). If you remove the #Component annotation component-scan will not be able to detect it anymore.
You can also create your own #Component based annotations by simply creating your own annotation and putting #Component on it.

#Component is a generic stereotype for any Spring-managed component. #Repository, #Service, and #Controller are specializations of #Component for more specific use cases, for example, in the persistence, service, and presentation layers, respectively.
Read this answer

Related

Is Controller inheritance in Spring Boot good practice? [duplicate]

Can I somehow group a set of annotations on an abstract class, and every class that extends this class has automatically assigned these annotations?
At least the following does not work:
#Service
#Scope(value = BeanDefinition.SCOPE_PROTOTYPE)
class AbstractService
class PersonService extends AbstractService {
#Autowired //will not work due to missing qualifier annotation
private PersonDao dao;
}
The answer is: no
Java annotations are not inherited unless the annotation type has the #Inherited meta-annotation on it: https://docs.oracle.com/javase/7/docs/api/java/lang/annotation/Inherited.html.
Spring's #Component annotation does not have #Inherited on it, so you will need to put the annotation on each component class. #Service, #Controller and #Repository neither.
The short answer is: with the annotations that you mentioned in your example, no.
The long answer: there is a meta-annotation called java.lang.annotation.Inherited. If an annotation itself is annotated with this annotation, then when a class is annotated with it, its subclasses are also automatically annotated with it by implication.
However, as you can see in the spring source code, the #Service and #Scope annotation are not themselves annotated with #Inherited, so the presence of #Service and #Scope on a class is not inherited by its subclasses.
Maybe this is something that can be fixed in Spring.
I have this piece of code in my project and it works just fine, although it's not annotated as Service:
public abstract class AbstractDataAccessService {
#Autowired
protected GenericDao genericDao;
}
and
#Component
public class ActorService extends AbstractDataAccessService {
// you can use genericDao here
}
So you don't need to put annotation on your abstract class but even if you do you will still have to put annotation on all subclass as #Component or #Service annotations are not inherited.

SPRING BOOT annotation: are they required

Are #Component, #Service and #Repository optional in Spring Boot 2?
Example If have a controller class called FirstController annotated with #Controller, #RestController and #RequestMapping. I also have service classes called FirstService and SecondService and a repository called FirstRespository.
I didn't annotate any of the class except FirstController but still my application works.
Does this mean that those stereotype annotations are not required for your app to make it work? You just need it for convention and if you need to modify behaviour like scope etc.
Thanks for answering in advance.
They are not required in order for your application to work BUT they will not be picked up by Spring on your application launch nor you will have benefits of that annotation specification
#Component - generic stereotype for any Spring-managed component
#Repository - stereotype for the persistence layer
#Service - stereotype for service layer
Any code can pass when you write your Spring application, but annotation helps Spring to understand what should be created as a bean or a component and for which use.
Consider this:
#Service
public class MyService {
private IComponent component;
#Autowired
public MyService(IComponent component) {
this.preparingService = preparingService;
}
}
In order to autowire a class implementing IComponent, you need to have that class decorated with #Service or #Component in order for Spring to inject it into MyService when MyService is itself of course injected in your controller.

Slight Difference between #RestController & #Component

Although every page on internet says that #RestController is a specification of #Component.I dont know whether it has to be related with DispatcherServlet. But when I try below code by switching between #RestController & #Component, I don't see same behaviour :
First I tried with #RestController:
#RestComponent
public class TestController {
#RequestMapping(value="/testController", method=RequestMethod.POST,consumes=MediaType.APPLICATION_JSON_VALUE)
public void testController() {
System.out.println("Hello");
}
}
I got below output in Console:
Hello
Second I tried with #Component + #ResponseBody:
#Component
#ResponseBody
public class TestController {
#RequestMapping(value="/testController", method=RequestMethod.POST,consumes=MediaType.APPLICATION_JSON_VALUE)
public void testController() {
System.out.println("Hello");
}
}
I got an error on postman:
{
"timestamp": 1570998345860,
"status": 405,
"error": "Method Not Allowed",
"message": "Request method 'POST' not supported",
"path": "/testController"
}
If both annotations are same, then why is there a difference in output ??
Below is the Source code for #RestController & #Controller , which shows that both #RestController & #Controller are specification of #Component:
#Target(ElementType.TYPE)
#Retention(RetentionPolicy.RUNTIME)
#Documented
#Controller
#ResponseBody
public #interface RestController {
}
#Target({ElementType.TYPE})
#Retention(RetentionPolicy.RUNTIME)
#Documented
#Component
public #interface Controller {
}
Maybe it has to be related with DispatcherServlet. It might be possible that Dispatcher Servlet only check for URL in #RestController annotated classes.
#Controller is user in traditional controller and #RestController annotation was introduced to simplify the creation of RESTful web services. It's a convenience annotation that combines #Controller and #ResponseBody
#Controller annotation is simply a specialized of the #Component class and allows implementation classes to be autodetect through the classpath scanning.
#Controller is typically used in combination with a #RequestMapping annotation used on request handling methods.
The request handling method is annotated with #ResponseBody. This annotation enables automatic serialization of the return object into the HttpResponse.
#RestController is a specialized version of the controller. It includes the #Controller and #ResponseBody annotations and as a result, simplifies the controller implementation.
The controller is annotated with the #RestController annotation, therefore the #ResponseBody isn't required.
Every request handling method of the controller class automatically serializes return objects into HttpResponse.
see here in detail : https://www.baeldung.com/spring-controller-vs-restcontroller
Just because #RestController is a #Component does not mean you can achieve the same functionality by switching to the broader one #Component. Even with the addition of #ResponseBody, you don't achieve equivalent functionality (as expressed through the Request Method POST not being supported).
Replace #Component with #Controller, because a #RestController has the exact same functionality as a #Controller + #ResponseBody. You can also see this in the meta-annotations of #RestController, you see it is meta-annotated with #Controller instead of just #Component. In turn, #Controller is meta-annotated with #Component.
The #Controller , #RestController , #Service etc are all annotations that are meta-annotated with the #Component annotation. All these annotations are essentially specializations of the #Component annotation for specific use cases.
The #Component annotation is generally used to register a Spring bean.
The #Controller annotation even though it is annotated with #Component internally , it provides a different functionality altogether.By annotating a class with this annotation we are essentially telling spring to scan this class for #RequestMapping annotation to register beans for request mapping. This does not happen when you just use the #Component annotation.
When the spring application starts up, the DispatcherServlet will enable the RequestMappingHandlerMapping RequestMappingHandlerAdapter (which is a handler mapping which looks for #RequestMapping annotations on #Controllers). So when a request reaches the dispatcher servlet it gives it to the RequestMappingHandlerMapping which resolves the uri to a controller method bean.For more information read : DispatcherServlet, Updated Doc Spring 5.x HandlerMapping
Note :
In older versions of spring DefaultAnnotationHandlerMapping is enabled for this by spring.
So in summary :
#Component is a generic stereotype for any Spring-managed component
or bean.
#Repository is a stereotype for the persistence layer.
#Service is a stereotype for the service layer.
#Controller is a stereotype for the presentation layer (spring-MVC).
Spring [Doc][4].
The #Controller annotation indicates that a particular class serves
the role of a controller.
The basic purpose of the #Controller annotation is to act as a
stereotype for the annotated class, indicating its role. The
dispatcher will scan such annotated classes for mapped methods,
detecting #RequestMapping annotations (see the next section).
Annotated controller beans may be defined explicitly, using a standard
Spring bean definition in the dispatcher's context. However, the
#Controller stereotype also allows for autodetection, aligned with
Spring 2.5's general support for detecting component classes in the
classpath and auto-registering bean definitions for them.
Similar post : What's the difference between #Component, #Repository & #Service annotations in Spring?
You should not get the same behaviour because #Component is more generic. It only registers your class as a Spring Managed Bean. However, #RestController not only registers your class as a managed bean, it further registers it as an entry point for HTTP calls to the specified URL path. Same goes for other Layer specific annotations like #Repository, #Configuration e.t.c

Aspect for method annotated with annotation which are annotated with another annotation

Is it possible to make pointcut using Spring AOP for methods and type having annotation which was annotated with some annotation.
Here's my custom annotation:
#AccessRestriction
#Target({ElementType.METHOD, ElementType.TYPE})
#Retention(RetentionPolicy.RUNTIME)
public #interface HasPermission {
}
It annotated with this annotation:
#Target({ElementType.ANNOTATION_TYPE})
#Retention(RetentionPolicy.RUNTIME)
public #interface AccessRestriction {
}
So is it possible to create point cut which will handle all methods which are annotated with any annotation annotated with AccessRestriction.
I found solution.
I made such pointcut:
within(#(#test.security.access.AccessRestriction *) *) ||
execution(#(#test.security.access.AccessRestriction *) * *(..))

Customised annotation in spring

I have seen few examples where customized annotations were used. example
#SimpleAnnotation
class SampleBean {
#SimpleAnnotation
public String getName() {
return "AAA";
}
public void setName(String name) {
}
public int getHeight() {
return 201;
}
}
#Target( { ElementType.METHOD, ElementType.TYPE })
#Retention(RetentionPolicy.RUNTIME)
#interface SimpleAnnotation {
}
Can anyone tell why we use this?
Spring supports for many Annotation the concept of "meta-annotation". (I am not sure if it is for all.)
This mean that you can build your own annotation and annotate the annotation with one of springs "core" annotations.
For example:
#Target({ ElementType.FIELD, ElementType.PARAMETER, ElementType.TYPE })
#Retention(RetentionPolicy.RUNTIME)
#Service
public #interface MyService {
}
Then you can use this annotation instead of #Service. (Btw: #Service, #Repository, #Controller use the same technique to "inherit" from #Component)
One example that make heavy use of this is "inherit" from #Qualifier.
For an example and some explanation have a look at Spring Reference Chapter: 3.9.3 Fine-tuning annotation-based autowiring with qualifiers (The Example with #Genre is at the end of the chapter.)
One very usefull construct that can be done with that technique is, that it enables you to combine several Annotations to a (in your use case) more meaning full. So instead of writing at every class of some type allways the same two annotations, for example: #Service and #Qualifiyer("someting") (the org.springframework.beans.factory.annotation.Qualifier). You can create your custom annotation that is annotated with this two annotations, and then use in your beans only this one custom annotation. (#See Avoid Spring Annotation Code Smell Use Spring 3 Custom Annotations)
If you want to see how powerfull this technique can be use, you can have a look at Context and Dependency Injection Framework.
Question from the comment:
The #interface also has some variables defined inside it, what does that signify?
The Annotations (defined by #Interface) work a bit like beans. This Fields are the properties that can/must be define if you use the annotations. The values can be later on be read via reflection API.
For example the #Controller Annotation in Spring:
#Target({ElementType.TYPE})
#Retention(RetentionPolicy.RUNTIME)
#Documented
#Component
public #interface Controller {
String value() default "";
}
The field with name value is that field that can be used without explicit name it: (#Controller("myUrl") is the same #Controller(value="myUrl"))
You can create your own meta-annotations that collect several other Spring annotations to reduce meta-boilerplate in your code:
#Service
#Scope(value = "prototype")
#Transactional(readOnly = true, rollbackFor = RuntimeException.class)
public #interface ReadOnlyService {}
And then you can simply write:
#ReadOnlyService
public class RoleService {
}
Spring will find the #ReadOnlyService and semantically replace it with:
#Service
#Scope(value = "prototype")
#Transactional(readOnly = true, rollbackFor = RuntimeException.class)
public class RoleService {
}
Of course having custom annotations pays of when you have tons of services annotated with the same set of Spring annotations that can be replaced with one, well named annotation.
Examples taken from: Avoid Spring Annotation Code Smell: Use Spring 3 Custom Annotations
Custom annotations do not do anything on their own. They are simple markers in code. Their real power comes from tools that look for specific annotations. Like some of the other answers mention, Spring has several uses for annotations and now mechanisms for defining your own component types. Pretty neat. Another example, a few weeks ago I used AOP and a few custom annotations to provide simple method level result caching. Now that I have the caching engine in place, and the appropriate AOP hooks defined, if I want to cache a method, I simply add that annotation. Some people simply use the annotations as fancy metadata to improve readability.
At the end of the day, they are a fairly simple tool that you can use for a great number of things.
The best part of using custom annotations is that you don't have to make any configuration, Spring will auto detect that these beans are service components and everything will work fine. Custom Annotations are a very small feature added in Spring but are very useful.For details take a look at this
http://java.dzone.com/articles/avoid-spring-annotation-code-smell-use-spring3-custom-annotations
Two options:
you need the #Component annotation on your custom annotation. That way you can use your custom annotation to mark classes as beans. In addition, you can add a default scope and other meta-information
qualifiers - you can use qualifier annotations (annotated with the #Qualifier meta-annotation) to distinguish between implementations of the same interface.
A common pattern is also to use annotations in AOP pointcuts. Not specifically Spring, but often employed when making use of Spring AOP.

Categories