Model view controller 从RequestMap中提取RequestScope CDIBean
我目前正在将Ed Burns的JSF 2.0教科书中的虚拟培训师示例应用程序从JSF托管bean转换为CDI。到目前为止,我遇到的大多数问题都与作用域和忘记正确注入有关,但现在我正在努力克服最近的一个障碍,即从RequestMap中提取CDIBean(实际上是一个实体类)。从我到目前为止所能确定的情况来看,似乎可以通过使用Map实现提供的boilerplate.get(String managedbeanname)方法非常简单地提取请求范围的托管Bean。然而,使用CDI,bean在CreationContextImp实例中被Weld包裹,我无法提取我真正想要的对象,即使我已经确认它存在于RequestMap中。我可以直接从RequestMap访问代理对象,但调用.get(“user”)后会恢复为null,我怀疑这会有多大好处,因为代理中的字段都为null 我发现BalusC的一篇文章讨论了使用一个过滤器类来访问SessionScope()中的CDIBeans,这似乎有点复杂——有更简单的解决方案吗?我也很清楚,我可能会搞砸托管Bean与CDI策略的范围界定/混合,所以请随意告诉我。。。我也有点不确定是否以这种方式直接使用实体Bean,而不是使用外观。这会不会给我带来麻烦 环境:JEE7、Glassfish 4、Netbeans 7.4、Maven EE Web原型 与托管bean的使用相关的原始代码已被注释掉 抽象支持bean类:Model view controller 从RequestMap中提取RequestScope CDIBean,model-view-controller,jsf-2,cdi,managed-bean,Model View Controller,Jsf 2,Cdi,Managed Bean,我目前正在将Ed Burns的JSF 2.0教科书中的虚拟培训师示例应用程序从JSF托管bean转换为CDI。到目前为止,我遇到的大多数问题都与作用域和忘记正确注入有关,但现在我正在努力克服最近的一个障碍,即从RequestMap中提取CDIBean(实际上是一个实体类)。从我到目前为止所能确定的情况来看,似乎可以通过使用Map实现提供的boilerplate.get(String managedbeanname)方法非常简单地提取请求范围的托管Bean。然而,使用CDI,bean在Creati
@RequestScoped
public abstract class AbstractBacking implements Serializable {
//@ManagedProperty(value="#{facesContext}")
private FacesContext facesContext;
//@ManagedProperty(value="#{requestScope}")
private Map<String, Object> requestMap;
//@ManagedProperty(value="#{sessionScope}")
private Map<String, Object> sessionMap;
@PostConstruct
public void init() {
this.facesContext = FacesContext.getCurrentInstance();
this.sessionMap = FacesContext.getCurrentInstance().getExternalContext().getSessionMap();
this.requestMap = FacesContext.getCurrentInstance().getExternalContext().getRequestMap();
}
用户实体bean:
@Entity
@Named
@Table(name = "Users")
@RequestScoped
@NamedQueries({
@NamedQuery(name = "user.getAll", query = "select u from User as u"), // @NamedQuery(name = "user.getTrainers", query = "select u from User as u where u.trainer = TRUE"),
// @NamedQuery(name = "user.getUsersForTrainerId", query = "select u from User as u where u.personalTrainerId = :theId")
})
public class User extends AbstractEntity implements Serializable {
protected String firstName;
protected String lastName;
@Temporal(TemporalType.DATE)
protected Date dob;
protected String sex;
protected String email;
private String serviceLevel = "medium";
@Column(name = "userid", nullable = false)
private String userid;
private String password;
private boolean trainer;
private List<Long> subscribedEventIds;
private Long personalTrainerId;
@OneToMany(mappedBy = "user", cascade = CascadeType.ALL)
private List<TrainingSession> sessions;
private boolean sessionsInitialized = false;
public User() {
this.init();
}
public User(String firstName, String lastName,
String sex, Date dob, String email, String serviceLevel,
String userid, String password, boolean isTrainer) {
this.init();
this.setFirstName(firstName);
this.setLastName(lastName);
this.setSex(sex);
this.setDob(dob);
this.setEmail(email);
this.setServiceLevel(serviceLevel);
this.setUserid(userid);
this.setPassword(password);
this.setTrainer(isTrainer);
}
.....
Getters/setters/etc
.....
@实体
@命名
@表(name=“Users”)
@请求范围
@命名查询({
@NamedQuery(name=“user.getAll”,query=“从用户中选择u作为u”),//@NamedQuery(name=“user.getTrainers”,query=“从用户中选择u作为u,其中u.trainer=TRUE”),
//@NamedQuery(name=“user.getUsersForTrainerId”,query=“从用户中选择u作为u,其中u.personalTrainerId=:theId”)
})
公共类用户扩展抽象实体实现可序列化{
受保护的字符串名;
受保护的字符串lastName;
@时态(TemporalType.DATE)
保护日期dob;
保护性;
受保护的字符串电子邮件;
私有字符串serviceLevel=“medium”;
@列(name=“userid”,nullable=false)
私有字符串用户标识;
私有字符串密码;
私人布尔训练器;
私有列表订阅事件ID;
私人长时间私人培训;
@OneToMany(mappedBy=“user”,cascade=CascadeType.ALL)
非公开名单会议;
私有布尔sessionInitialized=false;
公共用户(){
this.init();
}
公共用户(字符串名、字符串名、,
字符串性别、日期出生日期、字符串电子邮件、字符串服务级别、,
字符串用户ID、字符串密码、布尔值(isTrainer){
this.init();
这个.setFirstName(firstName);
此.setLastName(lastName);
这是性;
这是setDob(dob);
这个.setEmail(email);
此.setServiceLevel(服务级别);
this.setUserid(userid);
此.setPassword(密码);
这是setTrainer(isTrainer);
}
.....
接受者/接受者/等
.....
注册页面:
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml"
xmlns:h="http://java.sun.com/jsf/html"
xmlns:f="http://java.sun.com/jsf/core"
xmlns:ui="http://java.sun.com/jsf/facelets">
<body>
<ui:composition template="template.xhtml">
<ui:define name="content">
<h:form prependId="false">
<h:panelGrid columns="3">
<h:outputLabel for="fname" value="First Name:" />
<h:inputText label="First Name"
id="fname" value="#{user.firstName}"
required="true"/>
<h:message for="fname" />
<h:outputLabel for="lname" value="Last Name:" />
<h:inputText label="Last Name"
id="lname" value="#{user.lastName}"
required="true"/>
<h:message for="lname" />
<h:outputLabel for="sex" value="Sex:" />
<h:selectOneRadio label="Sex"
id="sex" value="#{user.sex}" required="true">
<f:selectItem itemLabel="Male" itemValue="male" />
<f:selectItem itemLabel="Female" itemValue="female" />
</h:selectOneRadio>
<h:message for="sex" />
<h:outputLabel for="dob" value="Date of Birth:" />
<h:panelGroup>
<h:inputText label="Date of Birth"
id="dob" value="#{user.dob}" required="true">
<f:convertDateTime pattern="MM-dd-yy" />
</h:inputText> (mm-dd-yy)
</h:panelGroup>
<h:message for="dob" />
<h:outputLabel for="email" value="Email Address:" />
<h:inputText label="Email Address"
id="email" value="#{user.email}" required="true" />
<h:message for="email" />
<h:outputLabel for="slevel" value="Service Level:" />
<h:selectOneMenu label="Service Level" id="slevel"
value="#{user.serviceLevel}">
<f:selectItem itemLabel="Medium" itemValue="medium" />
<f:selectItem itemLabel="Basic" itemValue="basic" />
<f:selectItem itemLabel="Premium" itemValue="premium" />
</h:selectOneMenu>
<h:message for="slevel" />
<h:outputLabel for="userid" value="Userid:" />
<h:inputText required="true" id="userid" value="#{user.userid}" />
<h:message for="userid" />
<h:outputLabel for="password" value="Password:" />
<h:inputSecret required="true" id="password"
validator="#{registerBacking.validatePassword1}"
value="#{requestScope.password1}" />
<h:message for="password" />
<h:outputLabel for="password2" value="Retype Password:" />
<h:inputSecret required="true" id="password2" value="#{requestScope.password2}"
validator="#{registerBacking.validatePassword2}" />
<h:message for="password2" />
</h:panelGrid>
<p><h:commandButton value="Register"
action="#{registerBacking.registerUser}" /></p>
</h:form>
</ui:define>
</ui:composition>
</body>
</html>
(年月日)
事实上,您似乎混合了CDI bean和JSF bean,老实说,您正在翻译的示例似乎很奇怪,我会将其全部扔出窗外
因为JSF也有它自己的依赖注入,除非您有一个非常特定的用例(比如ServletFilter),否则您自己不会从作用域映射中提取内容
阐明CDI使用的原理和自己“提取”的东西是一种反模式
进一步讲,CDIBean是由CDI容器(几乎所有情况下都是Weld或OWB)创建和管理的,您根本无法从externalContext检索CDIBean,因为它是JSF的上下文,是一个完全独立的东西
因此,JSF创建的实例不能在CDIBeans中注入,反之亦然。总之,正如我前面所说的,自己提取东西是不好的做法。请参阅此列表中的#10:
因此,您只需使用@Inject
(可能带有限定符)即可
注入不起作用的特殊情况的解决方法:
- CDI上下文在当前线程中不可用
- 当前实例不是CDI管理的
ContextNotActivieException
得到
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml"
xmlns:h="http://java.sun.com/jsf/html"
xmlns:f="http://java.sun.com/jsf/core"
xmlns:ui="http://java.sun.com/jsf/facelets">
<body>
<ui:composition template="template.xhtml">
<ui:define name="content">
<h:form prependId="false">
<h:panelGrid columns="3">
<h:outputLabel for="fname" value="First Name:" />
<h:inputText label="First Name"
id="fname" value="#{user.firstName}"
required="true"/>
<h:message for="fname" />
<h:outputLabel for="lname" value="Last Name:" />
<h:inputText label="Last Name"
id="lname" value="#{user.lastName}"
required="true"/>
<h:message for="lname" />
<h:outputLabel for="sex" value="Sex:" />
<h:selectOneRadio label="Sex"
id="sex" value="#{user.sex}" required="true">
<f:selectItem itemLabel="Male" itemValue="male" />
<f:selectItem itemLabel="Female" itemValue="female" />
</h:selectOneRadio>
<h:message for="sex" />
<h:outputLabel for="dob" value="Date of Birth:" />
<h:panelGroup>
<h:inputText label="Date of Birth"
id="dob" value="#{user.dob}" required="true">
<f:convertDateTime pattern="MM-dd-yy" />
</h:inputText> (mm-dd-yy)
</h:panelGroup>
<h:message for="dob" />
<h:outputLabel for="email" value="Email Address:" />
<h:inputText label="Email Address"
id="email" value="#{user.email}" required="true" />
<h:message for="email" />
<h:outputLabel for="slevel" value="Service Level:" />
<h:selectOneMenu label="Service Level" id="slevel"
value="#{user.serviceLevel}">
<f:selectItem itemLabel="Medium" itemValue="medium" />
<f:selectItem itemLabel="Basic" itemValue="basic" />
<f:selectItem itemLabel="Premium" itemValue="premium" />
</h:selectOneMenu>
<h:message for="slevel" />
<h:outputLabel for="userid" value="Userid:" />
<h:inputText required="true" id="userid" value="#{user.userid}" />
<h:message for="userid" />
<h:outputLabel for="password" value="Password:" />
<h:inputSecret required="true" id="password"
validator="#{registerBacking.validatePassword1}"
value="#{requestScope.password1}" />
<h:message for="password" />
<h:outputLabel for="password2" value="Retype Password:" />
<h:inputSecret required="true" id="password2" value="#{requestScope.password2}"
validator="#{registerBacking.validatePassword2}" />
<h:message for="password2" />
</h:panelGrid>
<p><h:commandButton value="Register"
action="#{registerBacking.registerUser}" /></p>
</h:form>
</ui:define>
</ui:composition>
</body>
</html>
@ViewScoped
@Named
public class WelcomeBean {
@Inject
private SettingManager settingManager;
private boolean allowCreateAccount;
public boolean isAllowCreateAccount() {
return allowCreateAccount;
}
// login and create account here
@PostConstruct
private void init() {
allowCreateAccount = settingManager.getBooleanSetting("registrationOpen");
}
}
<h:commandButton action="#{welcomeBean.createAccount}" value="login" disabled="#{welcomeBean.allowCreateAccount}"/>