Search code examples
springautowiredpostconstruct

@PostConstuct does not appear to work and @autowire gives an error


I am new to spring and am creating a spring web application. The application I'm writing has a Class PreLoadService. In this class is a method defined with @PostConstruct that calls a DAO to load the data. The DAO instance is declared in the class with the @autowired.

The Controller for the JSP then declares an instance of the PreLoadService and calls the getter to retrieve the data that should have been loaded in the @PostConstruct. The data is never loaded and an exception is also thrown on the @autowired.

Since this did not work I tried a simple Hello World version to write a message and received the same issue. I will post this. In the WEB_INF folder I have a web.xml and a spring3-servlet.xml. In the SRC folder I have an applicationContext.xml. I am running on Tomcat 7.

Web.xml

<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns="http://java.sun.com/xml/ns/javaee"
xmlns:web="http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee       http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"
id="WebApp_ID" version="2.5">
<display-name>Spring3MVC</display-name>
<context-param>
    <param-name>webAppRootKey</param-name>
    <param-value>root.webpath</param-value>
</context-param>

<welcome-file-list>
    <welcome-file>index.jsp</welcome-file>
</welcome-file-list>
<servlet>
    <servlet-name>spring3</servlet-name>
    <servlet-class>
        org.springframework.web.servlet.DispatcherServlet
    </servlet-class>
    <load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
    <servlet-name>spring3</servlet-name>
    <url-pattern>*.html</url-pattern>
     <url-pattern>/</url-pattern>
</servlet-mapping></web-app>

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

 <!--will allow Spring to load all the components from package and all its child packages-->    
<mvc:annotation-driven />
<context:component-scan
    base-package="com.nikki.spring3.controller" />
<!-- will resolve the view and add prefix string /WEB-INF/jsp/ and suffix .jsp to the view in ModelAndView.  -->       
<bean id="viewResolver"
    class="org.springframework.web.servlet.view.UrlBasedViewResolver">
    <property name="viewClass"
        value="org.springframework.web.servlet.view.JstlView" />
    <property name="prefix" value="/WEB-INF/jsp/" />
    <property name="suffix" value=".jsp" />
</bean>
</beans>

applicationContext.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: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-3.0.xsd
    http://www.springframework.org/schema/mvc 
    http://www.springframework.org/schema/mvc/spring-mvc-3.0.xsd
    http://www.springframework.org/schema/context
    http://www.springframework.org/schema/context/spring-context-3.0.xsd">
   <mvc:annotation-driven/>   
 <context:component-scan base-package="com.nikki.spring3">
 <context:exclude-filter    expression="org.springframework.stereotype.Controller" type="annotation"/>
</context:component-scan> 
<bean id="helloWorldService" 
    class="com.nikki.spring3.beansit.HelloWorldService">
    <property name="message" value="Preloading Init Config and Data" />

HelloWorldService

public class HelloWorldService {

 private String message;

   public void setMessage(String message){
      this.message  = message;
   }

   public String getMessage(){
      System.out.println("Your Message : " + message);
      return message;
   }
   @PostConstruct
   public void init(){
      System.out.println("Bean is going through init.");
   }
   @PreDestroy
   public void destroy(){
      System.out.println("Bean will destroy now.");
   }
}

HelloWorldController

 @Controller
public class HelloWorldController {
    @Autowired 
    HelloWorldService helloWorldService;
/* RequestMapping annotation tells Spring that this Controller should
 *  process all requests beginning with /hello in the URL path. 
 *  That includes /hello/* and /hello.html.
 */
    @RequestMapping("/hello")
    public ModelAndView helloWorld() {

        String message =helloWorldService.getMessage();
                //"Hello World, Spring 3.0!";
        return new ModelAndView("hello", "message", message);
    }
}

Error Message

Exception
SEVERE: StandardWrapper.Throwable  org.springframework.beans.factory.BeanCreationException: 
Error creating bean with name 'org.springframework.web.servlet.mvc.annotation.DefaultAnnotationHandlerMapping#0': 
Initialization of bean failed; nested exception is org.springframework.beans.factory.BeanCreationException: 
Error creating bean with name 'helloWorldController': 
Injection of autowired dependencies failed; nested exception is org.springframework.beans.factory.BeanCreationException:
Could not autowire field: com.nikki.spring3.beansit.HelloWorldService com.nikki.spring3.controller.HelloWorldController.helloWorldService; 
nested exception is org.springframework.beans.factory.NoSuchBeanDefinitionException: 
No matching bean of type [com.nikki.spring3.beansit.HelloWorldService] 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.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:521)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:450)

I appreciate any help. Thanks.


Solution

  • If you have config files other than xxx-servlet.xml you need to let know spring that these files exists. To do that you have to use contextConfigLocation along with ContextLoadListener. Try to add the following lines in your web.xml. If the applicationContext.xml exists in WEB-INF folder of the project use the following.

    <context-param>
        <param-name>contextConfigLocation</param-name>
        <param-value>/WEB-INF/applicationContext.xml</param-value>
    </context-param>
    
    <listener>
       <listener-class>
            org.springframework.web.context.ContextLoaderListener
       </listener-class>
    </listener>
    

    I think you had your applicationContext.xml under src folder. In that case use as below

    <context-param>
        <param-name>contextConfigLocation</param-name>
        <param-value>classpath*:applicationContext.xml</param-value>
    </context-param>