Integrating JSF managed bean annotations with Spring Boot

走远了吗. 提交于 2020-01-03 03:01:11

问题


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

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!