SPRING BOOT annotation: are they required - java

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.

Related

Spring is not creating the bean for #service annotated class when one of its method is annotated with #transactional

The spring application is failing to start as it could not find a bean for a class annotated with a #Service to be autowired in a configuration class. But it is only occurring when I am annotating a method in the that particular service class with #Transactional. Why this is happening?
While you annotate your class by #Transactional spring use AOP and if your class is final and has no interfaces it cannot create a proxy on your class.

ConditionalOnBean with RestController [duplicate]

There are spring boot 2.0.2 configuration
#Configuration
public class ApiConfig {
#Bean
#Profile("!tests")
#ConditionalOnProperty(name = "enabled", havingValue = "true")
public MyService service() {
return new MyServiceImpl();
}
}
... and some controller which should be created and added to application context only if MyService bean is initialized.
#RestController
#ConditionalOnBean(MyService.class)
public class MyController {
#Autowired
private MyService service;
}
It works Ok. But occasionally spring boot skips MyController creating. According to the logs MyService is created, but after any other beans(including all controllers), at the end.
Why boot does not process #Configuration beans prior to #RestController?
Thanks.
Why boot does not process #Configuration beans prior to #Controller?
Thanks.
Because Spring doesn't guarantee that.
As well as #ConditionalOnBean warns about this kind of issue in this specification :
The condition can only match the bean definitions that have been
processed by the application context so far and, as such, it is
strongly recommended to use this condition on auto-configuration
classes only. If a candidate bean may be created by another
auto-configuration, make sure that the one using this condition runs
after.
And you don't use the annotation in an auto-configuration class. You indeed specified it in a class annotated with #RestController.
I think that to achieve your requirement you should move the #RestController bean declaration in a #Configuration class that's imported via an EnableAutoConfiguration entry in spring.factories.

Spring Boot: #Autowired is not working for one of the class

I am developing OAuth implementation with Jwt tokens.
It's kind of weird but for class TokenAuthenticationService When I try to Autowired this class in a different package, I get
Consider defining a bean of type 'com.company.security.TokenAuthenticationService' in your configuration.
I did a workaround and added #Bean TokenAuthenticationService in that class.Now when I am trying to initialize an interface in the TokenAuthenticationService class, it gives the same type of error for that interface.
Consider defining a bean of type 'com.company.security.UserService' in your configuration.
ComponentScan annotation is configured like #ComponentScan({"com.company"})
What I am missing here and why?
You have two ways to define beans for autowiring in your project.
With classes defined by you, you can use the #Component annotation (or, for service classes, #Service annotation) this way:
#Service
public class TokenAuthenticationService { ... }
If you are using third party classes, you can configure them in a configuration class:
#Configuration
public MyProjectConfig {
#Bean
public ThirdPartyClass serviceClass() { new ThirdPartyClass(); }
}
(Using #Bean annotation is not a workround. You just need to understand its purpose...)
This way autowiring should work...
Pay attention to difference between #Component and #Bean annotations.

Does annotating a repository interface as #Component have any cons?

I have this interface:
public interface liteRepository extends CrudRepository<liteEntity, Long>, JpaSpecificationExecutor<liteEntity> {...}
It works, all is well.
However, intellij does not register this class as a spring component. If I annotate this interface with #Component, then intellij recognizes this as a spring bean and I can #Autowire this repository in my integration tests.
My code still works after annotation, but I'm not confident that I am not messing with things that I should not be messing with.
Question:
Is there any harm in adding the #Component annotation to this interface?
The only thing that #Component annotation means is that the class is eligible for becoming a Spring bean during Spring's component-scan.
So, if you want it to be a Spring bean and you did not define it as a Spring bean anywhere else, you can safely add the #Component annotation.
Of course, this will only work if you have the actual component scan configured somewhere(for, example <context:component-scan base-package="..."> in some Spring config file), which I am assuming you already heave, since the bean is properly getting autowired after you add the annotation.

Spring #ComponentScan for #Service

I have a package named com.example.service, and in my Spring Configuration class I have the annotation #ComponentScan({"com.example.service"},{"com.example.controller"}).
When I try to #Autowire a service, code compilation fails with a NoSuchBeanDefinitionException. The MyService interface is annotated with #Service.
Currently I use a quite ugly workaround and declare every single service bean in my ExampleConfig.java like
#Bean
public MyService myService() {
return new MyServiceImpl();
}
Generally the #ComponentScan seems to work, if I remove the controller package, the controllers are not found. What did I understand wrong? Please let me know, if I missed out any relevant information.
The MyService interface is annotated with #Service
You must annotate the implementation of your interface. Not the interface itself.
Try using below code for ComponentScan annotation for scanning multiple packages:
#ComponentScan({"com.example.service","com.example.controller"})
instead of
#ComponentScan({"com.example.service"},{"com.example.controller"})
#ComponentScan uses string array for scanning multiple base packages.

Categories