但是,当我在action方法a commandbutton中访问此继承的托管属性的getter时,它返回null.我调试并确认基本bean constructr被调用了两次 – 一次在页面加载时,然后单击按钮,如上面提到的链接中所述.
我按照提到的文章所选择的答案以及this帖子的建议,但无济于事.
以下是我的代码:
public abstract class BaseBean { @ManagedProperty(value = "#{serviceLocator}") private IServiceLocator serviceLocator; public IServiceLocator getServiceLocator() { return serviceLocator; } public void setServiceLocator(IServiceLocator serviceLocator) { this.serviceLocator = serviceLocator; } }
@ManagedBean @ViewScoped public class RegistrationBean extends BaseBean implements Serializable { private static final long serialVersionUID = -6449858513581500971L; private String userID; private String password; private String firstName; private String lastName; private String email; private String addressLine1; private String addressLine2; private String city; private String state; private String pincode; private static final Logger LOGGER = LoggerFactory.getLogger(RegistrationBean.class); /* getter / setters */ public String register() { String nextPage = null; try { RegistrationDetails userDetails = ModelBuilder.populateRegistrationData(this); int registrationID = getServiceLocator().getUserService().registerUser(userDetails); LOGGER.info("Registered user successfully. Registration ID - {}", registrationID); nextPage = "success"; } catch (RegistrationException e) { LOGGER.error(e.getMessage()); } return nextPage; } public void checkUserExists() { int regID = getServiceLocator().getUserService().findUser(getUserID()); if(regID > 0) { FacesMessage message = new FacesMessage(FacesMessage.SEVERITY_WARN, "User already exists !!", null); FacesContext.getCurrentInstance().addMessage(null, message); } } }
为什么在表单提交时再次调用构造函数? :/
即使在checkUserExists()方法中,getter也会返回null,该方法是通过userID字段的blur事件上的ajax调用的.
编辑:为ServiceLocator添加了代码..
@ManagedBean @ApplicationScoped public class ServiceLocator implements IServiceLocator { private static final String USER_SERVICE = "userService"; private static final String MOVIE_SERVICE = "movieService"; @PostConstruct public void init() { final ServletContext sc = FacesUtils.getServletContext(); this.webAppContext = WebApplicationContextUtils.getRequiredWebApplicationContext(sc); this.userService = (IUserService) webAppContext.getBean(USER_SERVICE); this.movieService = (IMovieService) webAppContext.getBean(MOVIE_SERVICE); } private ApplicationContext webAppContext; private IUserService userService; private IMovieService movieService; @Override public IUserService getUserService() { return userService; } @Override public IMovieService getMovieService() { return movieService; } }AFAIK你试图混合两个答案:一个用于@RequestScoped mbeans,另一个用于@ViewScoped mbeans.如果您看到您发布的第一个链接,BalusC表示您不必在@ViewScoped mbeans中拥有@ManagedProperty,如 ViewParam vs @ManagedProperty(value = “#{param.id})”所示.
如果您无法通过视图参数传递serviceLocator,则必须找到获取该值的另一种方法(从会话中保存/检索它).
另外,请检查BalusC的这些信息,解释为什么可以在每个请求上重新创建@ViewScoped mbean:
In a nutshell: the @ViewScoped breaks when any UIComponent is bound to the bean using binding attribute or when using JSTL or tags in the view. In both cases the bean will behave like a request scoped one. The first one is in my opinion a pretty major bug, the second one is only an extra excuse to get rid of the whole JSTL stuff in Facelets.
This is related to JSF 2.0 issue 1492. Here’s an extract of relevance:
This is a chicken/egg issue with partial state saving. The view is executed to populate the view before delta state is applied, so we see the behavior you’ve described.
At this point, I don’t see a clear way to resolve this use case.
The workaround, if you must use view-scoped bindings would be setting javax.faces.PARTIAL_STATE_SAVING to false.
从
> The benefits and pitfalls of @ViewScoped
根据您的评论和编辑,您可以使用此处提供的代码访问@ApplicationScoped mbean:
> How to get application scope variable in jsf?
这将是行:
FacesContext.getCurrentInstance().getExternalContext() .getApplicationMap().get("serviceLocator");
您必须使用该代码,因为显然,@ ViewScoped bean无法接受@ManagedProperty的注入.