Question

I am new to Spring and trying to learn @Autowired magic in SPring MVC. I was trying out a demo application using the @ModelAttribute method and @Autowired. Every time I am getting null which means @Autowired is not happening properly. Below is what I tried:

Controller

@Controller
public class ModelAttributeAutoWiredController {

@Autowired
private Employee empl;

public void setEmpl(Employee empl) {
    this.empl = empl;
}

@RequestMapping(value="/home")
public ModelAndView returnhome(){

    ModelAndView modelView = new ModelAndView("home");
    System.out.println("Employee First Name: " + empl.getFirstName()); // NULL
    return modelView;
}

@RequestMapping(value="/index")
public ModelAndView returnindex(){

    ModelAndView modelView = new ModelAndView("index");
    System.out.println("Employee Last Name: " + empl.getLastName()); // NULL
    return modelView;
}

@ModelAttribute("empl")
public Employee populateEmployee(){
    Employee empl = new Employee();
    empl.setFirstName("XXX");
    empl.setLastName("YYY");
    return empl;
}

}

Employee

@Component
public class Employee {

private String firstName;
private String lastName;
public String getFirstName() {
    return firstName;
}
public void setFirstName(String firstName) {
    this.firstName = firstName;
}
public String getLastName() {
    return lastName;
}
public void setLastName(String lastName) {
    this.lastName = lastName;
}
}

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

<context:annotation-config />
<context:component-scan
    base-package="com.pack" />

<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/pages/" />
    <property name="suffix" value=".jsp" />
</bean>
</beans>

Can someone please help me out in the above code and make me understand why @Autowired is not working?

Was it helpful?

Solution

You're confusing several Spring concepts here.

First, @Component is used for program components, generally objects that provide some service that other pieces of the program need. It is not intended for data objects such as your Employee class, and data objects that are runtime data (and not configuration objects) shouldn't be autowired, they should be passed in to the specific method calls that operate on them.

@ModelAttribute tells Spring that it should add whatever is being annotated to the MVC Model object so that it's available to the controller and view. This has nothing to do at all with @Autowired.

Here's what's happening in your code:

  • Your Employee class is annotated @Component, so Spring creates a singleton bean and registers it in the context. This bean never has its fields set, so they're null, but the bean itself exists, so it's wired into your controller's empl field. This is why you don't get a NullPointerException, which you would if the autowiring really weren't working.
  • Your @ModelAttribute is evaluated by Spring and added to the Model for each request. However, you never pass this model to any of your controllers, so they never see it.
  • Your controller methods create new, empty ModelAndView objects with nothing in them.
  • They then read the completely different, empty Employee object that was injected into empl and print out the null value on the fields (but don't throw NullPointerExceptions because the autowiring succeeded).

OTHER TIPS

Please check this: http://www.mkyong.com/spring-mvc/spring-3-mvc-and-xml-example/

You'll need the <mvc:annotation-driven/> and also the <context:component-scan base-package="com.your.package" /> in your context.xml file.

Looks like this isn't possible and if you think about it, it doesn't make much sense to have a @ModelAttribute as an instance variable. Please read here to get a better understanding.

@Autowired is not intended for the domain objects like Employee. In your case Spring creates an Employee object using the default constructor, so its lastname is null. Spring creates the Employee object because of @Component annotation on the Employee class, it has nothing to do with the @ModelAttribute. The method annotated with @ModelAttributes instructs Spring to create another Employee object and inject it to the Model object that you don't have to create by yourself. Just return "index" String from your "returnhome" method. For debugging, you may add @ModelAttribute Employee e as an argument to your "returnhome" method.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top