Inconsistent NoSuchBeanDefinitionException since upgrading from Spring 3.0 to Spring 3.1 - java

We've been seeing inconsistent NoSuchBeanDefinitionException since upgrading from Spring 3.0 to Spring 3.1. It happens to only about 2% of our hosts and even then the problem is not consistent in a single host since it might not happen after restarting the same server.
Here's the error :
nested exception is org.springframework.beans.factory.BeanCreationException: Could
not autowire field: private com.google.common.util.concurrent.ListeningExecutorService
com.amazon.ms3.container.impl.ExecutionEnvironmentImpl.functionThreadPool;
nested exception is org.springframework.beans.factory.NoSuchBeanDefinitionException:
No matching bean of type [com.google.common.util.concurrent.ListeningExecutorService]
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=functionThreadPool)}
| at org.springframework.beans.factory.annotation
.AutowiredAnnotationBeanPostProcessor.postProcessPropertyValues...
Here's the bean code (irrelevant code removed):
public class ExecutionEnvironmentImpl extends ExecutionEnvironment {
#Autowired
#Qualifier("functionThreadPool")
private ListeningExecutorService functionThreadPool;
public ExecutionEnvironmentImpl() {
}
public void setFunctionThreadPool(ListeningExecutorService functionThreadPool) {
this.functionThreadPool = functionThreadPool;
}
}
And here's the configuration file (irrelevant configuration removed):
<?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 id="executionEnvironment" class="com.amazon.ms3.container.impl.ExecutionEnvironmentImpl" scope="prototype"/>
<!-- ThreadPool for executing tenant functions asynchronously -->
<bean id="functionThreadPool" class="com.google.common.util.concurrent.MoreExecutors" factory-method="listeningDecorator">
<constructor-arg>
<bean class="java.util.concurrent.Executors" factory-method="newCachedThreadPool"/>
</constructor-arg>
</bean>
</beans>
The Qualifier annotation isn't much of use anymore since we don't have other ListeningExecutorService defined but I don't believe it should be causing any problem.
Any ideas of what might be causing this? I've been thinking about removing the autowiring completely but I'd like to understand why this is happening in the first place.
Thanks!

This is possibly some timing-related issue in the order that Spring brings up beans in the application context. It may be worth explicitly telling Spring to create the functionThreadPool first to ensure that it is available for autowiring into the executionEnvironment. To do that, you can use the depends-on attribute:
<bean id="executionEnvironment"
class="com.amazon.ms3.container.impl.ExecutionEnvironmentImpl"
scope="prototype"
depends-on="functionThreadPool"/>
<!-- ThreadPool for executing tenant functions asynchronously -->
<bean id="functionThreadPool" class="com.google.common.util.concurrent.MoreExecutors" factory-method="listeningDecorator">
<constructor-arg>
<bean class="java.util.concurrent.Executors" factory-method="newCachedThreadPool"/>
</constructor-arg>
</bean>
</beans>
If you intend to use autowiring then you should have the <context:annotation-config> element in the configuration also - so that Spring knows to autowire the functionThreadPool into the executionEnvironment.

After trying depends-on and even wiring the bean directly like shown below :
<bean id="executionEnvironment" class="com.amazon.ms3.container.impl.ExecutionEnvironmentImpl" scope="prototype">
<property name="functionThreadPool" ref="functionThreadPool"/>
</bean>
<!-- ThreadPool for executing tenant functions asynchronously -->
<bean id="functionThreadPool" class="com.google.common.util.concurrent.MoreExecutors" factory-method="listeningDecorator">
<constructor-arg>
<bean class="java.util.concurrent.Executors" factory-method="newCachedThreadPool"/>
</constructor-arg>
</bean>
we were still seeing the same error on some occasions. The only thing that fixed it was to remove the #Autowired annotation in the ExecutionEnvironmentImpl class.
We didn't really fix the problem but more like avoiding it. I wish I could provide a better answer.

Related

Cache interceptor call is ignored

I am working on cache implementation (exstremescale)for maven multi module project, where i have added below maven dependency
<dependency>
<groupId>com.ibm.extremescale</groupId>
<artifactId>ogclient</artifactId>
<version>8.6.0.20150901-215917</version>
</dependency>
Added caching annotation on
#Override
#Cacheable(value = "productDetails", key = "#productId + #orgId")
public Product productRead(final String productId, final String productKey, final String orgId, final CRApplicationEnum sourceSystem) throws IntegrationException {
cache-manager.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:p="http://www.springframework.org/schema/p"
xmlns:cache="http://www.springframework.org/schema/cache"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/cache http://www.springframework.org/schema/cache/spring-cache.xsd">
<cache:annotation-driven />
<bean id="cacheManager" class="org.springframework.cache.support.SimpleCacheManager" primary="true">
<property name="caches">
<set>
<bean class="com.ibm.websphere.objectgrid.spring.ObjectGridCache"
p:name="eventDetails" p:map-name="${iev.eventDetails.mapName}"
p:object-grid-client-ref="wxsGridClient" />
<bean class="com.ibm.websphere.objectgrid.spring.ObjectGridCache"
p:name="eventValidationDetails" p:map-name="${iev.eventValidationDetails.mapName}"
p:object-grid-client-ref="wxsGridClient" />
<bean class="com.ibm.websphere.objectgrid.spring.ObjectGridCache"
p:name="productDetails" p:map-name="${ipr.productDetails.mapName}"
p:object-grid-client-ref="wxsGridClient" />
</set>
</property>
</bean>
<bean id="wxsCSDomain"
class="com.ibm.websphere.objectgrid.spring.ObjectGridCatalogServiceDomainBean"
p:catalog-service-endpoints="${xscale.catalogServiceEndpoint}" />
<bean id="wxsGridClient"
class="com.ibm.websphere.objectgrid.spring.ObjectGridClientBean"
p:catalog-service-domain-ref="wxsCSDomain" p:objectGridName="${wxs.objectGridName}" />
Caching is working for only one maven module of the project, i can see the cache interceptor call and for rest of the maven module it is ignoring the #cacheable annotation(it is not going to the interceptor).
We dont have PostConstructor or Self invokation
We are using atomikos as transaction manager and CXF -interceptors which will be executed before coming to caching methods.
Please help me on this
Your comment about JdkDynamixAopProxy and looking at the code makes me think that the method you have annotated with #Cacheable is in a concrete class. And for the annotation on a concrete class to exhibit proper behavior; you need to enable the cglib proxying in your application.
This can be done by adding proxy target class parameter to your cache annotation driven tag.
<cache:annotation-driven proxy-target-class="true"/>
If you dont want to enable class based proxying for your overall application; you can specify the behavior for a particular class by annotating it with this annotation:
#Scope(proxyMode = ScopedProxyMode.TARGET_CLASS)
Calling methods in the same class bypasses the dynamic proxy and any cross cutting concern like caching, transaction etc which is part of the dynamic proxies logic is also bypassed. So could your problem be Spring cache #Cacheable method ignored when called from within the same class ?
If so, the fix is to use AspectJ compile time or load time weaving.

Spring MVC MongoDB integration

I would like to create Spring MVC sample with mongoDB by this tutorial http://spring.io/guides/gs/accessing-data-mongodb/. I try #Autowired for CustomerRepository repository into my #Controller class, but I receive org.springframework.beans.factory.BeanCreationException for repository class member with exception message "....No matching bean of type [com.mvc.venko.CustomerRepository] found for dependency: expected at least 1 bean which qualifies as autowire candidate for this dependency..."
My #Controller class and CustomerRepository are in same package.
I can't get the problem causing this exception.
PS: using springFramework 3.1.1.RELEASE, spring-data-mongodb 1.4.2.RELEASE
EDIT:
Complete conf.xml structure for resolving problem. Please switch to Spring 3.2.5
<?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:mongo="http://www.springframework.org/schema/data/mongo"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/data/mongo
http://www.springframework.org/schema/data/mongo/spring-mongo-1.0.xsd">
<!-- Root Context: defines shared resources visible to all other web components -->
<mongo:repositories base-package="com.mvc.venko" />
<mongo:mongo host="127.0.0.1" port="27017" />
<mongo:db-factory dbname="yourdb" write-concern="NONE" />
<bean id="mongoTemplate" class="org.springframework.data.mongodb.core.MongoTemplate">
<constructor-arg name="mongoDbFactory" ref="mongoDbFactory" />
</bean>
</beans>
I think you don't configure a bean of CustomerRepository type.
You can do this with this line in your spring-config.xml:
<mongo:repositories base-package="/path to your repository package/" />
more docs here

#Autowired - No qualifying bean of type found for dependency

I've started my project by creating entities, services and JUnit tests for services using Spring and Hibernate. All of this works great.
Then I've added spring-mvc to make this web application using many different step-by-step tutorials, but when I'm trying to make Controller with #Autowired annotation, I'm getting errors from Glassfish during deployment. I guess that for some reason Spring doesn't see my services, but after many attempts I still can't handle it.
Tests for services with
#RunWith(SpringJUnit4ClassRunner.class)
#ContextConfiguration(locations = {"classpath:/beans.xml"})
and
#Autowired
MailManager mailManager;
works properly.
Controllers without #Autowired too, I can open my project in web browser without trouble.
/src/main/resources/beans.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:aop="http://www.springframework.org/schema/aop"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:jdbc="http://www.springframework.org/schema/jdbc" xmlns:tx="http://www.springframework.org/schema/tx"
xmlns:util="http://www.springframework.org/schema/util"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-3.0.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.0.xsd
http://www.springframework.org/schema/jdbc http://www.springframework.org/schema/jdbc/spring-jdbc-3.0.xsd
http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-3.0.xsd
http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util-3.0.xsd
http://java.sun.com/xml/ns/persistence/orm http://java.sun.com/xml/ns/persistence/orm_2_0.xsd">
<context:property-placeholder location="jdbc.properties" />
<context:component-scan base-package="pl.com.radzikowski.webmail">
<context:exclude-filter type="annotation" expression="org.springframework.stereotype.Controller" />
</context:component-scan>
<!--<context:component-scan base-package="pl.com.radzikowski.webmail.service" />-->
<bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close">
<property name="driverClassName" value="${jdbc.driverClassName}" />
<property name="url" value="${jdbc.url}" />
<property name="username" value="${jdbc.username}" />
<property name="password" value="${jdbc.password}" />
</bean>
<!-- Persistance Unit Manager for persistance options managing -->
<bean id="persistenceUnitManager" class="org.springframework.orm.jpa.persistenceunit.DefaultPersistenceUnitManager">
<property name="defaultDataSource" ref="dataSource"/>
</bean>
<!-- Entity Manager Factory for creating/updating DB schema based on persistence files and entity classes -->
<bean id="entityManagerFactory" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
<property name="persistenceUnitManager" ref="persistenceUnitManager"/>
<property name="persistenceUnitName" value="WebMailPU"/>
</bean>
<!-- Hibernate Session Factory -->
<bean id="sessionFactory" class="org.springframework.orm.hibernate4.LocalSessionFactoryBean">
<property name="dataSource" ref="dataSource"/>
<!--<property name="schemaUpdate" value="true" />-->
<property name="packagesToScan" value="pl.com.radzikowski.webmail.domain" />
<property name="hibernateProperties">
<props>
<prop key="hibernate.dialect">org.hibernate.dialect.MySQLDialect</prop>
</props>
</property>
</bean>
<!-- Hibernate Transaction Manager -->
<bean id="txManager" class="org.springframework.orm.hibernate4.HibernateTransactionManager">
<property name="sessionFactory" ref="sessionFactory"/>
</bean>
<!-- Activates annotation based transaction management -->
<tx:annotation-driven transaction-manager="txManager"/>
</beans>
/webapp/WEB-INF/web.xml
<web-app xmlns="http://java.sun.com/xml/ns/j2ee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" id="WebApp_ID" version="2.4" xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd">
<display-name>Spring Web 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>
/webapp/WEB-INF/mvc-dispatcher-servlet.xml
<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-3.0.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.0.xsd
http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc-3.0.xsd">
<context:component-scan base-package="pl.com.radzikowski.webmail" use-default-filters="false">
<context:include-filter type="annotation" expression="org.springframework.stereotype.Controller" />
</context:component-scan>
<mvc:annotation-driven/>
<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<property name="prefix" value="/WEB-INF/views/" />
<property name="suffix" value=".jsp" />
</bean>
</beans>
pl.com.radzikowski.webmail.service.AbstractManager
package pl.com.radzikowski.webmail.service;
import org.apache.log4j.Logger;
import org.hibernate.SessionFactory;
import org.springframework.beans.factory.annotation.Autowired;
/**
* Master Manager class providing basic fields for services.
* #author Maciej Radzikowski <maciej#radzikowski.com.pl>
*/
public class AbstractManager {
#Autowired
protected SessionFactory sessionFactory;
protected final Logger logger = Logger.getLogger(this.getClass());
}
pl.com.radzikowski.webmail.service.MailManager
package pl.com.radzikowski.webmail.service;
import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Transactional;
#Component
#Transactional
public class MailManager extends AbstractManager {
// some methods...
}
pl.com.radzikowski.webmail.HomeController
package pl.com.radzikowski.webmail.controller;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.ModelMap;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import pl.com.radzikowski.webmail.service.MailManager;
#Controller
#RequestMapping("/")
public class HomeController {
#Autowired
public MailManager mailManager;
#RequestMapping(value = "/", method = RequestMethod.GET)
public String homepage(ModelMap model) {
return "homepage";
}
}
Error:
SEVERE: Exception while loading the app
SEVERE: Undeployment failed for context /WebMail
SEVERE: Exception while loading the app : java.lang.IllegalStateException: ContainerBase.addChild: start: org.apache.catalina.LifecycleException: org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'homeController': Injection of autowired dependencies failed; nested exception is org.springframework.beans.factory.BeanCreationException: Could not autowire field: public pl.com.radzikowski.webmail.service.MailManager pl.com.radzikowski.webmail.controller.HomeController.mailManager; nested exception is org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type [pl.com.radzikowski.webmail.service.MailManager] 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)}
Sorry for a lot of code, but I don't know what can cause that error anymore.
Added
I've created the interface:
#Component
public interface IMailManager {
added implements:
#Component
#Transactional
public class MailManager extends AbstractManager implements IMailManager {
and changed autowired:
#Autowired
public IMailManager mailManager;
But it still throws errors (also when I've tried with #Qualifier)
..Could not autowire field: public
pl.com.radzikowski.webmail.service.IMailManager
pl.com.radzikowski.webmail.controller.HomeController.mailManager...
I've tried with different combinations of #Component and #Transactional too.
Shouldn't I include beans.xml in web.xml somehow?
You should autowire interface AbstractManager instead of class MailManager. If you have different implemetations of AbstractManager you can write #Component("mailService") and then #Autowired #Qualifier("mailService") combination to autowire specific class.
This is due to the fact that Spring creates and uses proxy objects based on the interfaces.
I had this happen because my tests were not in the same package as my components. (I had renamed my component package, but not my test package.) And I was using #ComponentScan in my test #Configuration class, so my tests weren't finding the components on which they relied.
So, double check that if you get this error.
The thing is that both the application context and the web application context are registered in the WebApplicationContext during server startup. When you run the test you must explicitly tell which contexts to load.
Try this:
#RunWith(SpringJUnit4ClassRunner.class)
#ContextConfiguration(locations = {"classpath:/beans.xml", "/mvc-dispatcher-servlet.xml"})
I was facing the same issue while auto-wiring the class from one of my jar file.
I fixed the issue by using #Lazy annotation:
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Lazy;
#Autowired
#Lazy
private IGalaxyCommand iGalaxyCommand;
This may help you:
I have the same exception in my project. After searching while I found that I am missing the #Service annotation to the class where I am implementing the interface which I want to #Autowired.
In your code you can add the #Service annotation to MailManager class.
#Transactional
#Service
public class MailManager extends AbstractManager implements IMailManager {
Spent much of my time with this! My bad! Later found that the class on which I declared the annotation Service or Component was of type abstract. Had enabled debug logs on Springframework but no hint was received. Please check if the class if of abstract type. If then, the basic rule applied, can't instantiate an abstract class.
Faced the same issue in my spring boot application even though I had my package specific scans enabled like
#SpringBootApplication(scanBasePackages={"com.*"})
But, the issue was resolved by providing #ComponentScan({"com.*"}) in my Application class.
Correct way shall be to autowire AbstractManager, as Max suggested, but this should work fine as well.
#Autowired
#Qualifier(value="mailService")
public MailManager mailManager;
and
#Component("mailService")
#Transactional
public class MailManager extends AbstractManager {
}
Can you try annotating only your concrete implementation with #Component? Maybe the following answer could help. It is kind of a similar problem. I usually put Spring annotations in the implementation classes.
https://stackoverflow.com/a/10322456/2619091
I ran in to this recently, and as it turned out, I've imported the wrong annotation in my service class. Netbeans has an option to hide import statements, that's why I did not see it for some time.
I've used #org.jvnet.hk2.annotations.Service instead of #org.springframework.stereotype.Service.
The solution that worked for me was to add all the relevant classes to the #ContextConfiguration annotation for the testing class.
The class to test, MyClass.java, had two autowired components: AutowireA and AutowireB. Here is my fix.
#ContextConfiguration(classes = {MyClass.class, AutowireA.class, AutowireB.class})
public class MyClassTest {
...
}
My guess is that here
<context:component-scan base-package="pl.com.radzikowski.webmail" use-default-filters="false">
<context:include-filter type="annotation" expression="org.springframework.stereotype.Controller" />
</context:component-scan>
all annotations are first disabled by use-default-filters="false" and then only #Controller annotation enabled. Thus, your #Component annotation is not enabled.
One reason BeanB may not exist in the context
Another cause for the exception is the existence of two bean
Or definitions in the context bean that isn’t defined is requested by name from the Spring context
see more this url:
http://www.baeldung.com/spring-nosuchbeandefinitionexception
<context:component-scan base-package="com.*" />
same issue arrived , i solved it by keeping the annotations intact and in dispatcher servlet :: keeping the base package scan as com.*. this worked for me.
Instead of #Autowire MailManager mailManager, you can mock the bean as given below:
import org.springframework.boot.test.mock.mockito.MockBean;
::
::
#MockBean MailManager mailManager;
Also, you can configure #MockBean MailManager mailManager; separately in the #SpringBootConfiguration class and initialize like below:
#Autowire MailManager mailManager
This also happened to me when I had two methods with the same name marked #Bean in different #Configuration classes. It appears that one of the declarations was overriding the other.
If you are testing your controller.
Don't forget to use #WebAppConfiguration on your test class.
I had this happen because I added an autowired dependency to my service class but forgot to add it to the injected mocks in my service unit test.
The unit test exception appeared to report a problem in the service class when the problem was actually in the unit test. In retrospect, the error message told me exactly what the problem was.
I had faced the same problem,
Issue SOlved using below steps:
Check the class/Interface that you are auto wiring
For Interface Business logic we should use #service when it extends the Interface method.
For Dao that is a Database handling class we should use #Repository.
→ We can use #Service, #Repository and #Component annotation effectively and solve this issue very fast.
if you are testing the DAO layer you must use #Autowire annotation like this:
#Autowired
private FournisseurDao fournisseurDao;
Don't inject a repository element in the constructor
I've reproduced similar issue in multi-module project w/ No qualifying bean of type like:
Caused by: org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type 'com.example.stockclient.repository.StockPriceRepository' available: expected at least 1 bean which qualifies as autowire candidate. Dependency annotations: {}
and the reason for this error was missing annotation #EnableJpaRepositories in my specific use case.
To clarify: this annotation needs to be added for enabling auto configuration support for Spring Data JPA required to know the path of JPA repositories. By default, it will scan only the main application package and its sub packages for detecting the JPA repositories.
For more details you can refer, for instance, to this article.
Was configuring a non-SpringBoot, non-JPA, Hibernate application and the error was seen with injecting a DAO class implementation defined with #Repository.
Moving the declaration from #Repository to #Component worked. Remember that you would lose some features as mentioned here

Spring Autowiring Service doesn't work in my Controller

i've problems in order to autowire a service in my controller. I've this error:
org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'myController': Injection of autowired dependencies failed; nested exception is org.springframework.beans.factory.BeanCreationException: Could not autowire field: private es.unican.meteo.service.UserService es.unican.meteo.controller.MyController.userService; nested exception is org.springframework.beans.factory.NoSuchBeanDefinitionException: No matching bean of type [es.unican.meteo.service.UserService] 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)}
It seems that the userService is not registered, so that, the controller can't get the bean. I thought that my config was ok because it works with the tests. In the tests i have this:
ClassPathXmlApplicationContext("/WEB-INF/app-config.xml");
and i can get the bean ok from the ApplicationContext.xml
My package structure is the following:
es.unican.meteo.controller
|---- MyController.java
es.unican.meteo.service
|---- UserService.java
es.unican.meteo.service.impl
|---- UserServiceImpl.java
.....
WebContent/WEB-INF
|---- MyDispatcherServlet-servlet.xml
|---- app-config.xml
|---- web.xml
.....
The clases:
== UserServiceImpl.java ==
#Service
public class UserServiceImpl implements UserService{
#Autowired
private UserMapper userMapper;
public void setUserMapper(UserMapper userMapper) {
this.userMapper = userMapper;
}
== MyController.java ==
#Controller
public class MyController {
#Autowired
private UserService userService;
#RequestMapping(method=RequestMethod.GET, value="/home")
public String handleRequest(){
return "welcome";
}
#RequestMapping(method=RequestMethod.GET, value="/getUsers")
public #ResponseBody List<User> getUsersInJSON(){
return userService.getUsers();
}
}
== web.xml ==
<display-name>Spring MVC</display-name>
<servlet>
<servlet-name>MyDispatcherServlet</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>MyDispatcherServlet</servlet-name>
<url-pattern>*.go</url-pattern>
</servlet-mapping>
</web-app>
== app-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:context="http://www.springframework.org/schema/context"
xmlns:p="http://www.springframework.org/schema/p"
xmlns:mvc="http://www.springframework.org/schema/mvc"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.1.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.1.xsd
http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc-3.1.xsd">
<!-- Scans the classpath of this application for #Components to deploy as beans -->
<context:component-scan base-package="es.unican.meteo" />
<!-- Configures the #Controller programming model -->
<mvc:annotation-driven/>
<bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource"
p:driverClassName="org.apache.derby.jdbc.EmbeddedDriver"
p:url="jdbc:derby:C:\tools\derbydb"
p:connectionProperties=""
p:username="APP"
p:password="" />
<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="dataSource"/>
</bean>
<bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
<property name="dataSource" ref="dataSource" />
<property name="configLocation" value="/mybatis-config.xml" />
</bean>
<bean id="usersMapper" class="org.mybatis.spring.mapper.MapperFactoryBean">
<property name="mapperInterface" value="es.unican.meteo.dao.UserMapper" />
<property name="sqlSessionFactory" ref="sqlSessionFactory" />
</bean>
<bean id="rolesMapper" class="org.mybatis.spring.mapper.MapperFactoryBean">
<property name="mapperInterface" value="es.unican.meteo.dao.RoleMapper" />
<property name="sqlSessionFactory" ref="sqlSessionFactory" />
</bean>
</beans>
== MyDispatcherServlet.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:context="http://www.springframework.org/schema/context"
xmlns:mvc="http://www.springframework.org/schema/mvc"
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-3.1.xsd
http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc-3.1.xsd">
<!-- Enabling Spring beans auto-discovery -->
<context:component-scan base-package="es.unican.meteo.controller" />
<!-- Enabling Spring MVC configuration through annotations -->
<mvc:annotation-driven />
<!-- Defining which view resolver to use -->
<bean class= "org.springframework.web.servlet.view.InternalResourceViewResolver" >
<property name="prefix" value="/WEB-INF/views/" />
<property name="suffix" value=".jsp" />
</bean>
Spring mvc logger trace:
19:38:54,119 DEBUG http-8080-1 support.DefaultListableBeanFactory:430 - Creating instance of bean 'myController'
19:38:54,170 DEBUG http-8080-1 annotation.InjectionMetadata:60 - Found injected element on class [es.unican.meteo.controller.MyController]: AutowiredFieldElement for private es.unican.meteo.service.UserService es.unican.meteo.controller.MyController.userService
19:38:54,174 DEBUG http-8080-1 support.DefaultListableBeanFactory:504 - Eagerly caching bean 'myController' to allow for resolving potential circular references
19:38:54,206 DEBUG http-8080-1 annotation.InjectionMetadata:85 - Processing injected method of bean 'myController': AutowiredFieldElement for private es.unican.meteo.service.UserService es.unican.meteo.controller.MyController.userService
19:38:54,224 DEBUG http-8080-1 support.DefaultListableBeanFactory:217 - Creating shared instance of singleton bean 'userServiceImpl'
19:38:54,226 DEBUG http-8080-1 support.DefaultListableBeanFactory:430 - Creating instance of bean 'userServiceImpl'
19:38:54,234 DEBUG http-8080-1 annotation.InjectionMetadata:60 - Found injected element on class [es.unican.meteo.service.impl.UserServiceImpl]: AutowiredFieldElement for private es.unican.meteo.dao.UserMapper es.unican.meteo.service.impl.UserServiceImpl.userMapper
19:38:54,237 DEBUG http-8080-1 support.DefaultListableBeanFactory:504 - Eagerly caching bean 'userServiceImpl' to allow for resolving potential circular references
19:38:54,256 DEBUG http-8080-1 annotation.InjectionMetadata:85 - Processing injected method of bean 'userServiceImpl': AutowiredFieldElement for private es.unican.meteo.dao.UserMapper es.unican.meteo.service.impl.UserServiceImpl.userMapper
19:38:54,268 INFO http-8080-1 support.DefaultListableBeanFactory:433 - Destroying singletons in org.springframework.beans.factory.support.DefaultListableBeanFactory#56088b29: defining beans [myController,roleService,userServiceImpl,org.springframework.context.annotation.internalConfigurationAnnotationProcessor,org.springframework.context.annotation.internalAutowiredAnnotationProcessor,org.springframework.context.annotation.internalRequiredAnnotationProcessor,org.springframework.context.annotation.internalCommonAnnotationProcessor,org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping#0,org.springframework.format.support.FormattingConversionServiceFactoryBean#0,org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter#0,org.springframework.web.servlet.handler.MappedInterceptor#0,org.springframework.web.servlet.mvc.method.annotation.ExceptionHandlerExceptionResolver#0,org.springframework.web.servlet.mvc.annotation.ResponseStatusExceptionResolver#0,org.springframework.web.servlet.mvc.support.DefaultHandlerExceptionResolver#0,org.springframework.web.servlet.handler.BeanNameUrlHandlerMapping,org.springframework.web.servlet.mvc.HttpRequestHandlerAdapter,org.springframework.web.servlet.mvc.SimpleControllerHandlerAdapter,org.springframework.web.servlet.view.InternalResourceViewResolver#0,org.springframework.context.annotation.ConfigurationClassPostProcessor$ImportAwareBeanPostProcessor#0]; root of factory hierarchy
19:38:54,279 ERROR http-8080-1 servlet.DispatcherServlet:457 - Context initialization failed
I've reviewed some questions about this topic but i don't find a solution to my problem. Maybe i'm skipping something but i don't know certainly. I tried to change the component-scan with no results.
When i try to access to /SPRING-MVC/getUsers.go appears those errors.
I don't know if the beans must be placed in app-config (applicationContext) or in the servlet.xml because it is a little bit confusing...
Thank you
Your configuration is very strange...
First rule out the obvious
I don't see root web application context configuration in your web.xml. Could it be that you forgot to add this piece of code?
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>
WEB-INF/app-config.xml
</param-value>
</context-param>
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
Now a little bit of theory
Bit of Spring theory - Spring uses application context hierarchy for web applications:
top level web application context is loaded by ContextLoaderListener
then there are separate contexts for each DispatcherServlet instances
When a new bean is being instantiated, it can get dependencies either from the context where it is being defined or from parent context. This makes possible to define common beans in the root context (services, DAO, ...) and have the request handling beans in servlet application contexts as each servlet can have its own set of controllers, view handers, ...
Last, but not least - your errors
You are configuring MVC in your root context. That is just wrong. Remove the <mvc: context from there.
You are also registering your controllers in the root context via the <context:component-scan> on your base package. Make the component scan just on the services package or separate your classes into two top level packages core (for the root beans) and servlet (for servlet beans).
Make sure that your UserServiceImpl is in same package as defined in context:component-scan. If it's not, spring will not be able to detect it. Also, try removing value attribute from UserServiceImpl definition, since there is only 1 bean of that type. Spring will be able to autowire it by type.
You need to change the way you have autowired the service in the controller.
Change the following code
#Autowired
private UserService userService;
with following
#Resource(name="userService")
private UserService userService;
Because in the UserServiceImpl you have defined the #Service annotation with alias "userService".
I hope this would resolve your problem. :)
when ever you face such kind of problem kindly check, what is the path for context:component-scan basepackage
it should be root name Like if I am taking com.mike as package name & which contain bean,controller,dao,service folder in its structure then, in such condition you have to follow Like ----context:component-scan basepackaage="com.mike.*"
where * means all the folder (bean,service,dao,controller and theie corresponding classes) will be scaned.
You can use the #Qualifier annotation as follows:
#Autowired
#Qualifier("userService")
private UserService userService;
On first glance the config seems ok, yet there may be some smaller tripwires that might be not that obvious.
a) implemented UserService interface, is it the same as the controller needs? Dumb question, I know, but just be on the safe side.
b) bean name: Try eradicating the value-value (ba-da-tush) from the #Service annotation, its superflous anyway. Or be more specific with the help of an #Qualifier.
c) package scanning: Double check if your implemented service is really within es.unican.meteo. Sometimes its the small things.
Add #Component annotation on your service. It should work fine

Spring MongoDB and Apache Shiro

I am attempting to use Apache Shiro with Spring and MongoDB. I am using Spring Data Repositories which are autowired. I have created my own custom realm for Shiro which uses a Spring Data repository to talk to Mongo:
public class PlatformRealm extends AuthorizingRealm {
#Autowired(required = true)
protected UserRepository userRepository = null;
#Override
protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException {
...
}
}
The problem I'm seeing is the userRepository isn't being autowired. I get the following line in my console output referring to the PlatformRealm:
INFO org.springframework.web.context.support.XmlWebApplicationContext - Bean 'platformRealm' of type [class com.resonance.platform.core.security.PlatformRealm] is not eligible for getting processed by all BeanPostProcessors (for example: not eligible for auto-proxying)
This is because of the Apache Shiro ShiroFilterFactoryBean. What is happening is this bean and all of its dependencies are being loaded up immediately when the container is started. It doesn't wait for my persistence beans to be initialized prior to resolving dependencies. This causes the repository reference to be null.
The following bean configurations are loaded via the contextConfigLocation parameter:
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>
/WEB-INF/web-platform-persistence.xml,
/WEB-INF/web-platform-services.xml
</param-value>
</context-param>
Services bean configuration:
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:context="http://www.springframework.org/schema/context"
xmlns:util="http://www.springframework.org/schema/util"
xsi:schemaLocation="http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-3.0.xsd
http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util-3.0.xsd">
<bean id="userSession"
class="com.resonance.platform.web.core.services.ShiroUserSessionService" />
<!-- Shiro (Security) -->
<bean id="shiroFilter" class="org.apache.shiro.spring.web.ShiroFilterFactoryBean">
<property name="securityManager" ref="securityManager" />
<property name="loginUrl" value="/login" />
<property name="successUrl" value="/" />
<!-- The 'filters' property is not necessary since any declared javax.servlet.Filter
bean -->
<!-- defined will be automatically acquired and available via its beanName
in chain -->
<!-- definitions, but you can perform instance overrides or name aliases
here if you like: -->
<!-- <property name="filters"> <util:map> <entry key="anAlias" value-ref="someFilter"/>
</util:map> </property> -->
<property name="filterChainDefinitions">
<value>
# some example chain definitions:
/admin/** = passThruFilter, roles[admin]
/** = passThruFilter
</value>
</property>
</bean>
<bean id="passThruFilter"
class="org.apache.shiro.web.filter.authc.PassThruAuthenticationFilter" />
<bean id="securityManager" class="org.apache.shiro.web.mgt.DefaultWebSecurityManager">
<!-- Single realm app. If you have multiple realms, use the 'realms' property
instead. -->
<property name="realm" ref="platformRealm" />
<!-- By default the servlet container sessions will be used. Uncomment
this line to use shiro's native sessions (see the JavaDoc for more): -->
<!-- <property name="sessionMode" value="native"/> -->
</bean>
<bean id="lifecycleBeanPostProcessor" class="org.apache.shiro.spring.LifecycleBeanPostProcessor" />
<bean class="org.springframework.aop.framework.autoproxy.DefaultAdvisorAutoProxyCreator"
depends-on="lifecycleBeanPostProcessor" />
<bean class="org.apache.shiro.spring.security.interceptor.AuthorizationAttributeSourceAdvisor">
<property name="securityManager" ref="securityManager" />
</bean>
<!-- Define the Shiro Realm implementation you want to use to connect to
your back-end -->
<!-- security datasource: -->
<bean id="platformRealm" class="com.resonance.platform.core.security.PlatformRealm" />
Persistence bean config:
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:context="http://www.springframework.org/schema/context"
xmlns:mongo="http://www.springframework.org/schema/data/mongo"
xmlns:util="http://www.springframework.org/schema/util"
xsi:schemaLocation="http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-3.0.xsd
http://www.springframework.org/schema/data/mongo
http://www.springframework.org/schema/data/mongo/spring-mongo-1.0.xsd
http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
http://www.springframework.org/schema/util
http://www.springframework.org/schema/util/spring-util-3.0.xsd">
<mongo:mongo id="mongo" />
<bean id="mongoTemplate" class="org.springframework.data.mongodb.core.MongoTemplate">
<constructor-arg ref="mongo" />
<constructor-arg value="platform" />
<property name="writeConcern">
<util:constant static-field="com.mongodb.WriteConcern.SAFE" ></util:constant>
</property>
</bean>
<mongo:repositories base-package="com.resonance.platform.core.data.repositories" />
User Repository:
package com.resonance.platform.core.data.repositories;
import org.bson.types.ObjectId;
import org.springframework.data.repository.CrudRepository;
import com.resonance.platform.core.entities.User;
/**
* A repository used to manage User entities.
* #author Kyle
*/
public interface UserRepository extends CrudRepository<User, ObjectId> {
/**
* Gets a user by the specified login.
* #param login
* #return
*/
User getByLogin(String login);
}
My question is, how can I get the userRepository dependency to resolved properly? I understand that the ShiroFilterFactoryBean has to be initialized before the other dependencies and whatnot, but there must be a way to get the userRepository dependency to be resolved.
EDIT: Added User Repository code.
I am running into the same problem described here.
I am noticing two spring factories.
from the dispacher-servlet.xml which loads #Service #Repository classes due to component-scan defined at an base package level so I can #Autowire Service class into Controller.
from application context doesn't seem to #Autowire classes marked as #Service because they are not loaded.
If I understand you right you should be able to create a subclass of ShiroFilterFactoryBean which implements org.springframework.beans.factory.InitializingBean. In InitializingBean.afterPropertiesSet() you would then add some code that gets the UserRepository and sets it to that field. Not the most elegant solution, but this looks like an exceptional case.
I've had this problem too. It has something to do with the order of bean initialization in the Spring container. The workaround is not to autowire the repository but have your realm implement ApplicationContextAware and get the needed beans straight from the context. It's not elegant, but it'll work.
I am not too sure if this is helpful, but you may check this question from me for an alternative solution.
But, the core issue probably still stays open.
Concrete problem explanation taken from ShiroFilterFactoryBean-and-a-spring-data-mongodb-realm:
The problem is that spring-data-mongodb requires a spring
ApplicationEventMulticaster to have been initialised before it can be
used.
ShiroFilterFactoryBean is a beanPostProcessor, and as such, during
initialisation, spring attempts to configure its realms(and hence my
realm and spring data mongo based userDao). it fails because
ApplicationEventMulticaster has not yet been created.
After I've tried several suggested ways to solve this problem, like the InitializingBean, ApplicationContextAware or BeanPostProcessor interfaces (each resulting in a premature invocation, hence before initializing my necessary service/repository stuff), I came up with the following solution:
Let spring create your shiro context without any automatic bean resolution to your services/repositories.
Let spring create your service/repository context, including mongodb
Create a simple class which will take care of your shiro-service coupling and configure it accordingly in your spring config. This class will be invoked after your shiro and service context has been successful set up.
To (1), sth. like this:
<bean id="shiroFilter" class="org.apache.shiro.spring.web.ShiroFilterFactoryBean">
<property name="securityManager" ref="securityManager" />
<property name="filterChainDefinitions">
<value>
<!-- Your definitions -->
</value>
</property>
</bean>
<bean id="securityManager" class="org.apache.shiro.web.mgt.DefaultWebSecurityManager"
p:realm-ref="myShiroRealm" />
<bean id="myShiroRealm" class="com.acme.MyShiroRealm"
<!--no bean refs here-->
/>
To (2), sth. like this:
<bean id="myService" class="com.acme.MyService"
c:myRepository-ref="myRepository" />
...
<!-- Ask Spring Data to scan our repositories -->
<mongo:repositories base-package="com.acme.repository.impl.mongodb" />
To (3):
public class ShiroRealmServiceBridge {
public static void postInject( MyShiroServerRealm realm, MyService service ) {
realm.setService( service );
}
}
<bean class="org.springframework.beans.factory.config.MethodInvokingFactoryBean">
<property name="targetClass"><value>com.acme.ShiroRealmServiceBridge</value></property>
<property name="targetMethod"><value>postInject</value></property>
<property name="arguments">
<list>
<ref bean="myShiroRealm" />
<ref bean="myService" />
</list>
</property>
Advantages:
It works xD
No additional burden/dependencies on your shiro stuff
Complete spring configuration and setup, resulting in a consistent state after initialization
Disadvantage:
One time overhead setup
May result in an inconsistent state, which will complain at runtime rather than at startup, if you forget or bump the glue-configuration
The ShiroFilterFactoryBean implements the BeanPostProcessor and, since it has dependencies on the security manager w/ its own dependencies on data stores, data access objects, etc. it can cause a whole slew of Bean X of type Y is not eligible for getting processed by all BeanPostProcessors messages.
The worst part is that it seems to be just a way to see the Filter implementations that Spring is instantiating in order to track and possibly inject properties into AuthorizationFilters.
Frankly I don't need that headache just for filter tracking, so I created a custom version that did not include the BeanPostProcessor. I'm now forced to manually wire in Filter implementations to the beans "filters" property, but at least I don't have to deal with that error and the questionable status of my security manager and related beans.

Categories

Resources