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?
The field annotated @Autowired is null because Spring doesn't know about the copy of MileageFeeCalculator that you created with new and didn't know to autowire it.
So the answer is: No, @Autowired does not necessarily mean you must also use @Component . It may be registered with applicationContext. xml or @Configuration+@Bean .
This is called Spring Bean Autowiring. In java based configuration, all the bean methods are defined in the class with @configuration annotation. At runtime, Spring will provide bean definitions by reading those methods. Using @Autowired, the right dependency is assigned by the Spring Container.
The @Autowired annotation allows the container to automatically inject the message property from the application-context. xml file. The container searches for String bean object in the xml file and injects it here. If multiple String beans exist, then we will get an error.
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.
I had the same issue, it was due to the property name of @ManagedBean annotation.My backing bean looks like this
@Component
@ManagedBean(name="mainBean")
@SessionScoped
public class MainManagedBean{...}
As you can see, the name given to the bean (mainBean) is different to the default name (mainManagedBean) that the backing bean should have.
I have fixed the issue by setting the property name to "mainManagedBean". My bean becomes like this:
@Component
@ManagedBean(name="mainManagedBean")
@SessionScoped
public class MainManagedBean{...}
I wish this can help you
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With