我正在尝试实施流程。问题是我没有设置我的flowcoped bean属性。一点都没!当我导航到流程中的下一个视图时,永远不会激活setter。我正在使用Mojarra jsf实现的2.2.13版本。
我使用“值绑定”设置值,即
<h:inputText .... value="#{individualRegistration.firstname}" .../>
我正在使用CDI,即@Named与@FlowScoped一起使用。
然后bean本身可见,因为我的导航按钮使用了flowcoped bean中定义的方法,我可以正常导航。
流程本身是以编程方式定义的,即@Produces @FlowDefinition
UIComponents包含在
中<h:form>
虽然它们进一步包含在表单中的一些样式div中。
导航到下一个视图(此时我希望更新bean),我正在使用
<h:commandLink .../>
我在Payara 4.1.172(基本上是Glassfish 4.1)。
非常感谢。被困了一个星期!
这是bean代码。
import java.io.Serializable;
import java.util.Date;
import java.util.Iterator;
import java.util.LinkedHashMap;
import java.util.Locale;
import java.util.Map.Entry;
import javax.annotation.PostConstruct;
import javax.ejb.PostActivate;
import javax.faces.context.FacesContext;
import javax.faces.flow.FlowScoped;
import javax.inject.Named;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
*
*/
@Named("individualRegistration")
@FlowScoped("individual")
public class Individual implements Serializable{
private static final long serialVersionUID=3L;
private String gender="Male",
firstname=null,
initials=null,
lastname=null,
uniqueIdentifierType=null,
identifier = null,
username=null,
email=null,
mobile=null;
private Date dateOfBirth=null;
private Address address=null;
static final Logger LOG = LoggerFactory.getLogger(Individual.class);
private static final String INTERNATIONALISATION_BUNDLE_BASE_NAME = "com.netparadigm.security.registry.internationalisation.registration";
/**
* To help determine the next or previous view in processing the flow
*/
private static final LinkedHashMap<String, String> FLOW_MAP;
static{
FLOW_MAP = new LinkedHashMap<>();
FLOW_MAP.put("identification", "individual-flow-basics");
FLOW_MAP.put("contacts", "individual-flow-contacts");
FLOW_MAP.put("social", "individual-flow-social-networks");
FLOW_MAP.put("confirm", "individual-flow-confirmation");
FLOW_MAP.put("terms", "individual-flow-terms");
}
public Individual(){
}
@PostConstruct
public void init(){
LOG.trace("Initialising the individual flow");
this.setInternationalisation();
}
@PostActivate
public void activated(){
LOG.trace("Individual registration flow bean post activation");
}
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
public String getEmail() {
return email;
}
public void setEmail(String email) {
this.email = email;
}
public String getMobile() {
return mobile;
}
public void setMobile(String mobile) {
this.mobile = mobile;
}
public String getGender() {
return gender;
}
public void setGender(String gender) {
this.gender = gender;
}
public String getFirstname() {
return firstname;
}
public void setFirstname(String firstname) {
this.firstname = firstname;
}
public String getInitials() {
return initials;
}
public void setInitials(String initials) {
this.initials = initials;
}
public String getLastname() {
return lastname;
}
public void setLastname(String lastname) {
this.lastname = lastname;
}
public String getUniqueIdentifierType() {
return uniqueIdentifierType;
}
public void setUniqueIdentifierType(String uniqueIdentifierType) {
this.uniqueIdentifierType = uniqueIdentifierType;
}
public String getIdentifier() {
return identifier;
}
public void setIdentifier(String identifier) {
this.identifier = identifier;
}
public Date getDateOfBirth() {
return dateOfBirth;
}
public void setDateOfBirth(Date dateOfBirth) {
this.dateOfBirth = dateOfBirth;
}
public Address getAddress() {
return address;
}
public void setAddress(Address address) {
this.address = address;
}
public String exit(){
return "/registration/individual/index";
}
/***
* Navigate to the next view in the individual registration flow
* @param currentContext
* @return
*/
public String next(String currentContext){
String nextView = "individual-flow-entry";
Iterator <Entry<String, String>> iterator;
if(currentContext!=null && !currentContext.equalsIgnoreCase("")){
if(Individual.FLOW_MAP.containsKey(currentContext)){
iterator = Individual.FLOW_MAP.entrySet().iterator();
while(iterator.hasNext()){
Entry<String, String> entry = iterator.next();
if(entry.getKey().equalsIgnoreCase(currentContext)){
if(iterator.hasNext()){
nextView = iterator.next().getValue();
break;
}else{
nextView = Individual.FLOW_MAP.values().stream().findFirst().toString();
}
}
}
}
}
return nextView;
}
/**
*
* @param currentContext
* @return
*/
public String Previous(String currentContext){
String previousView = "individual-flow-entry";
Iterator <Entry<String, String>> iterator;
if(currentContext!=null && !currentContext.equalsIgnoreCase("")){
if(Individual.FLOW_MAP.containsKey(currentContext)){
iterator = Individual.FLOW_MAP.entrySet().iterator();
while(iterator.hasNext()){
Entry<String, String> entry = iterator.next();
if(entry.getKey().equalsIgnoreCase(currentContext)){
break;//Entry found, exit with current value of the previous view
}else{
previousView = entry.getValue();//read the current view into the previous handle
}
}
}
}
return previousView;
}
/**
* Load a resource bundle given its basename
* @param basename
* @return
*/
public void setInternationalisation(){
Locale locale = FacesContext.getCurrentInstance().getViewRoot().getLocale();
MessageBundleFactory messageFactory = new MessageBundleFactory(INTERNATIONALISATION_BUNDLE_BASE_NAME, locale, this.getClass().getClassLoader());
try{
FacesContext.getCurrentInstance().getExternalContext().getRequestMap().put("registrationMessages", messageFactory.getBundle());
}catch(Exception exception){
LOG.error(exception.getMessage());
}
}
}
以下是视图的代码!
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml"
xmlns:ui="http://xmlns.jcp.org/jsf/facelets"
xmlns:h="http://xmlns.jcp.org/jsf/html"
xmlns:f="http://xmlns.jcp.org/jsf/core">
<ui:composition template="/WEB-INF/templates/template.xhtml">
<ui:define name="head">
<ui:include src="/resources/includes/head.xhtml" />
<link rel="stylesheet" type="text/css" href="/resources/checkbox/bower_components/Font-Awesome/css/font-awesome.css"/>
<link rel="stylesheet" type="text/css" href="/resources/checkbox/demo/build.css"/>
</ui:define>
<ui:define name="body">
<ui:include src="/resources/includes/header.xhtml">
<ui:param name="flowContext" value="identification" />
</ui:include>
<div class="content-pane">
<div id="registration-individual-identification" class="registration-flow-pane">
<h3>basic personal identification details</h3>
<h:form id="frmIndividualBasicInformation">
<f:passThroughAttribute name="name" value="frmIndividualBasicInformation" />
<div class="input-group">
<span class="input-group-addon"><i class="glyphicon glyphicon-envelope"></i></span>
<h:inputText id="emlPrimary" class="form-control" value="#{individualRegistration.email}">
<f:passThroughAttribute name="type" value="email" />
<f:passThroughAttribute name="name" value="emlPrimary" />
<f:passThroughAttribute name="placeholder" value="Email Address" />
</h:inputText>
</div>
<div class="input-group">
<span class="input-group-addon"><i class="glyphicon glyphicon-user"></i></span>
<input id="txtFirstname" type="text" class="form-control" name="txtFirstname" value="#{individualRegistration.firstname}" placeholder="First Name" />
</div>
<div class="input-group">
<span class="input-group-addon"><i class="glyphicon glyphicon-user"></i></span>
<input id="txtLastname" type="text" class="form-control" name="txtLastname" value="#{individualRegistration.lastname}" placeholder="Last Name" />
</div>
<div class="input-group">
<span class="input-group-addon"><i class="glyphicon glyphicon-user"></i></span>
<h:inputText id="txtUsername" class="form-control" value="#{individualRegistration.username}">
<f:passThroughAttribute name="name" value="txtUsername" />
<f:passThroughAttribute name="placeholder" value="Prefered User Name" />
</h:inputText>
</div>
<fieldset class="fieldset-input-group">
<legend>Gender</legend>
<div class="radio radio-inline">
<input type="radio" id="optMale" value="Male" name="optGender" checked="checked" />
<label for="optMale">Male</label>
</div>
<div class="radio radio-inline">
<input type="radio" id="optFemale" value="Female" name="optGender" />
<label for="optFemale">Female</label>
</div>
</fieldset>
<div class="input-group">
<span class="input-group-addon"><i class="glyphicon glyphicon-calendar"></i></span>
<h:inputText id="dteDOB" class="form-control" value="#{individualRegistration.dateOfBirth}">
<f:convertDateTime pattern="dd-mm-yyyy" />
<f:passThroughAttribute name="name" value="dteDOB" />
<f:passThroughAttribute name="placeholder" value="dd/mm/yyyy" />
</h:inputText>
</div>
<div class="input-group">
<span class="input-group-addon"><i class="glyphicon glyphicon-king"></i></span>
<input id="txtCountry" type="text" class="form-control" name="txtCountry" value="#{individualRegistration.address.country}" placeholder="Country" />
</div>
<div class="command-bar row">
<div class="col-lg-6">
</div>
<div class="col-lg-6">
<h:commandLink class="btn btn-primary" action="#{individualRegistration.next('identification')}">Next <span class="glyphicon glyphicon-triangle-right"></span></h:commandLink>
</div>
</div>
<script type="text/javascript">
function changeState(el) {
if (el.readOnly) el.checked=el.readOnly=false;
else if (!el.checked) el.readOnly=el.indeterminate=true;
}
</script>
</h:form>
</div>
</div>
<ui:include src="/resources/includes/minimal-footer.xhtml" />
</ui:define>
</ui:composition>
</html>