Spring MVC autowiring bean throws nestedexception - java

I have big problems with autowiring in Spring MVC 4 and I already spent many hours on it. Found many solutions but nothing helps.
I have Controller:
#Controller
public class PrintedBookController {
#Autowired
PrintedBookService pbookService; // interface
#RequestMapping(value = "/pbook", method = RequestMethod.GET)
public ModelAndView pbook() {
return new ModelAndView("pbook", "command", new PrintedBookDTO());
}
...
}
Also have:
PrintedBookService // this is interface
PrintedBookServiceImpl // this is implementation of PrintedBookService
in printedbookserviceimpl is:
#Service
#Transactional
public class PrintedBookServiceImpl implements PrintedBookService {
#Autowired
private PrintedBookDAO pbookDao;
#Autowired
private BookDAO bookDao;
#Autowired
private LoanDAO loanDao;
public void setPrintedBookDao(PrintedBookDAO pbookDao) {
this.pbookDao = pbookDao;
}
....
}
the daos in PrintedBookServiceImpl are interfaces
The dao implementations look like this:
public class PrintedBookDAOImpl implements PrintedBookDAO, GenericDAO<PrintedBook> {
#PersistenceContext(unitName = "pbook-unit", type = PersistenceContextType.EXTENDED)
private EntityManager em;
....
}
I have three modules library-lib(daos) library-service(services) library-web(spring mvc).
Library mvc has controller xml:
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="
http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-3.0.xsd">
<context:component-scan base-package="cz.fi.muni.pa165.library.web" />
<context:component-scan base-package="cz.fi.muni.pa165.service" />
<context:component-scan base-package="cz.fi.muni.pa165.dao" />
<bean
class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<property name="prefix">
<value>/WEB-INF/pages/</value>
</property>
<property name="suffix">
<value>.jsp</value>
</property>
</bean>
</beans>
and web.xml
<web-app id="WebApp_ID" version="2.4"
xmlns="http://java.sun.com/xml/ns/j2ee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee
http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd">
<display-name>Spring MVC Application</display-name>
<servlet>
<servlet-name>mvc-dispatcher</servlet-name>
<servlet-class>
org.springframework.web.servlet.DispatcherServlet
</servlet-class>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>mvc-dispatcher</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping>
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>/WEB-INF/mvc-dispatcher-servlet.xml</param-value>
</context-param>
<listener>
<listener-class>
org.springframework.web.context.ContextLoaderListener
</listener-class>
</listener>
</web-app>
When i run the web(on tomcat8) it shows me exception:
Caused by: org.springframework.beans.factory.BeanCreationException: Could not autowire field: cz.fi.muni.pa165.service.PrintedBookServiceImpl cz.fi.muni.pa165.library.web.PrintedBookController.pbookService; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'printedBookServiceImpl': Injection of autowired dependencies failed; nested exception is org.springframework.beans.factory.BeanCreationException: Could not autowire field: private cz.fi.muni.pa165.dao.PrintedBookDAO cz.fi.muni.pa165.service.PrintedBookServiceImpl.pbookDao; nested exception is org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type [cz.fi.muni.pa165.dao.PrintedBookDAO] found for dependency: expected at least 1 bean which qualifies as autowire candidate for this dependency. Dependency annotations: {#org.springframework.beans.factory.annotation.Autowired(required=true)}
and
Caused by: org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'printedBookServiceImpl': Injection of autowired dependencies failed; nested exception is org.springframework.beans.factory.BeanCreationException: Could not autowire field: private cz.fi.muni.pa165.dao.PrintedBookDAO cz.fi.muni.pa165.service.PrintedBookServiceImpl.pbookDao; nested exception is org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type [cz.fi.muni.pa165.dao.PrintedBookDAO] found for dependency: expected at least 1 bean which qualifies as autowire candidate for this dependency. Dependency annotations: {#org.springframework.beans.factory.annotation.Autowired(required=true)}
also getting this:
Caused by: org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'pbookDao': Injection of persistence dependencies failed; nested exception is org.springframework.beans.factory.NoSuchBeanDefinitionException: No bean named 'pbook-unit' is defined
The project is on github https://github.com/Cospel/ProjLibrary
Any ideas how to solve this?

Try adding #Component annotation on PrintedBookDAOImpl, Spring can't find any bean of type PrintedBookDAO in the context.
See this part of the trace :
No qualifying bean of type [cz.fi.muni.pa165.dao.PrintedBookDAO] found for dependency: expected at least 1 bean which qualifies as autowire candidate for this dependency.

As Jean says, you need to add #Component to any class you wish to autowire. For services, Spring provides some optimizations by using the #Service tag rather than the #Component tag. Similarly, for the DAO layer, Spring provides an optimized #Repository annotation. Use these annotations to enable these classes for component scanning. Then, you shouldn't even need the
setPrintedBookDAO()
method at all, as Spring will take care of the autowiring for you.

Related

Spring and Hibernate Restful webservice configuration

Please any help on this
I would like to ask your help on this, I configured a project in Netbeans to build a Restful Webservice with Spring MVC and Hibernate to connect to the database.
The problem is that I don't know how to configure the controller to execute and return the JSON.
I already developed my Data Access Layer, my service and my controller, but I don't know how to configure the project to execute: http:localhost:8080/project/user for example.
dispatcher-servlet.xml
<?xml version='1.0' encoding='UTF-8' ?>
<!-- was: <?xml version="1.0" encoding="UTF-8"?> -->
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:p="http://www.springframework.org/schema/p"
xmlns:aop="http://www.springframework.org/schema/aop"
xmlns:tx="http://www.springframework.org/schema/tx"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.0.xsd
http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-4.0.xsd
http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-4.0.xsd
http://www.springframework.org/schema/cache http://www.springframework.org/schema/cache/spring-cache-4.0.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.0.xsd
http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc-4.0.xsd" xmlns:cache="http://www.springframework.org/schema/cache" xmlns:context="http://www.springframework.org/schema/context" xmlns:mvc="http://www.springframework.org/schema/mvc">
<bean class="org.springframework.web.servlet.mvc.support.ControllerClassNameHandlerMapping"/>
<!--
Most controllers will use the ControllerClassNameHandlerMapping above, but
for the index controller we are using ParameterizableViewController, so we must
define an explicit mapping for it.
-->
<bean id="urlMapping" class="org.springframework.web.servlet.handler.SimpleUrlHandlerMapping">
<property name="mappings">
<props>
<prop key="index.htm">indexController</prop>
</props>
</property>
</bean>
<bean id="viewResolver"
class="org.springframework.web.servlet.view.InternalResourceViewResolver"
p:prefix="/WEB-INF/jsp/"
p:suffix=".jsp" />
<!--
The index controller.
-->
<bean name="indexController"
class="org.springframework.web.servlet.mvc.ParameterizableViewController"
p:viewName="index" />
<mvc:annotation-driven/>
<context:component-scan base-package="ServiceLayer.Controller"/>
</beans>
Web.xml
<?xml version="1.0" encoding="UTF-8"?>
<web-app version="3.1" xmlns="http://xmlns.jcp.org/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd">
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>/WEB-INF/applicationContext.xml</param-value>
</context-param>
<context-param>
<param-name>javax.faces.PROJECT_STAGE</param-name>
<param-value>Development</param-value>
</context-param>
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
<servlet>
<servlet-name>dispatcher</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<load-on-startup>2</load-on-startup>
</servlet>
<servlet>
<servlet-name>Faces Servlet</servlet-name>
<servlet-class>javax.faces.webapp.FacesServlet</servlet-class>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>dispatcher</servlet-name>
<url-pattern>*.htm</url-pattern>
</servlet-mapping>
<servlet-mapping>
<servlet-name>Faces Servlet</servlet-name>
<url-pattern>/faces/*</url-pattern>
</servlet-mapping>
<session-config>
<session-timeout>
30
</session-timeout>
</session-config>
<welcome-file-list>
<welcome-file>faces/index.xhtml</welcome-file>
<welcome-file>redirect.jsp</welcome-file>
</welcome-file-list>
</web-app>
Error:
org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type [DataAccessLayer.DataAccessObject.UserDAO] found for dependency: expected at least 1 bean which qualifies as autowire candidate for this dependency. Dependency annotations: {#org.springframework.beans.factory.annotation.Autowired(required=true)}org.springframework.beans.factory.support.DefaultListableBeanFactory.raiseNoSuchBeanDefinitionException(DefaultListableBeanFactory.java:1100)
org.springframework.beans.factory.BeanCreationException: Could not autowire field: private DataAccessLayer.DataAccessObject.UserDAO ServiceLayer.Service.UserService.userDao; nested exception is org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type [DataAccessLayer.DataAccessObject.UserDAO] found for dependency: expected at least 1 bean which qualifies as autowire candidate for this dependency. Dependency annotations: {#org.springframework.beans.factory.annotation.Autowired(required=true)}
org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'userService': Injection of autowired dependencies failed; nested exception is org.springframework.beans.factory.BeanCreationException: Could not autowire field: private DataAccessLayer.DataAccessObject.UserDAO ServiceLayer.Service.UserService.userDao; nested exception is org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type [DataAccessLayer.DataAccessObject.UserDAO] found for dependency: expected at least 1 bean which qualifies as autowire candidate for this dependency. Dependency annotations: {#org.springframework.beans.factory.annotation.Autowired(required=true)}
org.springframework.beans.factory.BeanCreationException: Could not autowire field: private ServiceLayer.Service.UserService ServiceLayer.Controller.UserController.userService; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'userService': Injection of autowired dependencies failed; nested exception is org.springframework.beans.factory.BeanCreationException: Could not autowire field: private DataAccessLayer.DataAccessObject.UserDAO ServiceLayer.Service.UserService.userDao; nested exception is org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type [DataAccessLayer.DataAccessObject.UserDAO] found for dependency: expected at least 1 bean which qualifies as autowire candidate for this dependency. Dependency annotations: {#org.springframework.beans.factory.annotation.Autowired(required=true)}
org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'userController': Injection of autowired dependencies failed; nested exception is org.springframework.beans.factory.BeanCreationException: Could not autowire field: private ServiceLayer.Service.UserService ServiceLayer.Controller.UserController.userService; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'userService': Injection of autowired dependencies failed; nested exception is org.springframework.beans.factory.BeanCreationException: Could not autowire field: private DataAccessLayer.DataAccessObject.UserDAO ServiceLayer.Service.UserService.userDao; nested exception is org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type [DataAccessLayer.DataAccessObject.UserDAO] found for dependency: expected at least 1 bean which qualifies as autowire candidate for this dependency. Dependency annotations: {#org.springframework.beans.factory.annotation.Autowired(required=true)}
org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'org.springframework.web.servlet.mvc.support.ControllerClassNameHandlerMapping#0' defined in ServletContext resource [/WEB-INF/dispatcher-servlet.xml]: Initialization of bean failed; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'userController': Injection of autowired dependencies failed; nested exception is org.springframework.beans.factory.BeanCreationException: Could not autowire field: private ServiceLayer.Service.UserService ServiceLayer.Controller.UserController.userService; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'userService': Injection of autowired dependencies failed; nested exception is org.springframework.beans.factory.BeanCreationException: Could not autowire field: private DataAccessLayer.DataAccessObject.UserDAO ServiceLayer.Service.UserService.userDao; nested exception is org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type [DataAccessLayer.DataAccessObject.UserDAO] found for dependency: expected at least 1 bean which qualifies as autowire candidate for this dependency. Dependency annotations: {#org.springframework.beans.factory.annotation.Autowired(required=true)}
I will appreciate a lot your help.
This is not straight answer to your question. But it may help in longer run.
Why don't you make your application as spring boot application. It will make your application simpler. You don't need to configure web.xml, deploy your war and so on. May be you can get started with this
Complete documentation can be found here
You could always start the application in debug mode from the IDE and see the logs for which URL Mappings are being registered on to your controller handlers. On a different note :
Then, there is also this in the stacktrace : org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type [ServiceLayer.Service.UserService] found for dependency: expected at least 1 bean which qualifies which points to a possible configuration requirement for scanning components. So please adjust your <context:component-scan> tag to include the packages containing your beans.
As an example : <context:component-scan base-package="ServiceLayer.Service, ServiceLayer.Controller, ServiceLayer.Dao" />
Also, your web.xml maps *.htm to your dispatcher, so if you want
your dispatcher to receive all the requests - you might want to
change that to / or /* based on how you want it to operate.
Otherwise, only requests like http:localhost:8080/project/user.htm
will be processed, and not the type of requests that you intend to
process which is mentioned as this http:localhost:8080/project/user
in the question.
HTH.

NoSuchBeanDefinitionException: No qualifying bean of type JobLauncher to autowire

I'm following this spring batch tutorial. Now, I want to run the job on hitting an API, so I made it a web project & implemented following controller but beans aren't getting autowired.
examples.spring.batch.web.controller.JobLauncherController
#Controller
#RequestMapping("/run")
public class JobLauncherController {
#Autowired
private JobLauncher jobLauncher;
#Autowired
private Job job;
#RequestMapping(method = RequestMethod.GET, value = "/runJob")
#ResponseBody
public void launchImportDataJob() throws Exception {
jobLauncher.run(importDataJob, new JobParameters());
}
}
/WEB-INF/spring/batch/applicationContext.xml
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:tx="http://www.springframework.org/schema/tx" xmlns:aop="http://www.springframework.org/schema/aop"
xmlns:task="http://www.springframework.org/schema/task" xmlns:cache="http://www.springframework.org/schema/cache"
xmlns:p="http://www.springframework.org/schema/p" xmlns:mvc="http://www.springframework.org/schema/mvc"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:security="http://www.springframework.org/schema/security"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.2.xsd
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.2.xsd
http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-4.2.xsd
http://www.springframework.org/schema/task http://www.springframework.org/schema/task/spring-task-4.2.xsd
http://www.springframework.org/schema/cache http://www.springframework.org/schema/cache/spring-cache-4.2.xsd
http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc.xsd">
<!-- enable auto-scan for all #Repository, #Service, #Controller java files
for beans -->
<context:component-scan base-package="examples.spring">
</context:component-scan>
<!-- Import extra configuration -->
<import resource="/WEB-INF/spring/batch/database.xml"/>
<import resource="/WEB-INF/spring/batch/spring-batch.xml"/>
<import resource="/WEB-INF/spring/batch/job.xml"/>
</beans>
/WEB-INF/spring/batch/database.xml
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="
http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.2.xsd">
<!-- stored job-metadata in database -->
<bean id="jobRepository"
class="org.springframework.batch.core.repository.support.JobRepositoryFactoryBean">
<property name="dataSource" ref="dataSource" />
<property name="transactionManager" ref="transactionManager" />
<property name="databaseType" value="mysql" />
</bean>
<bean id="transactionManager"
class="org.springframework.batch.support.transaction.ResourcelessTransactionManager" />
<bean id="jobLauncher"
class="org.springframework.batch.core.launch.support.SimpleJobLauncher">
<property name="jobRepository" ref="jobRepository" />
</bean>
</beans>
Stack Trace
org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'jobLauncherController': Injection of autowired dependencies failed; nested exception is org.springframework.beans.factory.BeanCreationException: Could not autowire field: private org.springframework.batch.core.launch.JobLauncher examples.spring.batch.web.controller.JobLauncherController.jobLauncher; nested exception is org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type [org.springframework.batch.core.launch.JobLauncher] found for dependency: expected at least 1 bean which qualifies as autowire candidate for this dependency. Dependency annotations: {#org.springframework.beans.factory.annotation.Autowired(required=true), #org.springframework.beans.factory.annotation.Qualifier(value=jobLauncher)}
at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor.postProcessPropertyValues(AutowiredAnnotationBeanPostProcessor.java:334)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.populateBean(AbstractAutowireCapableBeanFactory.java:1214)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:543)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:482)
at org.springframework.beans.factory.support.AbstractBeanFactory$1.getObject(AbstractBeanFactory.java:305)
at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:230)
at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:301)
at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:196)
at org.springframework.beans.factory.support.DefaultListableBeanFactory.preInstantiateSingletons(DefaultListableBeanFactory.java:772)
at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:835)
at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:537)
at org.springframework.web.servlet.FrameworkServlet.configureAndRefreshWebApplicationContext(FrameworkServlet.java:667)
at org.springframework.web.servlet.FrameworkServlet.createWebApplicationContext(FrameworkServlet.java:633)
at org.springframework.web.servlet.FrameworkServlet.createWebApplicationContext(FrameworkServlet.java:681)
at org.springframework.web.servlet.FrameworkServlet.initWebApplicationContext(FrameworkServlet.java:552)
at org.springframework.web.servlet.FrameworkServlet.initServletBean(FrameworkServlet.java:493)
at org.springframework.web.servlet.HttpServletBean.init(HttpServletBean.java:136)
at javax.servlet.GenericServlet.init(GenericServlet.java:158)
at org.apache.catalina.core.StandardWrapper.initServlet(StandardWrapper.java:1231)
at org.apache.catalina.core.StandardWrapper.loadServlet(StandardWrapper.java:1144)
at org.apache.catalina.core.StandardWrapper.load(StandardWrapper.java:1031)
at org.apache.catalina.core.StandardContext.loadOnStartup(StandardContext.java:4914)
at org.apache.catalina.core.StandardContext.startInternal(StandardContext.java:5201)
at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:150)
at org.apache.catalina.core.ContainerBase$StartChild.call(ContainerBase.java:1409)
at org.apache.catalina.core.ContainerBase$StartChild.call(ContainerBase.java:1399)
at java.util.concurrent.FutureTask.run(FutureTask.java:266)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)
at java.lang.Thread.run(Thread.java:745)
Caused by: org.springframework.beans.factory.BeanCreationException: Could not autowire field: private org.springframework.batch.core.launch.JobLauncher examples.spring.batch.web.controller.JobLauncherController.jobLauncher; nested exception is org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type [org.springframework.batch.core.launch.JobLauncher] found for dependency: expected at least 1 bean which qualifies as autowire candidate for this dependency. Dependency annotations: {#org.springframework.beans.factory.annotation.Autowired(required=true), #org.springframework.beans.factory.annotation.Qualifier(value=jobLauncher)}
at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor$AutowiredFieldElement.inject(AutowiredAnnotationBeanPostProcessor.java:571)
at org.springframework.beans.factory.annotation.InjectionMetadata.inject(InjectionMetadata.java:88)
at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor.postProcessPropertyValues(AutowiredAnnotationBeanPostProcessor.java:331)
... 29 more
Caused by: org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type [org.springframework.batch.core.launch.JobLauncher] found for dependency: expected at least 1 bean which qualifies as autowire candidate for this dependency. Dependency annotations: {#org.springframework.beans.factory.annotation.Autowired(required=true), #org.springframework.beans.factory.annotation.Qualifier(value=jobLauncher)}
at org.springframework.beans.factory.support.DefaultListableBeanFactory.raiseNoSuchBeanDefinitionException(DefaultListableBeanFactory.java:1373)
at org.springframework.beans.factory.support.DefaultListableBeanFactory.doResolveDependency(DefaultListableBeanFactory.java:1119)
at org.springframework.beans.factory.support.DefaultListableBeanFactory.resolveDependency(DefaultListableBeanFactory.java:1014)
at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor$AutowiredFieldElement.inject(AutowiredAnnotationBeanPostProcessor.java:543)
... 31 more
web.xml
<web-app>
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>/WEB-INF/spring/applicationContext.xml</param-value>
</context-param>
<servlet>
<servlet-name>spring</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>/WEB-INF/spring/spring-servlet.xml</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>spring</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping>
</web-app>
Use Spring listener on web.xml that loads applicationContext.xml
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
Using the following in my Application class worked without having to mess with web.xml (I don't even have one in my project):
#EnableAutoConfiguration
#Configuration
#ImportResource({"classpath*:applicationContext.xml"})
See also Spring-boot automatically import applicationContext.xml?
Or use a more concise version
#SpringBootApplication
#ImportResource("applicationContext.xml")
Loading applicationcontext.xml when using SpringApplication

Spring web app - autowire - can not find bean to inject

I have a spring controller with an autowired object that Spring says it can't find, despite my seeing - in the log file - the bean/object for it being created in the root application context. It occurs during the deployment of the application (in Tomcat).
I tried adding #Qualifier to the #Autowired field but it didn't resolve the problem.
Controller:
package com.maha.testspring.endpoints.webrest.controllers;
import com.maha.testspring.services.TestSpringService;
#Controller
#RequestMapping("/testspring")
public class TestSpringController
{
#Autowired
#Qualifier("testSpringService")
private TestSpringService testSpringService;
...
}
war's testspring-endpoints-webrest-1.0-SNAPSHOT/WEB-INF/web.xml
<?xml version="1.0" encoding="UTF-8"?>
<web-app version="2.5" xmlns="http://java.sun.com/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd">
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>/WEB-INF/spring/root-context.xml</param-value>
</context-param>
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
<servlet>
<servlet-name>appServlet</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>/WEB-INF/spring/servlet-context.xml</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>appServlet</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping>
</web-app>
war's testspring-endpoints-webrest-1.0-SNAPSHOT/WEB-INF/spring/servlet-context.xml:
<?xml version="1.0" encoding="UTF-8"?>
<beans:beans
...
<mvc:annotation-driven />
<context:annotation-config />
<context:spring-configured />
<context:component-scan base-package="com.maha.testspring.endpoints.webrest.controllers" />
</beans:beans>
war's testspring-endpoints-webrest-1.0-SNAPSHOT/WEB-INF/spring/root-context.xml:
<?xml version="1.0" encoding="UTF-8"?>
<beans ...
<bean class="org.springframework.context.support.ClassPathXmlApplicationContext">
<constructor-arg>
<list>
<value>/applicationContext.testspring.services.xml</value>
</list>
</constructor-arg>
</bean>
</beans>
Service implementation class: (in jar, testspring-services-impl-1.0-SNAPSHOT.jar - in the war's testspring-endpoints-webrest-1.0-SNAPSHOT\WEB-INF\lib folder)
package com.maha.testspring.services;
import org.springframework.stereotype.Service;
#Service("testSpringService")
public class TestSpringServiceImpl implements TestSpringService {
public void testIt() { System.out.println("..."); }
}
Service interface: (in jar, testspring-services-interfaces-1.0-SNAPSHOT.jar - in the war's testspring-endpoints-webrest-1.0-SNAPSHOT\WEB-INF\lib folder)
package com.maha.testspring.services;
public interface TestSpringService
{
public void testIt();
}
applicationContext.testspring.services.xml (in jar, testspring-services-impl-1.0-SNAPSHOT.jar - in the war's testspring-endpoints-webrest-1.0-SNAPSHOT\WEB-INF\lib folder)
<?xml version="1.0" encoding="UTF-8"?>
<beans ...>
<context:spring-configured/>
<context:annotation-config />
<context:component-scan base-package="com.maha.testspring.services"/>
</beans>
Logging - shows TestSpringServiceImpl was processed for #Service (as a candidate component when injecting dependency later on)
annotation.ClassPathBeanDefinitionScanner - Identified candidate component class: URL [jar:file:/C:/osd/Tomcat%208.0/webapps/testspringwebrest/WEB-INF/lib/testspring-services-impl-1.0-SNAPSHOT.jar!/com/maha/testspring/services/TestSpringServiceImpl.class]
support.ClassPathXmlApplicationContext - Bean factory for org.springframework.context.support.ClassPathXmlApplicationContext#41e89deb: org.springframework.beans.factory.support.DefaultListableBeanFactory#7487b2bc
Logging shows creation of bean instance for this class:
support.DefaultListableBeanFactory - Creating shared instance of singleton bean 'testSpringService'
support.DefaultListableBeanFactory - Creating instance of bean 'testSpringService'
support.DefaultListableBeanFactory - Eagerly caching bean 'testSpringService' to allow for resolving potential circular references
support.DefaultListableBeanFactory - Finished creating instance of bean 'testSpringService'
Error when trying to create the controller - can't find the bean to inject:
support.DefaultListableBeanFactory - Creating shared instance of singleton bean 'testSpringController'
support.DefaultListableBeanFactory - Creating instance of bean 'testSpringController'
annotation.InjectionMetadata - Registered injected element on
class [com.maha.testspring.endpoints.webrest.controllers.TestSpringController]: AutowiredFieldElement for
private com.maha.testspring.services.TestSpringService com.maha.testspring.endpoints.webrest.controllers.TestSpringController.testSpringService
annotation.InjectionMetadata - Processing injected element of bean 'testSpringController':
AutowiredFieldElement for private
com.maha.testspring.services.TestSpringService
com.maha.testspring.endpoints.webrest.controllers.TestSpringController.testSpringService
support.XmlWebApplicationContext - Exception encountered during context initialization - cancelling refresh attempt
org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'testSpringController':
Injection of autowired dependencies failed; nested exception is org.springframework.beans.factory.BeanCreationException:
Could not autowire field: private com.maha.testspring.services.TestSpringService com.maha.testspring.endpoints.webrest.controllers.TestSpringController.testSpringService;
nested exception is
org.springframework.beans.factory.NoSuchBeanDefinitionException:
No qualifying bean of type
[com.maha.testspring.services.TestSpringService] found for dependency:
expected at least 1 bean which qualifies as autowire candidate for this dependency.
I had a similar problem . We solved it by keeping the CASE same . In your example you used #Qualifier("testSpringService")
and your yout service public class TestSpringServiceImpl implements TestSpringService
TRY changing it to public class TestSpringServiceImpl implements testSpringService with a SMALL t in testSpringService.
If that dont solve your problem then try annotating the parent class (Remember that annotations are not inherited from parent class to the child and in your case you have annotated the child and not its parent ) like :
package com.maha.testspring.services;
#Service("testSpringService")
public interface TestSpringService
{
public void testIt();
}

Intilaizing a bean with constructor args - WebApplicationContext vs ClassPathApplicationContext

A bean defiend on the applicationContext.xml is getting instantiated using both ClassPathXmlApllicationContext and WebApplicationContext. While using the former the bean is returned as expected but while using the latter, WebApplicationContext, I'm getting a null value.
FYI: Not using the Spring to its full extent. Just used to define a bean and to intialize it. Its a web service application based on jboss.
I defined the WebApplicationContext in my web.xml as below
<?xml version="1.0" encoding="UTF-8"?>
<web-app version="2.5"
xmlns="http://java.sun.com/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd">
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath:applicationContext.xml</param-value>
</context-param>
<listener>
<listener-class>
org.springframework.web.context.ContextLoaderListener
</listener-class>
</listener>
<servlet>
<display-name>Service</display-name>
<servlet-name>MService</servlet-name>
<servlet-class>
com.xyz.atop.ws.memb.MServiceImpl
</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>MService</servlet-name>
<url-pattern>/Service</url-pattern>
</servlet-mapping>
</web-app>
The entry from the applicationContext.xml
<beans ...>
<context:annotation-config />
<bean class="org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor"/>
<bean id="helper" name="helper" class="com.xyz.svc.wrapper.Helper">
<constructor-arg type="java.lang.String" value="ABC"/>
</bean>
</beans>
Used the ClassPathApplicationContext (returning a bean instance as expected) in my code as below
private static Helper helper;
public MServiceImpl() {
}
static {
ApplicationContext appContext = new ClassPathXmlApplicationContext("applicationContext.xml");
helper = (Helper) appContext.getBean("helper");
}
......
......
While using the WebApplicationContext, I tried #Autowired annotation and even tried setter injection. Both the ways I'm getting a null value returned.
The "Helper" class I'm trying to initialize is coming from a jar file which in turn makes calls to a cxf-spring application.
Please look at the above scenario and advise to get rid of the null pointer while using the WebApplicationCOntext.
Ok, spring beans are injected into other spring beans. MService needs to be a bean too. Autowire will then inject the helper into the MService bean. You can't use a static initializer to do this, because that is run at classload time, which is before the application context has loaded. Also, helper shouldn't be static -- that's bad practice -- it makes testing very difficult.
Scenario: Used WebApplicationContext to intialize the beans defined in the applicationCOntext.xml file and received a null while trying to use the instantaited bean object in the code after autowiring.
Issue in this scenario: I'm trying to autowire a spring bean in a class on which Spring has control over.
Solution:
Extending the Servlet class (Class which is not in Spring control) which is the endpoint of my JBOSS WS with Spring's SpringBeanAutowiringSupport class helped me resolve the issue.
Below is the code snippet
public class MServiceImpl extends SpringBeanAutowiringSupport implements MService{
#Autowired
private Helper helper;
public MServiceImpl() {
}
......
......
}
Figured out that using static block to initialize the spring bean is bad approach. Thanks to #Engineer Dollery

Can't #Autowire a bean into a controller - NoSuchBeanDefinitionException

I have a spring-mvc web app.
The following code has been simplified and sanitised to protect the guilty. The basic idea is that I have two separate context configuration files: one for MVC, the other for general config stuff.
When Spring goes to wire up the controller, I get:
org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'configController': Injection of autowired dependencies failed; nested exception is org.springframework.beans.factory.BeanCreationException: Could not autowire field: private com.example.ConfigBean com.example.ConfigController.config; nested exception is org.springframework.beans.factory.NoSuchBeanDefinitionException: No matching bean of type [com.example.ConfigBean] found for dependency: expected at least 1 bean which qualifies as autowire candidate for this dependency. Dependency annotations: {#org.springframework.beans.factory.annotation.Autowired(required=true)}
However, the following code from another servlet works just fine:
WebApplicationContext context = WebApplicationContextUtils.getWebApplicationContext(event.getServletContext());
ConfigBean config = context.getBean(ConfigBean.class);
This suggests to me that the MVC component scanner can't see the config stuff for some reason. I've tried adding
<import resource="config.xml" />
to dispatcher-servlet.xml, but that made no difference. It feels wrong anyway, as I don't want two instances of the config beans. Even manually copying the ConfigBean declaration into dispatcher.xml doesn't fix my problem, which suggests to me I'm doing something really dumb. Any suggestions on what I might be missing?
My detailed configuration is as follows:
web.xml
<?xml version="1.0" encoding="ISO-8859-1"?>
<web-app xmlns="http://java.sun.com/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd"
version="3.0">
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>
/WEB-INF/dispatcher-servlet.xml
/WEB-INF/config.xml
</param-value>
</context-param>
<servlet>
<servlet-name>dispatcher</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>dispatcher</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping>
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
... Some other non-spring stuff ...
</web-app>
dispatcher-servlet.xml
<?xml version="1.0" encoding="ISO-8859-1"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:mvc="http://www.springframework.org/schema/mvc"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="
http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context.xsd
http://www.springframework.org/schema/mvc
http://www.springframework.org/schema/mvc/spring-mvc.xsd">
<context:annotation-config />
<context:component-scan base-package="com.example" />
<mvc:annotation-driven />
</beans>
classpath:config.xml
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:util="http://www.springframework.org/schema/util"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/util
http://www.springframework.org/schema/util/spring-util.xsd">
<bean class="com.example.ConfigBean">
<property name="foo" value="bar" />
</bean>
</beans>
ConfigController.java
package com.example;
import com.example.ConfigBean
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.ResponseBody;
#Controller
#RequestMapping("/config")
public class ConfigController {
#Autowired
private ConfigBean config;
#RequestMapping(method=RequestMethod.GET)
public #ResponseBody ConfigBean getConfig() {
return config;
}
}
It might be because you have added /WEB-INF/dispatcher-servlet.xml to contextConfigLocation in context-param.
It is not required as the web-application context will ready the file based on the displater servlet name
From Spring Doc
Upon initialization of a DispatcherServlet, Spring MVC looks for a
file named [servlet-name]-servlet.xml in the WEB-INF directory of your
web application and creates the beans defined there, overriding the
definitions of any beans defined with the same name in the global
scope.
I think the autowiring is failing due to multiple instance of ConfigBean bean being present. The error message is slightly confusing. You get the same error if the bean is missing or if there are more than one instance.
The problem is with the component scan in the dispatcher-servlet.xml. Assuming that the ConfigBean class is also annotated with #Component or one of it's subtypes two instances will get created. Once for the bean definition in config.xml and once by component scanning.
To fix this you need to change the component-scan to ignore non-controller classes.
<context:component-scan user-default-filters='false'>
<context:include-filter annotation="org.springframework.stereotype.Controller"/>
</context:component-scan>
The lookup in the other servlet class is working because you are accessing the root application context directly.
This did turn out to be pretty dumb. The <context:annotation-config /> directive should have been in config.xml, not dispatcher-servlet.xml.
As I understand it, the annotation stuff is in the parent context, so that's where the directive belongs.

Categories