0

First of all, it's my post here and I would like to humbly say hi to the SO community - I've found a lot of answers for various issues and got a whole bunch of problems resolved here.

But I stumbled upon one issue, that I couldn't find a solution to. I'd like to point out the fact here, that I've been developing for a month, so I'm on a beginner level in Spring.

I am developing a backend RESTful webservice which handles and processes requests from dedicated Android and iOS Apps. I am using Spring MVC template (version 4.1.4.RELEASE) on the server-side and Wildfly 8.2 as a container.

Now, I have to implement a hashing algorithm to encode User activation password and unique Device identifier (currently these values are stored in database in raw plaintext), and match the input to the hashed values.

Spring Security provides a convenient BCrypt Password encoder/matcher class which fully satisfies my needs (I do not need other Spring Security functionalities, like filter chaining etc., but I will use them eventually, when I become fluent with Spring and grasp the Security concept).

The first step of implementing Spring-Security to my project already comes as a showstopper - importing spring-security-config and/or spring-security-core pom.xml dependency and trying to deploy my app, causes proxying errors during context initialization in my service class:

    10:02:00,845 ERROR [org.jboss.msc.service.fail] (MSC service thread 1-1) MSC000001: Failed to start service jboss.undertow.deployment.default-server.default-host./atwork: org.jboss.msc.service.StartException in service jboss.undertow.deployment.default-server.default-host./atwork: Failed to start service
    at org.jboss.msc.service.ServiceControllerImpl$StartTask.run(ServiceControllerImpl.java:1904) [jboss-msc-1.2.2.Final.jar:1.2.2.Final]
    at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142) [rt.jar:1.8.0_25]
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617) [rt.jar:1.8.0_25]
    at java.lang.Thread.run(Thread.java:745) [rt.jar:1.8.0_25]
Caused by: java.lang.RuntimeException: org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'authenticationService': Injection of autowired dependencies failed; nested exception is org.springframework.beans.factory.BeanCreationException: Could not autowire field: private pl.atwork.dao.EmployeeDao pl.atwork.service.AuthenticationService.empDao; nested exception is org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type [pl.atwork.dao.EmployeeDao] 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)}
    at io.undertow.servlet.core.DeploymentManagerImpl.deploy(DeploymentManagerImpl.java:222)
    at org.wildfly.extension.undertow.deployment.UndertowDeploymentService.startContext(UndertowDeploymentService.java:87)
    at org.wildfly.extension.undertow.deployment.UndertowDeploymentService.start(UndertowDeploymentService.java:72)
    at org.jboss.msc.service.ServiceControllerImpl$StartTask.startService(ServiceControllerImpl.java:1948) [jboss-msc-1.2.2.Final.jar:1.2.2.Final]
    at org.jboss.msc.service.ServiceControllerImpl$StartTask.run(ServiceControllerImpl.java:1881) [jboss-msc-1.2.2.Final.jar:1.2.2.Final]
    ... 3 more
Caused by: org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'authenticationService': Injection of autowired dependencies failed; nested exception is org.springframework.beans.factory.BeanCreationException: Could not autowire field: private pl.atwork.dao.EmployeeDao pl.atwork.service.AuthenticationService.empDao; nested exception is org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type [pl.atwork.dao.EmployeeDao] 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)}
    at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor.postProcessPropertyValues(AutowiredAnnotationBeanPostProcessor.java:334)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.populateBean(AbstractAutowireCapableBeanFactory.java:1202)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:537)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:476)
    at org.springframework.beans.factory.support.AbstractBeanFactory$1.getObject(AbstractBeanFactory.java:303)
    at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:230)
    at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:299)
    at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:194)
    at org.springframework.beans.factory.support.DefaultListableBeanFactory.preInstantiateSingletons(DefaultListableBeanFactory.java:762)
    at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:757)
    at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:480)
    at org.springframework.web.context.ContextLoader.configureAndRefreshWebApplicationContext(ContextLoader.java:403)
    at org.springframework.web.context.ContextLoader.initWebApplicationContext(ContextLoader.java:306)
    at org.springframework.web.context.ContextLoaderListener.contextInitialized(ContextLoaderListener.java:106)
    at io.undertow.servlet.core.ApplicationListeners.contextInitialized(ApplicationListeners.java:173)
    at io.undertow.servlet.core.DeploymentManagerImpl.deploy(DeploymentManagerImpl.java:193)
    ... 7 more
Caused by: org.springframework.beans.factory.BeanCreationException: Could not autowire field: private pl.atwork.dao.EmployeeDao pl.atwork.service.AuthenticationService.empDao; nested exception is org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type [pl.atwork.dao.EmployeeDao] 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)}
    at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor$AutowiredFieldElement.inject(AutowiredAnnotationBeanPostProcessor.java:561)
    at org.springframework.beans.factory.annotation.InjectionMetadata.inject(InjectionMetadata.java:88)
    at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor.postProcessPropertyValues(AutowiredAnnotationBeanPostProcessor.java:331)
    ... 22 more
Caused by: org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type [pl.atwork.dao.EmployeeDao] 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)}
    at org.springframework.beans.factory.support.DefaultListableBeanFactory.raiseNoSuchBeanDefinitionException(DefaultListableBeanFactory.java:1308)
    at org.springframework.beans.factory.support.DefaultListableBeanFactory.doResolveDependency(DefaultListableBeanFactory.java:1054)
    at org.springframework.beans.factory.support.DefaultListableBeanFactory.resolveDependency(DefaultListableBeanFactory.java:949)
    at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor$AutowiredFieldElement.inject(AutowiredAnnotationBeanPostProcessor.java:533)
    ... 24 more

10:02:00,875 ERROR [org.jboss.as.controller.management-operation] (Controller Boot Thread) JBAS014613: Operation ("deploy") failed - address: ([("deployment" => "atwork.war")]) - failure description: {"JBAS014671: Failed services" => {"jboss.undertow.deployment.default-server.default-host./atwork" => "org.jboss.msc.service.StartException in service jboss.undertow.deployment.default-server.default-host./atwork: Failed to start service
    Caused by: java.lang.RuntimeException: org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'authenticationService': Injection of autowired dependencies failed; nested exception is org.springframework.beans.factory.BeanCreationException: Could not autowire field: private pl.atwork.dao.EmployeeDao pl.atwork.service.AuthenticationService.empDao; nested exception is org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type [pl.atwork.dao.EmployeeDao] 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)}
    Caused by: org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'authenticationService': Injection of autowired dependencies failed; nested exception is org.springframework.beans.factory.BeanCreationException: Could not autowire field: private pl.atwork.dao.EmployeeDao pl.atwork.service.AuthenticationService.empDao; nested exception is org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type [pl.atwork.dao.EmployeeDao] 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)}
    Caused by: org.springframework.beans.factory.BeanCreationException: Could not autowire field: private pl.atwork.dao.EmployeeDao pl.atwork.service.AuthenticationService.empDao; nested exception is org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type [pl.atwork.dao.EmployeeDao] 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)}
    Caused by: org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type [pl.atwork.dao.EmployeeDao] 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)}"}}
10:02:01,022 INFO  [org.jboss.as.server] (ServerService Thread Pool -- 28) JBAS018559: Deployed "atwork.war" (runtime-name : "atwork.war")
10:02:01,089 INFO  [org.jboss.as.controller] (Controller Boot Thread) JBAS014774: Service status report
JBAS014777:   Services which failed to start:      service jboss.undertow.deployment.default-server.default-host./atwork: org.jboss.msc.service.StartException in service jboss.undertow.deployment.default-server.default-host./atwork: Failed to start service

Here's the dependency from pom.xml that causes the problem (the version is 3.2.6.RELEASE)

<dependency>
    <groupId>org.springframework.security</groupId>
    <artifactId>spring-security-config</artifactId>
    <version>${org.springframework.security-version}</version>
</dependency>

When I comment out the spring-security dependencies, autowiring executes correctly, and my app deploys successfully.

web.xml

<?xml version="1.0" encoding="UTF-8"?>
<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">

    <display-name>ATWork Webservice</display-name>

    <context-param>
        <param-name>contextConfigLocation</param-name>
        <param-value>/WEB-INF/spring/root-context.xml 
        /WEB-INF/spring/security-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/appServlet/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>

I have two context XML files - root-context and servlet-context

root-context.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:c="http://www.springframework.org/schema/c"
    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:aop="http://www.springframework.org/schema/aop" xmlns:jee="http://www.springframework.org/schema/jee"
    xmlns:security="http://www.springframework.org/schema/security"
    xsi:schemaLocation="http://www.springframework.org/schema/jdbc http://www.springframework.org/schema/jdbc/spring-jdbc-4.1.xsd
        http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.1.xsd
        http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.1.xsd
        http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-4.1.xsd
        http://www.springframework.org/schema/jee http://www.springframework.org/schema/jee/spring-jee-4.1.xsd
        http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-4.1.xsd
        http://www.springframework.org/schema/security http://www.springframework.org/schema/security/spring-security-3.2.xsd">

    <!-- Root Context: defines shared resources visible to all other web components -->

    <!-- PROPERTY FILES -->
    <context:property-placeholder location="classpath:database.properties"
        ignore-unresolvable="true" />

    <!-- DATABASE BEANS -->

    <context:component-scan base-package="pl.atwork" />

    <!-- Enable annotation based transaction management (@Transactional) -->
    <tx:annotation-driven transaction-manager="transactionManager" />

    <!-- Datasource -->

    <jee:jndi-lookup id="dataSource" jndi-name="${database.jndi-name}"
        expected-type="javax.sql.DataSource" />

    <bean id="sessionFactory"
        class="org.springframework.orm.hibernate4.LocalSessionFactoryBean">
        <property name="dataSource" ref="dataSource" />
        <property name="packagesToScan" value="pl.atwork.model" />
        <property name="hibernateProperties">
            <props>
                <prop key="hibernate.hbm2ddl.auto">${database.hibernate.hbm2ddl.auto}</prop>
                <prop key="hibernate.dialect">${database.hibernate.dialect}</prop>
            </props>
        </property>
    </bean>

    <!-- Exception translation bean post processor: translates database specific 
        HibernateException or SQLExceptions into Spring exceptions that can be understood 
        by the application context. -->
    <bean id="persistenceExceptionTranslationPostProcessor"
        class="org.springframework.dao.annotation.PersistenceExceptionTranslationPostProcessor" />

    <!-- Hibernate Transaction Manager bean: controls the transactions as well 
        as roll-backs. -->
    <bean id="transactionManager"
        class="org.springframework.orm.hibernate4.HibernateTransactionManager">
        <property name="sessionFactory" ref="sessionFactory" />
    </bean>
</beans>

servlet-context.xml

<?xml version="1.0" encoding="UTF-8"?>
<beans:beans xmlns="http://www.springframework.org/schema/mvc"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:beans="http://www.springframework.org/schema/beans"
    xmlns:context="http://www.springframework.org/schema/context" xmlns:tx="http://www.springframework.org/schema/tx"
    xmlns:mvc="http://www.springframework.org/schema/mvc"
    xsi:schemaLocation="http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc-4.1.xsd
        http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.1.xsd
        http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.1.xsd
        http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-4.1.xsd">

    <!-- DispatcherServlet Context: defines this servlet's request-processing 
        infrastructure -->

    <!-- Enables the Spring MVC @Controller programming model -->
    <mvc:annotation-driven />

    <context:component-scan base-package="pl.atwork.service" />
    <tx:annotation-driven transaction-manager="transactionManager" />

    <!-- Handles HTTP GET requests for /resources/** by efficiently serving 
        up static resources in the ${webappRoot}/resources directory -->
    <resources mapping="/resources/**" location="/resources/" />

    <!-- Resolves views selected for rendering by @Controllers to .jsp resources 
        in the /WEB-INF/views directory -->
    <beans:bean
        class="org.springframework.web.servlet.view.InternalResourceViewResolver">
        <beans:property name="prefix" value="/WEB-INF/views/" />
        <beans:property name="suffix" value=".jsp" />
    </beans:bean>

    <!-- Configure bean to convert JSON to POJO and vice versa -->
    <beans:bean id="jsonMessageConverter"
        class="org.springframework.http.converter.json.MappingJackson2HttpMessageConverter">
    </beans:bean>

    <!-- Configure to plugin JSON as request and response in method handler -->
    <beans:bean
        class="org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter">
        <beans:property name="messageConverters">
            <beans:list>
                <beans:ref bean="jsonMessageConverter" />
            </beans:list>
        </beans:property>
    </beans:bean>
</beans:beans>

My project structure seems OK, which is proved by valid initialization, when not importing Spring-Security dependencies:

pl.atwork.dao
---EmployeeDao.java
...
pl.atwork.model
---Employee.java
...
pl.atwork.service
---AuthenticationService.java
...
pl.atwork.service.controller
---RestController.java

RestController class, which Autowires services:

    @Controller
    public class RestController {

        @Autowired
        private AuthenticationService authService;

... other Autowired services fields and controller methods

AuthenticationService class, where proxying errors start on the first @Autowired annotation:

    @Service
    public class AuthenticationService implements Serializable {

        @Autowired
        private EmployeeDao empDao;

... other Autowired fields and @Transactional methods

EmployeeDao class, which could not be resolved when Autowiring:

@Repository
public class EmployeeDao implements Serializable {

    @Autowired
    private SessionFactory sessionFactory;

    ... typical DAO methods

I've tried enforcing GGLib proxying in context files, but it doesn't work for me. I also tried to use @Qualifier by type and name annotation for my @Autowired fields and it did not work as well.

It seems like importing spring-security dependencies entirely mess up my @Autowired configuration, and I'm out of ideas at this point. My latest clue is that maybe my component scanning in context files is a little awkward, but I do not know how to make it look and work better. Also, I am not quite sure whether I should be using interfaces in my project, and Autowire them instead of concrete implementations. I don't find a good reason to use interfaces in my project, as its not-too-wide scope is quite not worth it.

Any help would be much appreciated - I'm stuck with this for a few days now.

Mateusz W
  • 1
  • 1
  • I think that you should change `` in `` within `servlet-context.xml` – Xstian Mar 04 '15 at 10:28
  • Thanks for the comment Xstian - unfortunately, widening the scope does not work. I've tried manipulating both elements, but to no avail. The thing is, that Autowiring works well, when spring-security dependencies are not declared in pom.xml. – Mateusz W Mar 04 '15 at 10:38

2 Answers2

0

Try with a qualifier:

@Repository("employeeDao")
public class EmployeeDao implements Serializable {

And then

    @Autowired
    @Qualifier("employeeDao")
    private EmployeeDao empDao;
Martin Spa
  • 1,494
  • 1
  • 24
  • 44
  • Thanks Martin, but unfortunately explicit Qualifiers do not seem to work - I am getting the same error: `No qualifying bean of type [pl.atwork.dao.EmployeeDao] 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=employeeDao)}` – Mateusz W Mar 04 '15 at 13:17
0

Problem solved! I went through every single pom.xml import and found it weird, that I did not have spring-aop dependency added to my project. I thought AspectJ or other Spring core dependencies were enouth, but it turns out Spring Security does not resolve proxied beans without Spring-AOP dependency.

If you could provide a comprehensive explanation, I will be grateful as to know why that is the case.

Mateusz W
  • 1
  • 1