Spring. Dynamic dependency injection - spring

I have the following problem.
I have a generic class A
public class A<T, DAO extends JpaRepository<?, ?>>
{
#Autowired
protected DAO daoObject;
......
and there I am trying inject a genreic DAO-object of the JpaRepository-type.
If I have only one implemetation of injected object(of JpaRepository), then there is no problem, but if I have more then one, then spring doesn't know which object it is to inject and throws an exception.
The question is: How can I dynamish based on generic information, inject the correct object?
Thank you.
public interface IRegisteredUserDAO extends JpaRepository<RegisteredUser, String> {
}
public interface IMailLogDao extends JpaRepository<MailLog, Long> {
findByTo(String to);
}
and i used it so
public class RegisteredUserVM extends YBTableViewModel<RegisteredUser, IRegisteredUserDAO>
{
UPDATE:
public class MailLogVM extends YBTableViewModel<MailLog, IMailLogDao>
{
}

You should be able to do this using the latest Spring 4 RC1. Versions before that do not support generic injection at all. See this ticket and related commits for details.

You can use Spring's #Qualifier annotation to inject the correct bean:
#Autowired
#Qualifier("IRegisteredUserDAOImpl")
protected DAO daoObject;
Here the bean with qualifier value "IRegisteredUserDAOImpl" is wired.

Related

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.

Spring Abstract class #Autowire null while using that field in subclass constructor

Following is the code:
public abstract class A {
#Autowired
public Provider provider;
}
#Component
public class B extends A {
B() {
provider.get();
}
}
Spring is throwing NullPointerException, while instantiating Bean of Class B.
I know #Autowired defined in Abstract class are injected, but don't know in which order they are injected.
Earlier my understanding was, While instance creation of B, Spring will autowire fields of all subclasses and then will create instance of B.
But here it seems, it overlooks the subclass concept while instance creation, and just scans B to identify #Autowire field.
Use #PostConstruct. Java Object Instantiation and Spring Dependency Injection are two different flows.
#Component
public class B extends A {
#PostConstruct
void init() {
provider.get();
}
}
If autowiring your constructors is an option the following can be helpful.
public abstract class A {
protected final Provider provider;
#Autowired
public A(Provider provider) {
this.provider = provider;
}
}
#Component
public class B extends A {
#Autowired
B(Provider provider) {
super(provider);
provider.get();
}
}
Note since the latest Spring Versions you do not need to annotate the constructor with #Autowire. If you do things right the spring framework auto-detects the constructor.

Spring can not register spring hateoas resource assembler

I am using spring hateoas in spring and got the problem is spring could not instance hateoas resource assembler , here is my snippet code:
UserHateoasResourceAssembler.java:
#Service
public class UserHateoasResourceAssembler extends ResourceAssemblerSupport<UserDTO, UserHateoasResource> {
public UserHateoasResourceAssembler() {
super(UserController.class, UserHateoasResource.class);
}
#Override
public UserHateoasResource toResource(UserDTO entity) {
UserHateoasResource resource = createResourceWithId(entity.getId(), entity);
return resource;
}
#Override
protected UserHateoasResource instantiateResource(UserDTO entity) {
return new UserHateoasResource(entity);
}
}
UserController.java:
#RestController
#RequestMapping("/api/")
public class UserController {
#Inject
private UserHateoasResourceAssembler userAssembler ;
....
}
The exception was thrown is "No qualifying bean of type [UserHateoasResourceAssembler] found for dependency. I know this root cause is can not create instance of assembler.
I tried to use #Service or #Component but both does not work. I also tried to use #Autowire instead, but did not work too. I have to fix that by adding #Scope( proxyMode = ScopedProxyMode.TARGET_CLASS). But I wonder if there is any another solution to resolve it instead of using #Scope ?
Thanks.
I found the elegant solution. Due to my application using generated code and it used #EnableAspectJAutoProxy, this annotation default set auto-proxy = false and using JDK proxy, so almost the instance of class that implementing an interface was not allowed. We have to #inject the interface instead. So to inject the implementation class, have 2 options here:
Set #EnableAspectJAutoProxy(proxyTargetClass = true )
Remove this annotation if we does not really need that.

How to do inheritance in Dao layer?

I am working with SpringMVC+Hibernate, I want to apply Inheritance in DAO layer, I am doing like below:
BaseDao.java
public interface BaseDao
{
public Serializable save(Object object) throws DataAccessException,
HibernateException;
public void merge(Object object) throws DataAccessException,
HibernateException;
public void flush() throws DataAccessException,HibernateException;
}
EmpDao.java
public interface EmpDao extends BaseDao{
}
BaseDaoImpl.java
#Repository
public class BaseDaoImpl implements BaseDao{
// Implementation for baseDao methods
}
EmpDaoImpl .java
#Repository
public class EmpDaoImpl extends BaseDaoImpl implements EmpDao{
// Implementation
}
But I am getting below error:
org.springframework.beans.factory.NoUniqueBeanDefinitionException: No qualifying bean of type
[BaseDao] is defined: expected single matching bean but found 2
What am I missing here?
If you really want to have both BaseDaoImpl and EmpDaoImpl as two beans in your Spring container, you need to tell Spring which one to use wherever you have an #Autowired field of type BaseDao using #Qualifier annotation.
Related: Understanding Spring #Autowired usage
It seems like you're trying to inject BaseDao and Spring is complaining there are two candidates.
I think this is actually a design problem. You wanted to use BaseDaoImpl both as a concrete bean that you use directly and also as a base class for other DAOs. This is bad because the sub-classes does not actually extend but simply uses their parent class. The better pattern would be to get rid of the extends and simply inject the BaseDaoImpl into the other DAOs.
Also, the interfaces looks superfluous. If you're working around the proxy problem, just use proxyTargetClass.
You can use generic types like this
BaseDao.java
public interface BaseDao<EntityType extends Object>
{
public Serializable save(EntityType entity) throws DataAccessException,
HibernateException;
public void merge(EntityType entity) throws DataAccessException,
HibernateException;
public void flush() throws DataAccessException,HibernateException;
}
BaseDaoImpl.java
#Repository
public abstract class BaseDaoImpl<EntityType extends Object> implements BaseDao<EntityType>{
// Implementation for baseDao methods
}
EmpDao.java
public interface EmpDao extends BaseDao<Employee>{
}
EmpDaoImpl .java
#Repository
public class EmpDaoImpl extends BaseDaoImpl<Employee> implements EmpDao{
// Implementation
}
You need to add the #NoRepositoryBean on the BaseDao interface so spring would not create a bean for it, as well as for EmpDao I assume

Resources