Cannot persist or update from editable datatable
daxxy Nov 17, 2009 1:50 PMI'm trying to set up an editable dataTable along the same lines as the example in richfaces demo. I am using a seam generated project so my backing beans are extensions of EntityHome (hope I'm saying this correctly).
I have a datatable that contains 2 one-to-one entities, Devices and DevTags. I want to be able to edit the DevTag in a modalPanel component.
<rich:dataTable id="dataTable" value="#{officeViewHome.instance.devices}" var="_devices" rowKeyVar="rowId" ajaxKeys="#{devTagsHome.rowsToUpdate}"> <rich:column> <f:facet name="header">Row ID</f:facet> <h:outputText value="#{rowId}" id="rowid" /> </rich:column> <rich:column> <f:facet name="header"> <h:outputText value="Hostname" /> </f:facet> <h:outputText value="#{_devices.devName}" id="hostname" /> </rich:column> <rich:column> <f:facet name="header"> <h:outputText value="Platform" /> </f:facet> <h:outputText value="#{_devices.devPlatform}" id="platform" /> </rich:column> <rich:column> <f:facet name="header"> <h:outputText value="Soft Serial Number" /> </f:facet> <h:outputText value="#{_devices.devSerialNum}" id="softSerialNum" /> </rich:column> <rich:column> <f:facet name="header"> <h:outputText value="DEvID" /> </f:facet> <h:outputText value="#{_devices.devId}" id="devId" /> </rich:column> <rich:column> <f:facet name="header"> <h:outputText value="Asset Tag" /> </f:facet> <h:outputText value="#{_devices.devTag.devTagId}" /> </rich:column> <rich:column> <f:facet name="header"> <h:outputText value="Hard Serial Tag" /> </f:facet> <h:outputText value="#{_devices.devTag.devSerialNum}" /> </rich:column> <rich:column> <f:facet name="header">Action</f:facet> <a4j:commandLink id="editLink" onclick="#{rich:component('editPanel')}.show()" reRender="assetTagPanel"> <h:graphicImage value="/img/icons/edit.gif" style="border:0" /> <f:setPropertyActionListener value="#{_devices.devId}" target="#{devTagsHome.devTagsDevId}" /> <f:setPropertyActionListener value="#{rowId}" target="#{devTagsHome.currentRow}" /> </a4j:commandLink> <rich:toolTip for="editLink" value="Edit Tag" rendered="#{not empty _devices.devTag.tagId}" /> <rich:toolTip for="editLink" value="New Tag" rendered="#{empty _devices.devTag.tagId}" /> </rich:column> </rich:dataTable> <rich:modalPanel id="editPanel" autosized="true" width="450"> <f:facet name="header">Asset Tag</f:facet> <f:facet name="controls"> <h:panelGroup> <h:graphicImage value="/img/modal/close.png" id="hideEditPanel" styleClass="hidelink" onclick="#{rich:component('editPanel')}.hide()" /> </h:panelGroup> </f:facet> <h:form> <rich:messages for="assetTagPanel" style="color:red;"></rich:messages> <a4j:outputPanel ajaxRendered="true" id="assetTagPanel"> <h:panelGrid columns="2"> <h:outputText value="Serial Number. Change if necessary" /> <h:outputText value="#{devTagsHome.instance.devSerialNum}" rendered="#{not empty devTagsHome.instance.devSerialNum}" /> <h:outputText value="Asset Tag" /> <h:inputText value="#{devTagsHome.instance.devTagId}" /> <h:outputText value="Comment" /> <h:outputText value="#{devTagsHome.instance.comment}" /> <h:outputText value="Single Site Code" /> <h:outputText value="#{officeViewHome.officeViewSiteCode}" /> </h:panelGrid> </a4j:outputPanel> <a4j:commandButton value="Persist" actionListener="#{devTagsHome.persist}" oncomplete="#{rich:component('editPanel')}.hide()" reRender="dataTable" /> <a4j:commandButton value="Update" actionListener="#{devTagsHome.update}" oncomplete="#{rich:component('editPanel')}.hide()" reRender="dataTable" /> </h:form> </rich:modalPanel>
The only field I need to edit is devTagId and then I want to save my change by clicking on Update. The result is a nullPointerException and when I run in the debugger and stop on the "update()" method, sure enough DevTagsHome is empty so of course it cannot be updated.
The data populates the modalPanel just fine so I know the devTags.instance is being found correctly. Why, when I get to devTags.update() does my app act like it has never seen this devTag before?
Here is DevTagsHome.java
@Name("devTagsHome") public class DevTagsHome extends EntityHome<DevTags> { private Integer devTagsDevId; private Set<Integer> rowsToUpdate; private Integer currentRow; // Use devId to find the instance rather than tagId @Override public Object getId() { if (devTagsDevId == null) { return (Integer) super.getId(); } return (Integer) getEntityManager().createQuery("select d.tagId from DevTags d " + "where d.devId=:devId ").setParameter("devId", devTagsDevId). getSingleResult(); } protected DevTags createInstance() { DevTags devTags = new DevTags(); return devTags; } public void load() { if (isIdDefined()) { wire(); } } public void wire() { getInstance(); } public boolean isWired() { return true; } public DevTags getDefinedInstance() { return isIdDefined() ? getInstance() : null; } @Override public String update() { // TODO Auto-generated method stub rowsToUpdate.clear(); rowsToUpdate.add(currentRow); return super.update(); } @Override public String persist() { // TODO Auto-generated method stub rowsToUpdate.clear(); rowsToUpdate.add(currentRow); return super.persist(); } }
TDR