I'm currently in the process of converting the Virtual Trainer example app from Ed Burns' textbook on JSF 2.0 from JSF Managed Beans to CDI. Most of the problems I've encountered so far have been related to scoping and forgetting to inject correctly but now I'm struggling to overcome the most recent hurdle that relates to extracting a CDI Bean (actually an entity class) from the RequestMap. From what I've been able to ascertain so far, it would appear that a request-scoped Managed Bean can be extracted very simply by using the boilerplate .get(String managedbeanname) method provided by the Map implementation. However, with CDI the bean is wrapped by Weld in a CreationalContextImp instance and I can't extract the object I'm really after even though it I've confirmed it is present in the RequestMap. I can get as far as briefly accessing a proxy object from RequestMap but this reverts to null after calling .get("user") and I doubt it would do much good anyway as the fields in the proxy are all nulled.
I've found a post from BalusC that discusses using a filter class to access CDI beans held in SessionScope (How do I get a SessionScoped CDI bean from inside a Filter?) It seems a little bit involved - is there a simpler solution? I'm also very aware that I may be mucking up scoping/mixing of Managed Bean vs CDI strategies so feel free to set me straight... I am also a little uncertain about using an Entity Bean directly in this fashion rather than using a Facade. Is this causing me/likely to cause me a problem later?
Environment: JEE7, Glassfish 4, Netbeans 7.4, Maven EE Web Archetype Original code relating to use of Managed Beans has been commented out.
Abstract backing bean class:
@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();
}
Registration page backing bean:
@Named
@RequestScoped
public class RegisterBacking extends AbstractBacking implements Serializable {
private Object password1;
@Inject
private User newUser;
public String registerUser() {
String result = null;
User newUser = (User) getRequestMap().get("user");
// set the password into the user, because we know the validator was
// successful if we reached here.
newUser.setPassword((String) getRequestMap().get("password1"));
try {
UserRegistry.getCurrentInstance().addUser(newUser);
// Put the current user in the session
setCurrentUser(newUser);
// redirect to the main page
result = "/user/allEvents?faces-redirect=true";
} catch (EntityAccessorException ex) {
getFacesContext().addMessage(null,
new FacesMessage("Error when adding user"
+ ((null != newUser) ? " " + newUser.toString() : "") + "."));
}
return result;
}
User entity 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
.....
Registration page:
<!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>