0

I realize this question has been asked many times, but those answers don't seem to get me working.

The class which has the @Autowired field:

@Component
public class SpecialClaimsCaseManager {

    @Autowired
    private SpecialClaimsCaseRepositoryService<SpecialClaimsCaseDto> service;
    public SpecialClaimsCaseManager() {
    }

    public Collection<SpecialClaimsCase> findAll() {
        return convertToSpecialClaimsCase(service.findAll());
    }

The interface SpecialClaimsCaseRepositoryService

public interface SpecialClaimsCaseRepositoryService<C extends SpecialClaimsCaseDto> {
    //Some method signatures, not relevant

The implementation class (what should be injected)

@Service("specialClaimsCaseRepositoryService") 
public class SpecialClaimsCaseRepositoryServiceImpl implements SpecialClaimsCaseRepositoryService<SpecialClaimsCaseDto> {
    //Some method implementations, not relevant

mvcDispatcher.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/mvc
                http://www.springframework.org/schema/mvc/spring-mvc-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/context
                http://www.springframework.org/schema/context/spring-context-3.0.xsd">

        <context:component-scan base-package="com.redacted.sch"/>

        <mvc:resources mapping="/resources/**" location="/resources/" />

        <mvc:annotation-driven />
        <bean class="org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor"/>

        <bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
           <property name="prefix" value="/WEB-INF/views/" />
           <property name="suffix" value=".jsp" />
        </bean>

    </beans>

web.xml

    <?xml version="1.0" encoding="UTF-8"?>
<web-app 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>SpecialClaimsHandling</display-name>

    <!-- Spring Configuration Files -->
    <context-param>
        <param-name>contextConfigLocation</param-name>
        <param-value>
            WEB-INF/application-security.xml
            classpath*:sch_model_spring.xml
        </param-value>
    </context-param>

    <!-- Spring Security Filters -->
    <filter>
        <filter-name>springSecurityFilterChain</filter-name>
        <filter-class>
             org.springframework.web.filter.DelegatingFilterProxy
        </filter-class>
    </filter>

    <filter-mapping>
        <filter-name>springSecurityFilterChain</filter-name>
        <url-pattern>/*</url-pattern>
    </filter-mapping>

    <!-- Spring Listeners -->
    <listener>
        <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
    </listener>

    <!-- MVC Filter -->
    <servlet>
        <servlet-name>mvcDispatcher</servlet-name>
        <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
        <load-on-startup>1</load-on-startup>
    </servlet>

    <servlet-mapping>
        <servlet-name>mvcDispatcher</servlet-name>
        <url-pattern>/*</url-pattern>
    </servlet-mapping>

    <!-- Session Configuration -->
    <session-config>
        <session-timeout>5</session-timeout>
    </session-config>

</web-app>

sch_model_spring.xml (in another project)

<?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:tx="http://www.springframework.org/schema/tx"
    xsi:schemaLocation="http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd
        http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
        http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx.xsd">

        <context:component-scan base-package="com.redacted.sch.model"/>

        <tx:annotation-driven />
        <tx:jta-transaction-manager />

        <bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close">
            <property name="driverClassName" value="com.ibm.db2.jcc.DB2Driver" />
            <property name="url" value="redacted" />
            <property name="username" value="redacted" />
            <property name="password" value="redacted" />
        </bean>

        <bean id="entityManagerFactory" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
              <property name="persistenceUnitName" value="schManager" />
              <property name="dataSource" ref="dataSource" />
        </bean>

        <bean id="transactionManager" class="org.springframework.orm.jpa.JpaTransactionManager">
            <property name="entityManagerFactory" ref="entityManagerFactory" />
        </bean> 
</beans>

Full stack trace (fpasted because it's pretty long) http://fpaste.org/116696/14049194/

So, as we can see, mvc:annotation-driven is enabled, and autowiring is enabled. If I understand this correctly (I might not, pretty new to Spring), this should be all I need. SpecialClaimsCaseRepositoryService is an interface, if that matters, though I don't think it should as this same @Autowiring worked fine in another class annotated with @Controller.

Thanks for any help!

jaredready
  • 2,398
  • 4
  • 23
  • 50
  • Try adding the `@Component` annotation to `SpecialClaimsCaseManager` and let me know – geoand Jul 09 '14 at 14:19
  • Added `@Component`, getting __NoSuchBeanException__ for `SpecialClaimsCaseRepositoryService`. If it matters, `SpecialClaimsCaseRepositoryService` is an interface. This `@Autowiring` did work in another class annotated with `@Controller`. I'll update the OP. – jaredready Jul 09 '14 at 14:26
  • Which version of spring are you using? Before Spring 4 RC1 you [couldn't autowire an interface with generics](https://jira.spring.io/browse/SPR-9965), you had to create your own impl and use that as bean. Also, stupid but could be, is `SpecialClaimsCaseRepositoryService` annotaded as `@Service` or similar? – Narmer Jul 09 '14 at 14:28
  • @ResidentBiscuit Could you also show the controller on which `@Autowired` that is working? – geoand Jul 09 '14 at 14:29
  • We are using 4.0.0. `SpecialClaimsCaseRepositoryService` is _not_ annotated as `@Service` (or anything), but the implementation class _is_ annotated as `@Service("specialClaimsCaseRepositoryService")`. – jaredready Jul 09 '14 at 14:30
  • Mmmh... The only thing I can't think of is package-scan. Are your impls scanned properly? Have you tried using `` instead of ``? – Narmer Jul 09 '14 at 14:40
  • Everything is under `com.redacted.sch`. I've made sure of that. The `SpecialClaimsCaseRepositoryService` and Impl class are in another Eclipse project, but it's all deployed in the same EAR so that shouldn't matter. Changing to `` doesn't fix it. Same error. – jaredready Jul 09 '14 at 14:45
  • Have you ensured that `` is _before_ ``? It means: first activate `@Autowired` then scan for components and inject the beans with `@Autowired` fields. – Narmer Jul 09 '14 at 14:49
  • Yup same error. – jaredready Jul 09 '14 at 14:53
  • Is the inreface and impl of the service build in the same class path and package as the rest of your spring code? if not... – zpontikas Jul 09 '14 at 15:08
  • 1
    @Narmer No. If you have `component-scan`, you **don't** need `annotation-config`. OP, get rid of `AutowiredAnnotationBeanPostProcessor`, it's redundant and unnecessary. Post the full stack trace. And show us how you load the XML configuration. – Sotirios Delimanolis Jul 09 '14 at 15:13
  • @Narmer If you are using component-scan, AutowiredAnnotationBeanPostProcessor is called implicitly. – Prasad Jul 09 '14 at 15:18
  • Updated post with rest of xml configuration and stack trace. – jaredready Jul 09 '14 at 15:23
  • @SotiriosDelimanolis You're right. Component-scan is already enabling `@Autowired` annotation, my bad. Also I agree, a full stack trace will surely help to figure out the problem. – Narmer Jul 09 '14 at 15:25
  • Drop a @Qualifier in there and wire by name. Also we are correctly assuming that the code scanned by: is indeed the package your service is in? – zmf Jul 09 '14 at 15:28
  • @zmf Or change `@Service("specialClaimsCaseRepositoryService")` to just `@Service` and let spring deduce the name. – Narmer Jul 09 '14 at 15:35

1 Answers1

3

You'll notice from your stack trace that the exception occurs in the process of initializing the root application context loaded by the ContextLoaderListener. That's taken from

<!-- Spring Configuration Files -->
<context-param>
    <param-name>contextConfigLocation</param-name>
    <param-value>
        WEB-INF/application-security.xml
        classpath*:sch_model_spring.xml
    </param-value>
</context-param>

In those two, you are scanning

<context:component-scan base-package="com.redacted.sch.model"/>

but not the com.redacted.sch.service... package that is required by one of the beans.

Caused by: org.springframework.beans.factory.BeanCreationException: Could not autowire field: private com.redacted.sch.service.SpecialClaimsCaseRepositoryService com.redacted.sch.model.SpecialClaimsCaseManager.specialClaimsCaseRepositoryService; 

In this case, xyz.model.SpecialClaimsCaseManager has an @Autowired field of type xyz.service.SpecialClaimsCaseRepositoryService, but no such bean exists.

Don't mix component-scanned folders between application contexts, those loaded by ContextLoaderListener vs DispatcherServlet. Refactor so that application beans are loaded by the ContextLoaderListener and controller-related beans are loaded by the DispatcherServlet.

Reading:

Community
  • 1
  • 1
Sotirios Delimanolis
  • 274,122
  • 60
  • 696
  • 724
  • Silly me... The whole time i was treating mvcDispatcher as it were applicationContext... Good one noticing! Beans in `spring-servlet.xml` can reference beans in `applicationContext.xml`, but not vice versa. Ergo he can't autowire a bean scanned in mvcDispatcher from a bean scanned in sch_model_spring. – Narmer Jul 09 '14 at 15:44
  • All my beans are configured via annotation, though. Why do I need __more__ xml? – jaredready Jul 09 '14 at 18:20
  • @ResidentBiscuit You don't need XML. The concept of root context and servlet context applies to annotation configuration just the same. The issue here is to separate them and make sure they don't have dependencies that cannot be satisfied, as is currently the case. – Sotirios Delimanolis Jul 09 '14 at 18:34
  • Then I have no idea what to do. In sch_model_spring.xml, I change the base-package of the component-scan to com.redacted.sch (base for entire project), I get an NPE because that bean is not being injected. This makes no sense. At least to me. Sorry I'm a noob here. – jaredready Jul 09 '14 at 18:52
  • @ResidentBiscuit If you haven't read the links I posted, read them. The `ApplicationContext` loaded by the `ContextLoaderListener` is self contained. Any beans declared in this context which have injection targets must have those targets satisfied by the beans in this context. – Sotirios Delimanolis Jul 09 '14 at 19:01
  • I did the read the links. They didn't really answer the question. – jaredready Jul 10 '14 at 17:59
  • @ResidentBiscuit Very simply, `SpecialClaimsCaseManager` has a dependency on `SpecialClaimsCaseRepositoryService`. Therefore, both beans have to be available in the same context. Whether you do that implicitly with component scanning or explicitly with `@Bean` methods is up to you. All you have to know is that the root context loaded by the `ContextLoaderListener` is available to the servlet context loaded by the `DispatcherServlet`, but not the other way around. – Sotirios Delimanolis Jul 10 '14 at 18:01
  • How I'm understanding this, you're telling me that the package that the service class lies in needs to be scanned by dispatcher-servlet.xml? That does not work. – jaredready Jul 10 '14 at 18:49
  • @ResidentBiscuit What won't work is having a bean declared in the root context depend on a bean declared in the servlet context. That's what your configuration is setting up right now. A bean in `xyz.model` needs a bean in `xyz.service`, but such a bean doesn't exist in the root context. – Sotirios Delimanolis Jul 10 '14 at 18:52
  • So then I should create an `application-context.xml`, and move the `component-scan`s out of `dispatcher-servlet.xml` and into `application-context.xml`? – jaredready Jul 10 '14 at 19:00
  • @ResidentBiscuit You can do that, yes. However, there are some beans that should be in the servlet context, like controller, handler mappings, etc. You have to decide on that separation. The links in the answer help do that. Look at what is in each of your packages and refactor where appropriate. – Sotirios Delimanolis Jul 10 '14 at 19:02
  • I'm sorry, but even moving it into applicationContext.xml did not resolve this. I have been fighting this for three days now and made zero progress. Spring's docs have hardly any information on @Autowire. – jaredready Jul 11 '14 at 14:03
  • @ResidentBiscuit I've been away from SO for a few days. The Spring documentation is very detailed. You should read the [chapter on IoC](http://docs.spring.io/spring/docs/current/spring-framework-reference/html/beans.html#beans-autowired-annotation) and the [chapter on Spring MVC](http://docs.spring.io/spring/docs/current/spring-framework-reference/html/mvc.html). You need to understand the Parent-Child relationship between application contexts. For simplicity, just combine your contexts into one and have that context be loaded by the `DispatcherServlet`. – Sotirios Delimanolis Jul 20 '14 at 16:37