Решил ответить на свой вопрос, так как у меня теперь есть полнофункциональное приложение с прототипом ajax only. Это соответствует моим первоначальным требованиям, чтобы каждое представление сохранялось как одна страница .xhtml, а каждое представление имеет свой собственный компонент поддержки. Вместо дальнейшего загрязнения мой вопрос здесь упрощенный код. (Спасибо BalusC за его предыдущий ответ, который действительно помог, хотя теперь он исчез).
viewController.xhtml
<h:body>
<h:panelGroup layout="block" id="transactionControl">
<h:form>
<h4>
<p:commandLink id="mfa" ajax="true" process="@form" update="content transactionBannerContent" styleClass="menuLink" oncomplete="showTransaction01Screens();">
<h:outputText value="MFA"></h:outputText>
<f:setPropertyActionListener target="#{viewController.destinationPage}" value="MFA01"/>
</p:commandLink>
</h4>
<h4>
<p:commandLink id="inq" ajax="true" process="@form" update="content transactionBannerContent" styleClass="menuLink" oncomplete="showTransaction01Screens();">
<h:outputText value="INQ"></h:outputText>
<f:setPropertyActionListener target="#{viewController.destinationPage}" value="INQ01"/>
</p:commandLink>
</h4>
</h:form>
</h:panelGroup>
<h:panelGroup layout="block" id="content" style="border-style: solid;">
<ui:include src="#{viewController.destinationPage}.xhtml"></ui:include>
</h:panelGroup>
</h:body>
mfa01.xhtml
<h:panelGroup layout="block" id="mfa01">
<h:form id="mfa01Form">
<p>
<span>
<h:outputLabel value="UCN" for="ucn"/>
<h:inputText id="ucn" value="#{mfa01BackingBean.mfa01FormVO.ucn}" size="20"/>
</span>
</p>
<p class="submitButton">
<p:commandButton id="submitButton" value="Go" ajax="true" actionListener="#{mfa01BackingBean.doMFA01}" process="@form"
update="content transactionBannerContent" oncomplete="ajaxFinished('MFA01')">
</p:commandButton>
</p>
</h:form>
</h:panelGroup>
mfa02.xhtml
<h:panelGroup layout="block" id="mfa02">
<h:form id="mfa02Form" prependId="true">
<p>
<span style="width:25%">
<h:outputLabel value="Vessel Name"/>
<h:outputText id="vesselName"
value="#{mfa02BackingBean.mfa02FormVO.vesselName}"/>
</span>
<span style="width:75%">
<h:outputLabel value="ETA"/>
<h:outputText id="eta"
value="#{mfa02BackingBean.mfa02FormVO.eta}"/>
</span>
</p>
<p>
<span>
<h:outputLabel value="Unit ID" for="unitID"/>
<h:inputText id="unitID"
value="#{mfa02BackingBean.mfa02FormVO.unitID}"
size="20"
required="true" validator="#{mfa02BackingBean.validateData}"/>
</span>
</p>
<p class="submitButton">
<p:commandButton id="submitButton" value="Go" ajax="true" action="#{mfa02BackingBean.doMFA02}"
process="@form" update="content transactionBannerContent" oncomplete="ajaxFinished('MFA02')">
<f:param name="randomString" value="AAA"/>
</p:commandButton>
</p>
</h:form>
</h:panelGroup>
ViewController.java
package com.mcpplc.supportclient.webapp.managedBeans;
import javax.faces.bean.*;
import java.io.Serializable;
@ManagedBean (name = "viewController")
@SessionScoped
public class ViewController implements Serializable
{
String destinationPage = "splash";
String transactionID;
public String getDestinationPage()
{
return destinationPage;
}
public void setDestinationPage( String destinationPage )
{
this.destinationPage = destinationPage;
transactionID = destinationPage.toUpperCase();
}
public String getTransactionID()
{
return transactionID;
}
public void setTransactionID( String transactionID )
{
this.transactionID = transactionID;
}
}
mfa01BackingBean.java
package com.mcpplc.supportclient.webapp.managedBeans;
import com.mcpplc.supportclient.webapp.Utils.JSFUtils;
import com.mcpplc.supportclient.webapp.valueObjects.*;
import javax.annotation.PostConstruct;
import javax.faces.bean.ManagedBean;
import javax.faces.bean.ManagedProperty;
import javax.faces.bean.RequestScoped;
@ManagedBean
@RequestScoped
public class Mfa01BackingBean
{
@ManagedProperty(value = "#{viewController}")
private ViewController viewController;
private ImportConsignmentVO importConsignmentVO;
private VoyageVO voyageVO;
private Mfa01FormVO mfa01FormVO;
private Mfa02FormVO mfa02FormVO;
@PostConstruct
public void init()
{
mfa01FormVO = new Mfa01FormVO();
}
public void doMFA01()
{
//pretend to get VOs
importConsignmentVO = new ImportConsignmentVO();
voyageVO = new VoyageVO();
//set some VO stuff
if ( mfa01FormVO.getUcn().equalsIgnoreCase( "123" ) )
{
importConsignmentVO.setUnitID("AJF1");
voyageVO.setVesselName("Ever Glade");
}
else {
importConsignmentVO.setUnitID("ZZZ1");
voyageVO.setVesselName("Ever Champion");
}
importConsignmentVO.setType("41G1");
importConsignmentVO.setWeight("25000");
voyageVO.setEta("01/01/2011");
constructMFA02Form();
viewController.setDestinationPage("mfa02");
}
private void constructMFA02Form()
{
mfa02FormVO = new Mfa02FormVO();
mfa02FormVO.setUnitID(importConsignmentVO.getUnitID());
mfa02FormVO.setType(importConsignmentVO.getType());
mfa02FormVO.setWeight(importConsignmentVO.getWeight());
mfa02FormVO.setMfaRef("12345");
mfa02FormVO.setVesselName(voyageVO.getVesselName());
mfa02FormVO.setEta(voyageVO.getEta());
JSFUtils.addObjectToRequest(Mfa02FormVO.class.getName(), mfa02FormVO);
}
.....getters&setters
}
mfa02BackingBean.java
package com.mcpplc.supportclient.webapp.managedBeans;
import com.mcpplc.supportclient.webapp.Utils.JSFUtils;
import com.mcpplc.supportclient.webapp.valueObjects.*;
import java.io.Serializable;
import java.util.*;
import javax.annotation.PostConstruct;
import javax.faces.application.FacesMessage;
import javax.faces.bean.ManagedBean;
import javax.faces.bean.ManagedProperty;
import javax.faces.bean.ViewScoped;
import javax.faces.component.UIComponent;
import javax.faces.component.UIInput;
import javax.faces.context.FacesContext;
@ManagedBean
@ViewScoped
public class Mfa02BackingBean implements Serializable
{
@ManagedProperty(value = "#{viewController}")
private ViewController viewController;
private Mfa02FormVO mfa02FormVO;
@PostConstruct
public void init()
{
mfa02FormVO = (Mfa02FormVO) JSFUtils.getObjectFromRequest(Mfa02FormVO.class.getName());
}
public String doMFA02()
{
viewController.setDestinationPage("mfa01");
return "viewController";
}
public void validateData ( FacesContext facesContext, UIComponent uiComponentToValidate, Object value)
{
String message = "";
String requestData = (String) value;
if ( !requestData.contains( "0" ) )
{
((UIInput )uiComponentToValidate).setValid( false );
message = "Incorrect format for Unit ID";
facesContext.addMessage( uiComponentToValidate.getClientId(facesContext), new FacesMessage(message) );
//JSFUtils.addObjectToRequest(Mfa02FormVO.class.getName(), mfa02FormVO);
}
}
.....getters&setters
}
Mfa01FormVO и Mfa02FormVO - просто объекты значений с геттерами и сеттерами
Основной проблемой, с которой я столкнулся, было сохранение данных объекта между запросами. Когда я перехожу из mfa01 в mfa02, я делаю поиск, заполняю некоторые vos и затем передаю форму vo во Flash. Затем экран Mfa02 создается со значениями vo. Большая проблема у меня была, когда произошла ошибка проверки на mfa02. Первоначально у меня был установлен bean-компонент requestScoped, однако я потерял объект vo после неудачной проверки. Это было несмотря на то, что я добавил объект обратно во вспышку, как только я получил его от Flash. Странно было то, что не было никакой гарантии, что я потеряю объект. Если бы я щелкнул снова, то я бы сразу потерял объект, но иногда он оставался бы еще на один щелчок, а затем я бы его потерял.
Затем я изменил mfa02backingbean на ViewScoped. Однако, поскольку это полностью ajax, mfa02backingbean не было повторно инициализировано при последующих запросах. Это означало, что все значения, которые я установил в первом запросе, будут отображаться всегда. В конце концов я решил эту проблему, используя ViewScoped и изменив Командную кнопку, чтобы использовать Action, а не ActionListener, и в этом методе я возвращаю строку «viewController». Я предполагаю, что жизненный цикл думает, что я возвращаюсь к новому представлению, поэтому он очищает все, что осталось в окне обзора.
Надеюсь, этот код поможет всем, кто ищет подобное решение.