5

I know there are so many similar questions about this. I looked through a lot of them but the problem still remains.

I have a service that gets created but is not autowired. There is no(!) manual initiation, neither in the project nor in tests (like in this question)

Both beans are found and created, says Tomcat output. At least the first service is not injected where it should be. I don't know about the second one.

Service (Interface):

public interface SchoolService {
  public School getSchool(String id);
}

Service (Implementation):

@Service
@Transactional
public class SchoolServiceImpl implements SchoolService {

  @Autowired
  private SchoolDAO schoolDAO;

  public School getSchool(String id) {
    //database things
    return school;
  }

}

Where it gets "called"

public class SchoolMenu implements Serializable {

  @Autowired
  private SchoolService schoolService;

  public SchoolMenu () {
    //here schoolService is null
    School school = schoolService.getSchool("id");
  }

}

application-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: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">


    <bean id="SchoolServiceImpl" class="content_management.School.service.SchoolServiceImpl"/>
    <bean id="SchoolDAOImpl" class="content_management.School.dao.SchoolDAOImpl"/>
</beans>

Tomcat Output:

org.springframework.beans.factory.support.DefaultListableBeanFactory: Pre-instantiating singletons in org.springframework.beans.factory.support.DefaultListableBeanFactory@57003970: defining beans [SchoolServiceImpl,SchoolDAOImpl]; root of factory hierarchy
org.springframework.beans.factory.support.DefaultListableBeanFactory: Creating shared instance of singleton bean 'SchoolServiceImpl'
org.springframework.beans.factory.support.DefaultListableBeanFactory: Creating instance of bean 'SchoolServiceImpl'
org.springframework.beans.factory.support.DefaultListableBeanFactory: Eagerly caching bean 'SchoolServiceImpl' to allow for resolving potential circular references
org.springframework.beans.factory.support.DefaultListableBeanFactory: Finished creating instance of bean 'SchoolServiceImpl'
org.springframework.beans.factory.support.DefaultListableBeanFactory: Creating shared instance of singleton bean 'SchoolDAOImpl'
org.springframework.beans.factory.support.DefaultListableBeanFactory: Creating instance of bean 'SchoolDAOImpl'
org.springframework.beans.factory.support.DefaultListableBeanFactory: Eagerly caching bean 'SchoolDAOImpl' to allow for resolving potential circular references
org.springframework.beans.factory.support.DefaultListableBeanFactory: Finished creating instance of bean 'SchoolDAOImpl'

Where is my error?

Community
  • 1
  • 1
sebastian
  • 135
  • 1
  • 5

3 Answers3

2

In order for @Autowired to work, SchoolMenu also has to be a Spring bean. If it is not, you can get schoolService from application context. Something like this

ApplicationContext appContext = new ClassPathXmlApplicationContext("application-context.xml");
SchoolService schoolService = (SchoolService) appContext.getBean(SchoolService.class);
Predrag Maric
  • 23,938
  • 5
  • 52
  • 68
2

You're accessing schoolService in the constructor of SchoolMenu:

public SchoolMenu () {
    //here schoolService is null
    School school = schoolService.getSchool("id");
}

At that point, schoolService is not yet injected. It couldn't be - nothing can happen before the constructor has been invoked.

You can declare a method to be invoked after the bean is initialized, by annotating it with the javax.annotation.PostConstruct annotation. Perform actions that need the injected dependencies in that method, not in the constructor.

(There are a few other ways to achieve the same, such as implementing the InitializingBean interface, but these are a bit outdated)

Example:

public SchoolMenu () {
}

@PostConstruct
public void init() {
    // schoolService is NOT null here
    School school = schoolService.getSchool("id");
}
Erwin Bolwidt
  • 30,799
  • 15
  • 56
  • 79
0

Instead of defining beans in xml, you can use component scan by adding this config to your application-context and Spring will scan and detect the bean automatically for you.

<context:component-scan base-package="content_management.School" />

Also you need to add in the context namespace so the application-context.xml will look like this:

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

 <context:component-scan base-package="content_management.School" />

 </beans>
Tony Vu
  • 4,251
  • 3
  • 31
  • 38
  • I added both namespace and scan snippet, but I get `XmlBeanDefinitionStoreException: Line 26 in XML document from ServletContext resource [/WEB-INF/applicationContext.xml] is invalid; nested exception is org.xml.sax.SAXParseException; lineNumber: 26; columnNumber: 78; cvc-complex-type.2.4.c: ` – sebastian Apr 22 '15 at 15:02
  • Can you show line 26 of your applicationContext.xml or even better the whole file? Seems like syntax error – Tony Vu Apr 23 '15 at 01:28
  • line 26 is the ` – sebastian Apr 23 '15 at 06:15
  • Sorry I miss out the schemaLocation for context. I have updated my answer. Also verify that the base-package is correct. It must point to the package which contains both your SchoolDAO and SchoolService. – Tony Vu Apr 23 '15 at 07:05