I tried union Spring 3(MVC) with JSF 2. I have some experience in Spring and JSF, but never tried to join them before. In the end I have 2 files
@ManagedBean(name = "userBean")
@Scope
@Component
public class someBean {
@Autowired
private TestService testService;
public void printString() {
System.out.println(testService.getString());
}
}
and
@ManagedBean(name = "studentBean")
@Scope
@Component
public class StudentBean {
@Autowired
private TestService testService;
public void printString() {
System.out.println(testService.getString());
}
}
For these file I have right configuration for spring, jsf, and web.xml. And have .xhtml page where I start printString() for 'someBean' and for 'StudentBean'. I have the NPE in first case and 'some string' in the console in second case. The reason is simple - different bean names in the Spring context and JSF. all problems finished after
@Component => @Component("userBean")
public class someBean {
In the debug I saw that
private TestService testService;
@Autowired
public void setTestService(TestService testservice) {
this.testService = testService;
}
When JSF bean is creating testService sets not null, but it is null during JSF lifecycle when
public void pringString() {
testService.blah();
}
testService is null. It is what I can't understand. Has someone deep knowledge the Spring and JSF to describe this situation in details?
Both JSF and Spring can act as bean containers. The @ManagedBean
annotation instructs the JSF managed bean facility to create a new instance of the class, and manage it under the given name. The @Component
annotation instructs the Spring ApplicationContext to create a new instance of the class, and manage it under the given name. That is, both JSF and Spring create an instance of that class, the JSF one is reachable through EL, but the Spring one gets its dependencies injected (because, being a spring annotation, @Autowired is not understood by the JSF managed bean facility).
So you have a choice: Use the JSF managed bean facility for everything (which I would not recommend, as it is rather limited), use CDI for everything (which is an option, but does not use Spring), or use Spring for everything (which I usually do), by removing the @ManagedBean
annotation, and making Spring beans accessible through EL by registering a SpringBeanFacesELResolver
in your faces-config.xml. The Spring reference manual describes this in section 19.3.1.