Home > Software design >  How to autowire generic types
How to autowire generic types

Time:01-04

I'm new to Spring and I'm trying to autowire a generic DAO. Unfortunately, I'm getting an error. I tried to search info based on it, but most solutions state to use @Qualifier annotation which in my opinion is against what I want to achieve.

So below some code (I'll get rid of that class parameter once I deal with current issue):

DAO

public interface GenericDAO<T> {

    T save(T entity, Class<T> tClass);
    List<T> findAll(Class<T> tClass);
    List<T> findAllByKeyword(String keyword, Class<T> tClass);
    T findById(int id, Class<T> tClass);
    void deleteById(int id, Class<T> tClass);

}

public class GenericDAOImpl<T> implements GenericDAO<T> {

    SessionFactory sessionFactory;


    public GenericDAOImpl(SessionFactory sessionFactory) {
        this.sessionFactory = sessionFactory;
    }

    @Override
    @Transactional
    public T save(T entity, Class<T> tClass) {
        //body
    }

    //other methods
}

@Repository
public class FooDAOImpl extends GenericDAOImpl<Foo> {

    @Autowired
    public FooDAOImpl(SessionFactory sessionFactory) {
        super(sessionFactory);
    }

Service

public interface GenericService<T> {

    T save(T entity, Class<T> tClass);
    List<T> findAll(Class<T> tClass);
    List<T> findAllByKeyword(String keyword, Class<T> tClass);
    T findById(int id, Class<T> tClass);
    void deleteById(int id, Class<T> tClass);

}

public class GenericServiceImpl<T, T_DAO extends GenericDAO<T>> implements GenericService<T> {


    private final T_DAO dao;

    public GenericServiceImpl(T_DAO dao) {
        this.dao = dao;
    }

    @Override
    public T save(T entity, Class<T> tClass) {
        return dao.save(entity, tClass);
    }

    // other methods
}

@Service
public class FooServiceImpl extends GenericServiceImpl<Foo, FooDAOImpl> {

    @Autowired
    public FooServiceImpl(FooDAOImpl fooDAOImpl) {
        super(fooDAOImpl);
    }
}
}

And error thrown below:

javax.servlet.ServletException: Servlet.init() for servlet [dispatcher] threw exception
    org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:542)
    org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:92)
    org.apache.catalina.valves.AbstractAccessLogValve.invoke(AbstractAccessLogValve.java:687)
    org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:357)
    org.apache.coyote.http11.Http11Processor.service(Http11Processor.java:374)
    org.apache.coyote.AbstractProcessorLight.process(AbstractProcessorLight.java:65)
    org.apache.coyote.AbstractProtocol$ConnectionHandler.process(AbstractProtocol.java:893)
    org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.doRun(NioEndpoint.java:1707)
    org.apache.tomcat.util.net.SocketProcessorBase.run(SocketProcessorBase.java:49)
    java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1128)
    java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:628)
    org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61)
    java.base/java.lang.Thread.run(Thread.java:834)
Root Cause

org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'fooServiceImpl' defined in class path resource [*/*/*/service/FooServiceImpl.class]: Unsatisfied dependency expressed through constructor parameter 0; nested exception is org.springframework.beans.factory.BeanNotOfRequiredTypeException: Bean named 'fooDAOImpl' is expected to be of type '*.*.*.repository.FooDAOImpl' but was actually of type 'com.sun.proxy.$Proxy76'
    org.springframework.beans.factory.support.ConstructorResolver.createArgumentArray(ConstructorResolver.java:797)
    org.springframework.beans.factory.support.ConstructorResolver.autowireConstructor(ConstructorResolver.java:227)
    org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.autowireConstructor(AbstractAutowireCapableBeanFactory.java:1356)
    org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBeanInstance(AbstractAutowireCapableBeanFactory.java:1203)
    org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:556)
    org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:516)
    org.springframework.beans.factory.support.AbstractBeanFactory.lambda$doGetBean$0(AbstractBeanFactory.java:324)
    org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:234)
    org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:322)
    org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:202)
    org.springframework.beans.factory.support.DefaultListableBeanFactory.preInstantiateSingletons(DefaultListableBeanFactory.java:897)
    org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:879)
    org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:551)
    org.springframework.web.servlet.FrameworkServlet.configureAndRefreshWebApplicationContext(FrameworkServlet.java:702)
    org.springframework.web.servlet.FrameworkServlet.createWebApplicationContext(FrameworkServlet.java:668)
    org.springframework.web.servlet.FrameworkServlet.createWebApplicationContext(FrameworkServlet.java:716)
    org.springframework.web.servlet.FrameworkServlet.initWebApplicationContext(FrameworkServlet.java:591)
    org.springframework.web.servlet.FrameworkServlet.initServletBean(FrameworkServlet.java:530)
    org.springframework.web.servlet.HttpServletBean.init(HttpServletBean.java:170)
    javax.servlet.GenericServlet.init(GenericServlet.java:158)
    org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:542)
    org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:92)
    org.apache.catalina.valves.AbstractAccessLogValve.invoke(AbstractAccessLogValve.java:687)
    org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:357)
    org.apache.coyote.http11.Http11Processor.service(Http11Processor.java:374)
    org.apache.coyote.AbstractProcessorLight.process(AbstractProcessorLight.java:65)
    org.apache.coyote.AbstractProtocol$ConnectionHandler.process(AbstractProtocol.java:893)
    org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.doRun(NioEndpoint.java:1707)
    org.apache.tomcat.util.net.SocketProcessorBase.run(SocketProcessorBase.java:49)
    java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1128)
    java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:628)
    org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61)
    java.base/java.lang.Thread.run(Thread.java:834)
Root Cause

org.springframework.beans.factory.BeanNotOfRequiredTypeException: Bean named 'fooDAOImpl' is expected to be of type '*.*.*.repository.FooDAOImpl' but was actually of type 'com.sun.proxy.$Proxy76'
    org.springframework.beans.factory.support.DefaultListableBeanFactory.checkBeanNotOfRequiredType(DefaultListableBeanFactory.java:1736)
    org.springframework.beans.factory.support.DefaultListableBeanFactory.raiseNoMatchingBeanFound(DefaultListableBeanFactory.java:1713)
    org.springframework.beans.factory.support.DefaultListableBeanFactory.doResolveDependency(DefaultListableBeanFactory.java:1273)
    org.springframework.beans.factory.support.DefaultListableBeanFactory.resolveDependency(DefaultListableBeanFactory.java:1227)
    org.springframework.beans.factory.support.ConstructorResolver.resolveAutowiredArgument(ConstructorResolver.java:884)
    org.springframework.beans.factory.support.ConstructorResolver.createArgumentArray(ConstructorResolver.java:788)
    org.springframework.beans.factory.support.ConstructorResolver.autowireConstructor(ConstructorResolver.java:227)
    org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.autowireConstructor(AbstractAutowireCapableBeanFactory.java:1356)
    org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBeanInstance(AbstractAutowireCapableBeanFactory.java:1203)
    org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:556)
    org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:516)
    org.springframework.beans.factory.support.AbstractBeanFactory.lambda$doGetBean$0(AbstractBeanFactory.java:324)
    org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:234)
    org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:322)
    org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:202)
    org.springframework.beans.factory.support.DefaultListableBeanFactory.preInstantiateSingletons(DefaultListableBeanFactory.java:897)
    org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:879)
    org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:551)
    org.springframework.web.servlet.FrameworkServlet.configureAndRefreshWebApplicationContext(FrameworkServlet.java:702)
    org.springframework.web.servlet.FrameworkServlet.createWebApplicationContext(FrameworkServlet.java:668)
    org.springframework.web.servlet.FrameworkServlet.createWebApplicationContext(FrameworkServlet.java:716)
    org.springframework.web.servlet.FrameworkServlet.initWebApplicationContext(FrameworkServlet.java:591)
    org.springframework.web.servlet.FrameworkServlet.initServletBean(FrameworkServlet.java:530)
    org.springframework.web.servlet.HttpServletBean.init(HttpServletBean.java:170)
    javax.servlet.GenericServlet.init(GenericServlet.java:158)
    org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:542)
    org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:92)
    org.apache.catalina.valves.AbstractAccessLogValve.invoke(AbstractAccessLogValve.java:687)
    org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:357)
    org.apache.coyote.http11.Http11Processor.service(Http11Processor.java:374)
    org.apache.coyote.AbstractProcessorLight.process(AbstractProcessorLight.java:65)
    org.apache.coyote.AbstractProtocol$ConnectionHandler.process(AbstractProtocol.java:893)
    org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.doRun(NioEndpoint.java:1707)
    org.apache.tomcat.util.net.SocketProcessorBase.run(SocketProcessorBase.java:49)
    java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1128)
    java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:628)
    org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61)
    java.base/java.lang.Thread.run(Thread.java:834)

CodePudding user response:

The error is that spring has failed to create the bean customerServiceImpl because customerServiceImpl expect a dependency of type CustomerDAOImpl and spring has injected a dependency of com.sun.proxy.$Proxy76

Bean named 'customerDAOImpl' is expected to be of type 
'com.smartdigit.zalewski.repository.CustomerDAOImpl' but was actually of type 
'com.sun.proxy.$Proxy76'  

You have to change your FooServiceImpl class in order to get a dependency of type FooDAOInterface and not an implementation of it.

Someting like:

public class FooServiceImpl extends GenericServiceImpl<> {
    @Autowired
    public FooServiceImpl(FooDAOInterface fooDAO) {
    super(fooDAOImpl);
   }
}

You have to pass an interface type in the FooServiceImpl constructor in order to spring autowired it when the spring context has been initilized.

CodePudding user response:

Hi Error is coming due to wrong dependency got passed in constructor.

Please use like this.

@Service
public class FooServiceImpl extends GenericServiceImpl<Foo, FooDAO> {

private final FooDAO fooDAO;
    @Autowired
    public FooServiceImpl(FooDAO fooDAO) {
        this.fooDAO = fooDAO
    }
}

If a bean has one constructor, you can omit the @Autowired

@Service
public class FooServiceImpl extends GenericServiceImpl<Foo, FooDAO> {

private final FooDAO fooDAO;
    
    public FooServiceImpl(FooDAO fooDAO) {
        this.fooDAO = fooDAO
    }
}

Note: FooDAO should be your interface

  •  Tags:  
  • Related