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?