问题
I use Spring boot with JSF 2.2. My problem is that I can create @ManagedBean
from javax.annotation.ManagedBean
and it is working in my index.xhtml when I run the app, but when I want to use javax.faces.bean.ManagedBean
is not displaying the value. What's the difference between those two? Why I can't use the javax.faces.bean.ManagedBean
? ( I don't have web.xml file, all is configured in classes)
回答1:
The javax.annotation.*
annotations are meant to be a move from the classic JSF annotations to a CDI approach. The Spring Framework has the ability to read some CDI annotations, so that could be the reason why this annotation "works". However, the trend in CDI is to use @Named
, overall.
In a Spring Boot application, it's Spring the one scanning your annotations, not JSF. So, even you could think that the application works with @ManagedBean
, you'll see that the @*Scoped
annotations are useless, because all the created beans happen to be singletons, which is Spring's default scope.
In the end the choice I made was to use vanilla Spring annotations and scopes. As Spring lacks the JSF view scope, also a custom scope to emulate it.
MyBean.java:
@Component
@Scope("view")
public class MyBean {
//Here it goes your logic
}
ViewScope.java:
public class ViewScope implements Scope {
@Override
public Object get(String name, ObjectFactory<?> objectFactory) {
Map<String, Object> viewMap = FacesContext.getCurrentInstance().getViewRoot().getViewMap();
if (viewMap.containsKey(name)) {
return viewMap.get(name);
} else {
Object object = objectFactory.getObject();
viewMap.put(name, object);
return object;
}
}
@Override
public String getConversationId() {
return null;
}
@Override
public void registerDestructionCallback(String arg0, Runnable arg1) {
}
@Override
public Object remove(String name) {
return FacesContext.getCurrentInstance().getViewRoot().getViewMap().remove(name);
}
@Override
public Object resolveContextualObject(String arg0) {
return null;
}
}
Register the view scope with a CustomScopeConfigurer:
@Bean
public static CustomScopeConfigurer viewScope() {
CustomScopeConfigurer configurer = new CustomScopeConfigurer();
configurer.setScopes(
new ImmutableMap.Builder<String, Object>().put("view", new ViewScope()).build());
return configurer;
}
Finally, do not forget to add the Spring EL resolver in your faces-config.xml to make the Spring beans available through EL expressions:
<application>
<el-resolver>org.springframework.web.jsf.el.SpringBeanFacesELResolver</el-resolver>
</application>
See also:
- Why are there different bean management annotations
- Backing beans (@ManagedBean) or CDI Beans (@Named)?
- Configuring Spring Boot with JSF
来源:https://stackoverflow.com/questions/38292456/integrating-jsf-managed-bean-annotations-with-spring-boot