托管属性继承 [英] Managed property inheritance
问题描述
我的问题类似于此问题.我有一个 BaseBean ,目前只有一个属性,该属性被注释为@ManagedProperty
.
My problem is similar to this issue. I have a BaseBean which currently has just a single property which is annotated as a @ManagedProperty
.
但是,当我在action方法的命令按钮中访问此继承的托管属性的getter时,它将返回null.我调试并确认两次调用基础bean构造器-一次在页面加载时调用,然后在单击按钮时再次调用,如所提到的链接中所述.
However, when I access the getter of this inherited managed property in the action method a commandbutton, it returns null. I debugged and confirmed that the base bean constructr was called twice - once on page load and next on click of the button as already described in the mentioned link.
我遵循了本文选择的答案中提到的建议以及此帖子,但无济于事.
I followed the suggestions as mentioned the article's chosen answer as well as this post, but to no avail.
以下是我的代码:
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);
}
}
}
为什么在表单提交时再次调用构造函数? :/
Why would the constructor be called again on form submit ??? :/
即使在checkUserExists()
方法中,getter也会返回null,该方法是在userID字段的blur事件上通过ajax调用的.
The getter returns null even in the checkUserExists()
method which is called via ajax on the blur event of the userID field.
编辑:为ServiceLocator添加了代码.
EDIT : Added code for 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
mbean中包含@ManagedProperty
,如.
AFAIK you're trying to mix two answers: one for @RequestScoped
mbeans and other for @ViewScoped
mbeans. If you see the first link you've posted, BalusC is saying that you don't have to have @ManagedProperty
in @ViewScoped
mbeans as shown in ViewParam vs @ManagedProperty(value = "#{param.id})".
如果无法通过视图参数传递serviceLocator
,则必须寻找另一种获取该值的方法(从会话中保存/检索该值).
If you can't pass the serviceLocator
through a view param, you have to find another way to get that value (saving/retrieving it from session).
此外,请从BalusC中检查此信息,以说明为什么可以在每个请求上重新创建@ViewScoped
mbean的原因:
Also, check this info from BalusC explaining why the @ViewScoped
mbean could be recreated on every request:
简而言之:当使用绑定属性将任何UIComponent绑定到Bean时,或者在视图中使用JSTL或标签时,@ ViewScoped都会中断.在这两种情况下,bean的行为都将像是一个范围限定的请求.在我看来,第一个是一个非常重大的错误,第二个只是摆脱Facelets中整个JSTL内容的额外借口.
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.
这与JSF 2.0问题1492相关.这是相关性的一部分: 这是部分状态保存的鸡/蛋问题.在应用delta状态之前,将执行该视图以填充视图 ,因此我们看到了您所描述的行为. 在这一点上,我看不到解决此用例的明确方法. 如果必须使用视图范围的绑定,则解决方法是将javax.faces.PARTIAL_STATE_SAVING设置为false.
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.
来自
根据您的评论和编辑,您可以使用此处提供的代码访问@ApplicationScoped
mbean:
Based on your comment and edit, you can access to the @ApplicationScoped
mbean by using the code provided here:
这将是一行:
FacesContext.getCurrentInstance().getExternalContext()
.getApplicationMap().get("serviceLocator");
您必须使用该代码,因为显然@ViewScoped
bean无法接受@ManagedProperty
的注入.
You have to use that code since, apparently, the @ViewScoped
bean can't accept injection by @ManagedProperty
.
这篇关于托管属性继承的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!