#Autowire failing with #Repository - spring

I am not being able to make #Autowire annotation work with a #Repository annotated class.
I have an interface:
public interface AccountRepository {
public Account findByUsername(String username);
public Account findById(long id);
public Account save(Account account);
}
And the class implementing the interface annotated with #Repository:
#Repository
public class AccountRepositoryImpl implements AccountRepository {
public Account findByUsername(String username){
//Implementing code
}
public Account findById(long id){
//Implementing code
}
public Account save(Account account){
//Implementing code
}
}
In another class, I need to use this repository to find an account by the username, so I am using autowiring, but I am checking if it works and the accountRepository instance is always null:
#Component
public class FooClass {
#Autowired
private AccountRepository accountRepository;
...
public barMethod(){
logger.debug(accountRepository == null ? "accountRepository is NULL" : "accountRepository IS NOT NULL");
}
}
I have also set the packages to scan for the components (sessionFactory.setPackagesToScan(new String [] {"com.foo.bar"});), and it does autowire other classes annotated with #Component for instance, but in this one annotated with #Repository, it is always null.
Am I missing something?

Your problem is most likely that you're instantiating the bean yourself with new, so that Spring isn't aware of it. Inject the bean instead, or make the bean #Configurable and use AspectJ.

It seems likely that you haven't configured your Spring annotations to be enabled. I would recommend taking a look at your component scanning annotations. For instance in a Java config application:
#ComponentScan(basePackages = { "com.foo" })
... or XML config:
<context:annotation-config />
<context:component-scan base-package="com.foo" />
If your FooClass is not under the base-packages defined in that configuration, then the #Autowired will be ignored.
As an additional point, I would recommend trying #Autowired(required = true) - that should cause your application to fail on start-up rather than waiting until you use the service to throw a NullPointerException. However, if annotations are not configured, then there will be no failure.
You should test that your autowiring is being done correctly, using a JUnit test.
#RunWith(SpringJUnit4ClassRunner.class)
#ContextConfiguration(
classes = MyConfig.class,
loader = AnnotationConfigContextLoader.class)
public class AccountRepositoryTest {
#Autowired
private AccountRepository accountRepository;
#Test
public void shouldWireRepository() {
assertNotNull(accountRepository);
}
}
This should indicate whether your basic configuration is correct. The next step, assuming that this is being deployed as a web application, would be to check that you have put the correct bits and pieces in your web.xml and foo-servlet.xml configurations to trigger Spring initialisation.

FooClass needs to be instancied by Spring to have his depencies managed.
Make sure FooClass is instancied as a bean (#Component or #Service annotation, or XML declaration).
Edit : sessionFactory.setPackagesToScan is looking for JPA/Hibernate annotations whereas #Repository is a Spring Context annotation.
AccountRepositoryImpl should be in the Spring component-scan scope
Regards,

Related

How to use unit of work in rest controller properly?

public interface CourseRepo extends CrudRepository<Course, Long> {
}
#Getter
#Setter
#AllArgsConstructor
#NoArgsConstructor
public class UnitOfWork {
CourseRepo courses;
StudentRepository students;
StudyProgramRepository studyPrograms;
StudySchemeRepo studySchemes;
FeeStructureRepository feeStructures;
}
#RestController
public class TestController {
#Autowired
UnitOfWork uow;
#GetMapping("/addcr")
public String addCourse() {
Course cr = new Course();
cr.setTitle("DingDong course");
uow.getCourses().save(cr);
return "course Added..!!" ;
}
APPLICATION FAILED TO START
***************************
Description:
Field uow in com.srs.TestController required a bean of type 'com.srs.uow.UnitOfWork' that could not be found.
The injection point has the following annotations:
- #org.springframework.beans.factory.annotation.Autowired(required=true)
Action:
Consider defining a bean of type 'com.srs.uow.UnitOfWork' in your configuration.
if i remove autowired and add a bean
#RestController
public class TestController {
#Bean
public UnitOfWork uow() {
return new UnitOfWork();
}
#GetMapping("/addcr")
public String addCourse() {
Course cr = new Course();
cr.setTitle("DingDong course");
uow().getCourses().save(cr);
return "course Added..!!" ;
}
java.lang.NullPointerException: Cannot invoke "com.srs.jpa.CourseRepo.save(Object)"
because the return value of "com.srs.uow.UnitOfWork.getCourses()" is null
i tried both autowired and in this case how can i use autowired or bean properly ?
Your class need to be annotated with #Component to be used with DI provider by #Autowired annotation
For the same reason each repository of your class need to be annotated with #Autowired
The Error Message gives the answer.
Field uow in com.srs.TestController required a bean of type 'com.srs.uow.UnitOfWork' that could not be found.
spring is searching for a bean from type UnitOfWork. You have to add this class to the application context from spring boot. To accomplish this you have to annotate the class UnitOfWork with #bean or #Data if you use lombok.
After this the spring application can find the Class UnitOfWork and auto wire it.
Since UnitOfWork (a somewhat misleading name in the JPA context) autowires data repositories, it has to be a Spring Bean itself.
The easiest and most common way is to annotate the class with one of the annotations #Service, #Component or #Bean, depending on the semantic of the class. There are also other ways, like the #Bean on method-level as you used.
To use the fully initialized bean you need to autowire it where you want to use it, not calling the create method. E.g. calling uow() as in your sample, bypasses the Spring Bean mechanism and creates a new instance, which hasn't been fully initialized (thus the NullPointerException).
Usually, the beans are autowired as fields, sometimes they are autowired in mehtod parameters (especially when working with #Bean on method-level in the same class).
E.g.
#Component
#Getter
#RequiredArgsConstructor
public class UnitOfWork {
private final CourseRepo courses;
private final StudentRepository students;
private final StudyProgramRepository studyPrograms;
private final StudySchemeRepo studySchemes;
private final FeeStructureRepository feeStructures;
}

Autowiring of Service and Service Implementation class

Following are my code
#RestController
public class EmployeeController {
#Autowired
EmployeeService empService;
public EmployeeController (EmployeeService Impl empServiceImpl) {
super();
this.empService = empServiceImpl;
}
}
#Service
public interface EmployeeService {
public List<EmployeeDTO> getAllEmployeeDetails()
}
public class EmployeeServiceImpl {
public List<EmployeeDTO> getAllEmployeeDetails(){
//methods business logic and repo call goes here
}
}
When I start my server I am getting below error.
Parameter 1 of constructor in
com.app.in.controller.EmployeeController required a bean of type
'com.app.in.service.EmployeeServiceImpl' that could not be found
My understanding might be wrong. If I annotate the EmployeeSeriveImpl class also with #Service then it working.Is that is the correct way to do it ? My question is the service interface is annotated with #Service still why its implementation is also required to annotation. Please let me know if I miss something in that ? What is the standard method to solve this issue ?
You can get your dependency injected using a constructor. And #Autowired is optional in this case.
This is your example, but with a few corrections:
#RestController
public class EmployeeController {
// private final is a good practice. no need in #Autowire
private final EmployeeService empService;
// this constructor will be used to inject your dependency
// #Autowired is optional in this case, but you can put it here
public EmployeeController (EmployeeService empServiceImpl) {
this.empService = empServiceImpl;
}
}
I assume you have an interface EmployeeService and class EmployeeServiceImpl which implements that interface and is Spring Bean.
Something like this:
#Service
public class EmployeeServiceImpl implements EmployeeService {}
Why this #Service is needed? When you put this annotation on your class, Spring knows this is a bean that Spring should manage for you (container will create an instance of it and inject it wherever it is needed).
Check Spring docs to get more details about Dependency Injection.
The Spring team generally advocates constructor injection, as it lets you implement application components as immutable objects and ensures that required dependencies are not null.

Error on injecting service: UnsatisfiedDependencyException: There was no object available for injection at SystemInjecteeImpl

I am trying to inject service in spring boot app. However I'm getting following error:
org.glassfish.hk2.api.UnsatisfiedDependencyException: There was no object available for injection at SystemInjecteeImpl(requiredType=RecommendationService,parent=RecommendationResourceImpl,qualifiers={},position=-1,optional=false,self=false,unqualified=null,1163111460)
Here is the code:
package com.example.test.recommendations.resources;
#Provider
public class RecommendationResourceImpl implements RecommendationResource {
#Inject
private RecommendationService recommendationService;
#Override
public List<Recommendation> get(String currency,
String entity) {
return recommendationService.getRecommendations(currency, entity));
}
}
Service interface
package com.example.test.recommendations.resources;
// imports
public interface RecommendationService {
List<Recommendation> getRecommendations(String currency, String entity);
Recommendation get(UUID uuid);
}
Service implementation
package com.example.test.recommendations.resources;
//imports
#Component
public class RecommendationServiceImpl implements RecommendationService{
#Override
public List<Recommendation> getRecommendations(String currency, String entity) {
return Collections.emptyList();
}
#Override
public Recommendation get(UUID uuid) {
return null;
}
}
What is correct way to inject services in spring boot applications?
I am using spring boot version 1.3.8 and Jersey version 2.25.1
From your stacktrace it is evident that the server cannot find the dependency bean to be injected.So initially check that the desired bean for the class is getting created during applciation start up.Verify that the service class is in the classpath for component scan to take place, otherwise include the package for scanning.
You are using the #Inject annotation instead of the spring #Autowired annotation to inject the beans.It will work fine but the first and most important difference between #Autowired and #Inject annotation is that the #Inject annotation is only available from Spring 3.0 onwards, so if you want to use annotation-driven dependency injection in Spring 2.5 then you have to use the #Autowired annotation.
Secondly, use the annotation #Service for the service layer rather than using the #Component annotation.
Indicates that an annotated class is a "Service", originally defined
by Domain-Driven Design (Evans, 2003) as "an operation offered as an
interface that stands alone in the model, with no encapsulated state."
May also indicate that a class is a "Business Service Facade" (in the
Core J2EE patterns sense), or something similar. This annotation is a
general-purpose stereotype and individual teams may narrow their
semantics and use as appropriate.
This annotation serves as a specialization of #Component, allowing for
implementation classes to be autodetected through classpath scanning.
#Service
public class RecommendationServiceImpl implements RecommendationService{
#Override
public List<Recommendation> getRecommendations(String currency, String entity) {
return Collections.emptyList();
}
#Override
public Recommendation get(UUID uuid) {
return null;
}
}
I am not an expert on using jersey with springboot , so i do not know if any configurations are causing this issue.
Maybe this thread might be of help to you more:
Dependency injection with Jersey 2.0
You probably never registered your Service with the DI-container. You can do that in your ResourceConfig, which you probably have since you are using jersey:
public class MyApplication extends ResourceConfig {
public MyApplication() {
register(new org.glassfish.hk2.utilities.binding.AbstractBinder() {
#Override
protected void configure() {
bind(RecommendationServiceImpl.class).to(RecommendationService.class).in(Singleton.class);
}
});
packages("com.example.test.recommendations.resources");
}
}
I am using hk2 without spring, so I usually annotate my interfaces with org.jvnet.hk2.annotations.Contract and the implementations with org.jvnet.hk2.annotations.Service. (note: not the spring #Service annotation), so I recommend trying that as well.

what is the difference between #Bean annotation and #Component annotation at Spring?

It might be a very simple question for you.But I read lots of documents and I am totally confused.We can use #Component instead of #Bean or #Bean instead of #Component(as well as #Repository #Service #Controller) ?
Cheers
Component
#Component also for #Service and #Repository are used to auto-detect and auto-configure beans using classpath scanning.
As long as these classes are in under our base package or Spring is aware of another package to scan, a new bean will be created for each of these classes
Bean and Component are mapped as one to one i.e one bean per Class.
These annotations (#Component, #Service, #Repository) are Class level annotations.
Example:
Lets Say we have a UserService Class which contains all methods for User Operation.
#Service
public class UserService {
#Autowired
private UserRepository userRepository;
#Override
public User findByUsername( String username ) throws UsernameNotFoundException {
User u = userRepository.findByUsername( username );
return u;
}
public List<User> findAll() throws AccessDeniedException {
List<User> result = userRepository.findAll();
return result;
}
}
Spring will create a Bean for UserService and we can use this at multiple location/classes.
#Bean
#Bean is used to declare a single bean, rather than letting Spring do it automatically as in case of Component.
It decouples the declaration of the bean from the class definition, and lets you create and configure beans exactly how you choose.
#Bean are used at method level and can be configured as required
eg:
#Configuration
#EnableWebSecurity
#EnableGlobalMethodSecurity(prePostEnabled = true)
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
#Bean
public SpringTemplateEngine springTemplateEngine()
{
SpringTemplateEngine templateEngine = new SpringTemplateEngine();
templateEngine.addTemplateResolver(htmlTemplateResolver());
return templateEngine;
}
#Bean
public SpringResourceTemplateResolver htmlTemplateResolver()
{
SpringResourceTemplateResolver emailTemplateResolver = new SpringResourceTemplateResolver();
emailTemplateResolver.setPrefix("classpath:/static/template/");
emailTemplateResolver.setSuffix(".html");
emailTemplateResolver.setTemplateMode("HTML");
emailTemplateResolver.setCharacterEncoding(StandardCharsets.UTF_8.name());
return emailTemplateResolver;
}
...
Read more about Stereotype Annotations here.
#Bean is used to define a method as a producer, which tells Spring to use that method to retrieve an object of the method return type and inject that object as a dependency whenever it's required.
#Component is used to define a class as a Spring component, which tells Spring to create an object (if it's Singleton) from and take care of it's lifecycle and dependencies and inject that object whenever it's required.
#Service and #Repository are basically just like #Component and AFAIK they are just for better grouping of your components.
#Service for Defining your service classes where you have your business logic, and #Repository for Defining your repository classes where you interact with an underlying system like database.
#Component
If we mark a class with #Component or one of the other Stereotype annotations these classes will be auto-detected using classpath scanning. As long as these classes are in under our base package or Spring is aware of another package to scan, a new bean will be created for each of these classes.
package com.beanvscomponent.controller;
import org.springframework.stereotype.Controller;
#Controller
public class HomeController {
public String home(){
return "Hello, World!";
}
}
There's an implicit one-to-one mapping between the annotated class and the bean (i.e. one bean per class). Control of wiring is quite limited with this approach since it's purely declarative. It is also important to note that the stereotype annotations are class level annotations.
#Bean
#Bean is used to explicitly declare a single bean, rather than letting Spring do it automatically like we did with #Controller. It decouples the declaration of the bean from the class definition and lets you create and configure beans exactly how you choose. With #Bean you aren't placing this annotation at the class level. If you tried to do that you would get an invalid type error. The #Bean documentation defines it as:
Indicates that a method produces a bean to be managed by the Spring container.
Typically, #Bean methods are declared within #Configuration classes.We have a user class that we needed to instantiate and then create a bean using that instance. This is where I said earlier that we have a little more control over how the bean is defined.
package com.beanvscomponent;
public class User {
private String first;
private String last;
public User(String first, String last) {
this.first = first;
this.last = last;
}
}
As i mentioned earlier #Bean methods should be declared within #Configuration classes.
package com.beanvscomponent;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
#Configuration
public class ApplicationConfig {
#Bean
public User superUser() {
return new User("Partho","Bappy");
}
}
The name of the method is actually going to be the name of our bean. If we pull up the /beans endpoint in the actuator we can see the bean defined.
{
"beans": "superUser",
"aliases": [],
"scope": "singleton",
"type": "com.beanvscomponent.User",
"resource": "class path resource
[com/beanvscomponent/ApplicationConfig.class]",
"dependencies": []
}
#Component vs #Bean
I hope that cleared up some things on when to use #Component and when to use #Bean. It can be a little confusing but as you start to write more applications it will become pretty natural.

Spring Boot Autowired failed - null

I have 3 classes which are found in different packages in a spring boot application as follows:
Why does #Autowired work in certain classes only?Anything I am doing wrong?
#Configuration
public class Configurations{
#Autowired
Prop prop; //works fine
#Bean
//other bean definitions
}
#Component
public class Prop{
public void method(){};
}
public class User{
#Autowired
Prop prop; //does not work, null
public void doWork(){
prop.method();
}
}
I have also tried the #PostConstruct, but same result
public class User{
#Autowired
Prop prop; //does not work, null
#PostConstruct
public void doWork(){
prop.method();
}
}
The #Autowired annotation works only if Spring detects that the class itself should be a Spring bean.
In your first example you annotated Configurations with the #Configuration annotation. Your User class on the other hand does not have an annotation indicating that it should be a Spring bean.
There are various annotations (with different meanings) to make your class being picked up by the Spring container, some examples are #Service, #Component, #Controller, #Configuration, ... . However, this only works if your class is in a package that is being scanned by the Spring container. With Spring boot, the easiest way to guarantee that is by putting your User class in a (sub)package of your main class (the class annotated with #SpringBootApplication).
You can also manually create your bean by writing the following method in your Configurations:
#Bean
public User user() {
return new User();
}
In this case you don't have to annotate your User class, nor do you have to make sure that it is in a package that is being scanned.

Resources