Refreshing a Listing on an Edit Screen
sandman202 Jan 14, 2009 12:00 AMUsing Richfaces 3.2.2, Seam 2.1.1, JBoss 4.2.3 and MySQL. The Listing, detail and edit screens are like those described in the seam in action
.
I have an edit screen called InFilesEdit.xhtml which I use to validate and post an imported file. In This case, it is a collection of city-state-zip records. The importing, validation and posting is working fine. The problem I am having is once I validate or post the records, the listing of city-state-zip records does not get refreshed.
I have tried using an event/observer and afterTransactionSuccess, but it does not seem to refresh the tab.
InFileEdit.xhtml
<ui:composition xmlns="http://www.w3.org/1999/xhtml"
xmlns:s="http://jboss.com/products/seam/taglib"
xmlns:ui="http://java.sun.com/jsf/facelets"
xmlns:f="http://java.sun.com/jsf/core"
xmlns:h="http://java.sun.com/jsf/html"
xmlns:a="http://richfaces.org/a4j"
xmlns:rich="http://richfaces.org/rich"
template="/layout/template.xhtml">
<ui:define name="body">
<h:form id="inFilesForm" styleClass="edit" enctype="multipart/form-data">
<rich:panel>
<f:facet name="header">#{inFilesHome.managed ? 'Edit' : 'Add'} InFiles</f:facet>
<s:decorate id="nameDecoration" template="/layout/display.xhtml">
<ui:define name="label">Name</ui:define>
<h:inputTextarea id="name"
cols="80"
rows="3"
disabled="true"
value="#{inFilesHome.instance.name}"/>
</s:decorate>
<s:decorate id="typeDecoration" template="/layout/edit.xhtml">
<ui:define name="label">Type</ui:define>
<h:selectOneMenu id="inFilesType"
styleClass="selectOneMenu"
value="#{inFilesHome.instance.type}"
disabled="true">
<s:selectItems value="#{inFilesHome.inFileTypes}" var="inFilesType" label="#{inFilesType.value}"
noSelectionLabel=""/>
<s:convertEnum />
</h:selectOneMenu>
</s:decorate>
<s:decorate id="statusDecoration" template="/layout/edit.xhtml">
<ui:define name="label">Status</ui:define>
<h:selectOneMenu id="inFilesStatus"
styleClass="selectOneMenu"
value="#{inFilesHome.instance.status}"
disabled="true">
<s:selectItems value="#{inFilesHome.inFileStatuses}" var="inFilesStatus" label="#{inFilesStatus.value}"
noSelectionLabel=""/>
<s:convertEnum />
</h:selectOneMenu>
</s:decorate>
<s:decorate id="createdOnDecoration" template="/layout/display.xhtml">
<ui:define name="label">Created On</ui:define>
<rich:calendar id="createdOn"
value="#{inFilesHome.instance.createdOn}"
required="true"
disabled="true"
datePattern="MM/dd/yyyy"
event="onblur"
reRender="createdOnDecoration"
style="width: auto;">
</rich:calendar>
</s:decorate>
<div style="clear:both">
<span class="required">*</span>
required fields
</div>
</rich:panel>
<div class="actionButtons">
<h:commandButton id="save"
value="Save"
action="#{inFilesHome.persist}"
rendered="#{!inFilesHome.managed}"/>
<h:commandButton id="delete"
value="Delete"
action="#{inFilesHome.remove}"
immediate="true"
rendered="#{inFilesHome.managed}"/>
<s:button propagation="end"
id="done"
value="Done"
view="/admin/InFiles.xhtml"
rendered="#{inFilesHome.managed}"/>
<s:button propagation="end"
id="cancel"
value="Cancel"
view="/admin/#{empty inFilesFrom ? 'InFilesList' : inFilesFrom}.xhtml"
rendered="#{!inFilesHome.managed}"/>
<h:commandButton id="validate"
value="Validate"
action="#{inFilesHome.validate}"
rendered="#{inFilesHome.managed}"
disabled="#{!inFilesHome.readyForValidation}"/>
<h:commandButton id="post"
value="Post"
action="#{inFilesHome.post}"
rendered="#{inFilesHome.managed}"
disabled="#{!inFilesHome.readyForPosting}"/>
</div>
</h:form>
<rich:tabPanel switchType="ajax">
<rich:tab label="InCityStateZip">
<ui:include src="/admin/InCityStateZipTable.xhtml">
<ui:param name="inCityStateZipFrom" value="InFilesEdit"/>
</ui:include>
</rich:tab>
<rich:tab label="Errors">
<ui:include src="InErrorsTable.xhtml">
<ui:param name="inErrorsFrom" value="InFilesEdit"/>
</ui:include>
</rich:tab>
</rich:tabPanel>
</ui:define>
</ui:composition>
InCityStateZipList.java
@Name("inCityStateZipList")
public class InCityStateZipList extends EntityQuery<InCityStateZip>
{
private static final long serialVersionUID = -3524846754525228492L;
private static final String[] RESTRICTIONS = {
"lower(inCityStateZip.country) like concat(lower(#{inCityStateZipList.inCityStateZip.country}),'%')",
"lower(inCityStateZip.city) like concat(lower(#{inCityStateZipList.inCityStateZip.city}),'%')",
"lower(inCityStateZip.province) like concat(lower(#{inCityStateZipList.inCityStateZip.province}),'%')",
"lower(inCityStateZip.zipcode) like concat(lower(#{inCityStateZipList.inCityStateZip.zipcode}),'%')",
"lower(inCityStateZip.county) like concat(lower(#{inCityStateZipList.inCityStateZip.county}),'%')",
"inCityStateZip.status = #{inCityStateZipList.inCityStateZip.status}",
"inCityStateZip.inFiles.id = #{inFilesHome.inFilesId}",
};
private InCityStateZip inCityStateZip = new InCityStateZip();
public InCityStateZipList() {
this.setMaxResults(25);
this.setEjbql("select inCityStateZip from InCityStateZip inCityStateZip");
this.setOrder("inCityStateZip.status asc");
this.setRestrictionExpressionStrings(Arrays.asList(RESTRICTIONS));
}
public InCityStateZip getInCityStateZip() {
return inCityStateZip;
}
public InFileStatus[] getInFileStatuses() {
return InFileStatus.values();
}
}
InCityStateZipTable.xhtml
<a4j:form id="inCityStateZipTableForm"
xmlns="http://www.w3.org/1999/xhtml"
xmlns:s="http://jboss.com/products/seam/taglib"
xmlns:ui="http://java.sun.com/jsf/facelets"
xmlns:f="http://java.sun.com/jsf/core"
xmlns:h="http://java.sun.com/jsf/html"
xmlns:a4j="http://richfaces.org/a4j"
xmlns:rich="http://richfaces.org/rich">
<div class="association" id="inCityStateZips">
<h:outputText value="No city-state-zips exists"
rendered="#{empty inCityStateZipList.resultList}"/>
<rich:dataTable id="inCityStateZipList"
var="_inCityStateZip"
value="#{inCityStateZipList.resultList}"
rendered="#{not empty inCityStateZipList.resultList}">
<h:column>
<f:facet name="header">
<a4j:htmlCommandLink styleClass="columnHeader" reRender="inCityStateZipList"
value="Country #{inCityStateZipList.order=='country asc' ? messages.down : ( inCityStateZipList.order=='country desc' ? messages.up : '' )}">
<f:param name="inCityStateZipListOrder" value="#{inCityStateZipList.order=='country asc' ? 'country desc' : 'country asc'}"/>
</a4j:htmlCommandLink>
</f:facet>
#{_inCityStateZip.country}
</h:column>
<h:column>
<f:facet name="header">
<a4j:htmlCommandLink styleClass="columnHeader" reRender="inCityStateZipList"
value="City #{inCityStateZipList.order=='city asc' ? messages.down : ( inCityStateZipList.order=='city desc' ? messages.up : '' )}">
<f:param name="inCityStateZipListOrder" value="#{inCityStateZipList.order=='city asc' ? 'city desc' : 'city asc'}"/>
</a4j:htmlCommandLink>
</f:facet>
#{_inCityStateZip.city}
</h:column>
<h:column>
<f:facet name="header">
<a4j:htmlCommandLink styleClass="columnHeader" reRender="inCityStateZipList"
value="State #{inCityStateZipList.order=='province asc' ? messages.down : ( inCityStateZipList.order=='province desc' ? messages.up : '' )}">
<f:param name="inCityStateZipListOrder" value="#{inCityStateZipList.order=='province asc' ? 'province desc' : 'province asc'}"/>
</a4j:htmlCommandLink>
</f:facet>
#{_inCityStateZip.province}
</h:column>
<h:column>
<f:facet name="header">
<a4j:htmlCommandLink styleClass="columnHeader" reRender="inCityStateZipList"
value="Zipcode #{inCityStateZipList.order=='zipcode asc' ? messages.down : ( inCityStateZipList.order=='zipcode desc' ? messages.up : '' )}">
<f:param name="inCityStateZipListOrder" value="#{inCityStateZipList.order=='zipcode asc' ? 'zipcode desc' : 'zipcode asc'}"/>
</a4j:htmlCommandLink>
</f:facet>
#{_inCityStateZip.zipcode}
</h:column>
<h:column>
<f:facet name="header">
<a4j:htmlCommandLink styleClass="columnHeader" reRender="inCityStateZipList"
value="County #{inCityStateZipList.order=='county asc' ? messages.down : ( inCityStateZipList.order=='county desc' ? messages.up : '' )}">
<f:param name="inCityStateZipListOrder" value="#{inCityStateZipList.order=='county asc' ? 'county desc' : 'county asc'}"/>
</a4j:htmlCommandLink>
</f:facet>
#{_inCityStateZip.county}
</h:column>
<h:column>
<f:facet name="header">
<a4j:htmlCommandLink styleClass="columnHeader" reRender="inCityStateZipList"
value="Status #{inCityStateZipList.order=='status.value asc' ? messages.down : ( inCityStateZipList.order=='status.value desc' ? messages.up : '' )}">
<f:param name="inCityStateZipListOrder" value="#{inCityStateZipList.order=='status.value asc' ? 'status.value desc' : 'status.value asc'}"/>
</a4j:htmlCommandLink>
</f:facet>
#{_inCityStateZip.status.value}
</h:column>
<h:column>
<f:facet name="header">Action</f:facet>
<s:link view="/admin/#{empty from ? 'InCityStateZip' : from}.xhtml"
value="Select"
id="inCityStateZip"
propagation="none">
<f:param name="inCityStateZipFrom"
value="#{inCityStateZipFrom}"/>
<f:param name="inCityStateZipId"
value="#{_inCityStateZip.id}"/>
</s:link>
</h:column>
</rich:dataTable>
</div>
<div class="tableControl">
<s:link view="/admin/#{inCityStateZipFrom}.xhtml"
rendered="#{inCityStateZipList.previousExists}"
value="#{messages.left}#{messages.left} First Page"
id="inCityStateZipListFirstPage">
<f:param name="firstResult" value="0"/>
</s:link>
<s:link view="/admin/#{inCityStateZipFrom}.xhtml"
rendered="#{inCityStateZipList.previousExists}"
value="#{messages.left} Previous Page"
id="inCityStateZipListPreviousPage">
<f:param name="firstResult"
value="#{inCityStateZipList.previousFirstResult}"/>
</s:link>
<s:link view="/admin/#{inCityStateZipFrom}.xhtml"
rendered="#{inCityStateZipList.nextExists}"
value="Next Page #{messages.right}"
id="inCityStateZipListNextPage">
<f:param name="firstResult"
value="#{inCityStateZipList.nextFirstResult}"/>
</s:link>
<s:link view="/admin/#{inCityStateZipFrom}.xhtml"
rendered="#{inCityStateZipList.nextExists}"
value="Last Page #{messages.right}#{messages.right}"
id="inCityStateZipListLastPage">
<f:param name="firstResult"
value="#{inCityStateZipList.lastFirstResult}"/>
</s:link>
</div>
</a4j:form>
InFilesHome.java
@Name("inFilesHome")
public class InFilesHome extends EntityHome<InFiles> {
private static final long serialVersionUID = 2221010914357487335L;
@In private Events events;
/**
* Setter for the entity id.
*
* @param id
* the entity id.
*/
public void setInFilesId(Long id) {
setId(id);
}
/**
* Getter for the entity id.
*
* @return the entity id.
*/
public Long getInFilesId() {
return (Long) getId();
}
/**
* Initializes the entity instance.
*/
@Override
protected InFiles createInstance() {
InFiles inFiles = super.createInstance();
// inFiles.setStatus(InFileStatus.NEW);
// inFiles.setCreatedOn(new Date());
return inFiles;
}
/**
* Called from the object's page.xml to establish the association prior to
* the editor being rendered.
*/
public void wire() {
}
/**
* Toggles the disabled attribute of the Save button if a wired object has
* not been selected.
*
* @return true if object is selected and false if object is not selected
*/
public boolean isWired() {
return true;
}
/**
* A custom method that strictly attempts to retrieve an instance from the
* persistence manager if the id is established, as determined by the
* isIdDefined() method.
*
* @return
*/
public InFiles getDefinedInstance() {
return isIdDefined() ? getInstance() : null;
}
// ---------------------------------------------------------------------------------
// Detail Screen
// ---------------------------------------------------------------------------------
// Tab listings are queried and displayed through their perspective java and
// xhtml.
// ---------------------------------------------------------------------------------
// Edit Screen
// ---------------------------------------------------------------------------------
/**
* Checks to see if inFiles record is ready for validation.
*
* @return true if ready for validation.
*/
public boolean isReadyForValidation() {
return (getInstance().getStatus().getKey() == InFileStatus.IMPORTED.getKey()
|| getInstance().getStatus().getKey() == InFileStatus.VALIDATING.getKey()
|| getInstance().getStatus().getKey() == InFileStatus.VALIDATION_ERROR.getKey());
}
/**
* Validates the inFiles data.
*
* NOTE: If any new validation needs to be added, place it in the action bean.
*/
public void validate() {
if (getInstance().getStatus().getKey() == InFileStatus.IMPORTING.getKey()
|| getInstance().getStatus().getKey() == InFileStatus.IMPORT_ERROR.getKey()) {
if (!areErrorsDeleted(InFileStatus.IMPORTED)) {
return;
}
}
this.info("validating...");
InFilesValidateAction contentAction = (InFilesValidateAction) Component.getInstance(InFilesValidateActionBean.class);
if (contentAction.inFilesValidateAction(getInstance()).equalsIgnoreCase("success")) {
getInstance().setStatus(InFileStatus.VALIDATED);
} else {
getInstance().setStatus(InFileStatus.VALIDATION_ERROR);
}
update();
//events.raiseTransactionSuccessEvent("refreshInCityStateZip");
}
/**
* Checks to see if inFiles record is available for posting.
*
* @return true if available for posting.
*/
public boolean isReadyForPosting() {
return (getInstance().getStatus().getKey() == InFileStatus.VALIDATED.getKey()
|| getInstance().getStatus().getKey() == InFileStatus.POSTING.getKey()
|| getInstance().getStatus().getKey() == InFileStatus.POSTING_ERROR.getKey());
}
/**
* Posts the inFiles data.
*
* NOTE: If any new posting needs to be added, place it in the action bean.
*/
public void post() {
if (getInstance().getStatus().getKey() == InFileStatus.POSTING.getKey()
|| getInstance().getStatus().getKey() == InFileStatus.POSTING_ERROR.getKey()) {
if (!areErrorsDeleted(InFileStatus.VALIDATED)) {
return;
}
}
this.info("posting...");
InFilesPostAction contentAction = (InFilesPostAction) Component.getInstance(InFilesPostActionBean.class);
if (contentAction.inFilesPostAction(getInstance()).equalsIgnoreCase("success")) {
getInstance().setStatus(InFileStatus.POSTED);
} else {
getInstance().setStatus(InFileStatus.POSTING_ERROR);
}
update();
}
/**
* Tries to delete any errors and set the inFiles status to the passed
* InFileStatus.
*
* @param inFilesStatus
* the status to set the inFile record to after deletion.
* @return true if the errors were deleted.
*/
private boolean areErrorsDeleted(InFileStatus inFilesStatus) {
try {
this.getEntityManager().createNamedQuery(
"inErrors.deleteByInFilesId").setParameter(
InErrors.FIELD_TO_INFILES, getInstance().getId());
getInstance().setStatus(inFilesStatus);
persist();
} catch (Exception ex) {
FacesMessages.instance().add(ex.getMessage());
ex.printStackTrace();
return false;
}
return true;
}
private byte[] inFile;
private String inContentType;
private String inFileName;
/**
* Method called when import is invoked.
*/
public void uploadInFile() {
if (inFile == null) {
FacesMessages.instance().add("The file: " + inFileName + "is null");
return;
}
if (inFile != null && inFile.length > 0) {
getInstance().setName(inFileName);
FacesMessages.instance().add(
"Filename: " + inFileName + "; filesize: " + inFile.length);
// System.out.println("filename: " + inFileName);
}
}
public void setInFile(byte[] inFile) {
this.inFile = inFile;
}
public byte[] getInFile() {
return inFile;
}
public String getInContentType() {
return inContentType;
}
public void setInContentType(String contentType) {
this.inContentType = contentType;
}
public InFileType[] getInFileTypes() {
return InFileType.values();
}
public InFileStatus[] getInFileStatuses() {
return InFileStatus.values();
}
}
The reason I have an InCityStateZipTable.xhtml is to eliminitate duplication of listings.
Does anyone have any idea how to refresh the tab listing?