Passing and entity to a template fails on submit
shadders Feb 20, 2010 4:36 AMI've got a project that started with seam-gen (from eclipse) which I'm trying to modify.
eclipse 3.5, JBoss tools 3.1, JBoss AS 5.1, seam 2.2.0 GA
I have an entity Person which has a property Address which is also an entity. Actually it has two, address1 and address2.
The PersonHome/PersonList/AddressHome/AddressList beans are unmodified from the generated version.
I'm trying to build a person edit form and use a template for displaying the address because I will want to display the address from numerous sources (I have another entity 'Creature' which has address as well). So I am passing the address entity as a parameter to the template.
The relevant section of the main form is:
<rich:tabPanel switchType="client"> <rich:tab id="address1Detail" label="Main Address"> <f:facet name="header">Primary Address</f:facet> <s:decorate id="address1Fields" template="/comp/Address.xhtml" propagation="nest"> <ui:param name="addressBean" value="#{personHome.instance.addressByAddress1}" /> <ui:param name="addressHomeBean" value="#{addressHome}" /> </s:decorate> </rich:tab> <rich:tab id="address2Detail" label="Secondary Address"> <f:facet name="header">Secondary Address (click to expand)</f:facet> <s:decorate id="address2Fields" template="/comp/Address.xhtml" propagation="nest"> <ui:param name="addressBean" value="#{personHome.instance.addressByAddress2}" /> <ui:param name="addressHomeBean" value="#{addressHome}" /> </s:decorate> </rich:tab> </rich:tabPanel>
and the template:
<!DOCTYPE composition PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> <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:rich="http://richfaces.org/rich" xmlns:a="http://richfaces.org/a4j" > <s:conversationPropagation propagation="join"/> <h:outputText value="#{conversation.id}" /> <s:decorate id="street1Field" template="/layout/edit.xhtml" rendered="#{addressHomeBean.allowView}"> <ui:define name="label">Street1</ui:define> <h:outputText id="vStreet1" value="#{addressBean.street1}" rendered="#{addressHomeBean.allowViewNotEdit}"/> <h:inputText id="sStreet1" required="true" size="45" maxlength="45" value="#{addressBean.street1}" rendered="#{addressHomeBean.allowEdit}"> <a:support event="onblur" reRender="street1Field" bypassUpdates="true" ajaxSingle="true" /> </h:inputText> </s:decorate> <s:decorate id="street2Field" template="/layout/edit.xhtml" rendered="#{addressHomeBean.allowView}"> <ui:define name="label">Street2</ui:define> <h:outputText id="vetreet2" value="#{addressBean.street2}" rendered="#{addressHomeBean.allowViewNotEdit}"/> <h:inputText id="eStreet2" size="45" maxlength="45" value="#{addressBean.street2}" rendered="#{addressHomeBean.allowEdit}"> <a:support event="onblur" reRender="street2Field" bypassUpdates="true" ajaxSingle="true" /> </h:inputText> </s:decorate> <s:decorate id="suburbField" template="/layout/edit.xhtml" rendered="#{addressHomeBean.allowMinorView}"> <ui:define name="label">Suburb</ui:define> <h:outputText id="vSuburb" value="#{addressBean.suburb}" rendered="#{addressHomeBean.allowMinorViewNotEdit}"/> <h:inputText id="eSuburb" required="true" size="45" maxlength="45" value="#{addressBean.suburb}" rendered="#{addressHomeBean.allowEdit}"> <a:support event="onblur" reRender="suburbField" bypassUpdates="true" ajaxSingle="true" /> </h:inputText> </s:decorate> <s:decorate id="cityField" template="/layout/edit.xhtml" rendered="#{addressHomeBean.allowMinorView}"> <ui:define name="label">City</ui:define> <h:outputText id="vCity" value="#{addressBean.city}" rendered="#{addressHomeBean.allowMinorViewNotEdit}"/> <h:inputText id="eCity" size="45" maxlength="45" value="#{addressBean.city}" rendered="#{addressHomeBean.allowEdit}"> <a:support event="onblur" reRender="cityField" bypassUpdates="true" ajaxSingle="true" /> </h:inputText> </s:decorate> <s:decorate id="postcodeField" template="/layout/edit.xhtml" rendered="#{addressHomeBean.allowMinorView}"> <ui:define name="label">Postcode</ui:define> <h:outputText id="vPostcode" value="#{addressBean.postcode}" rendered="#{addressHomeBean.allowMinorViewNotEdit}"/> <h:inputText id="ePostcode" required="true" size="10" maxlength="10" readonly="true" disabled="true" value="#{addressBean.postcode}" rendered="#{addressHomeBean.allowEdit}" > <a:support event="onblur" reRender="postcodeField" bypassUpdates="true" ajaxSingle="true" /> </h:inputText> </s:decorate> <s:decorate id="stateField" template="/layout/edit.xhtml" rendered="#{addressHomeBean.allowMinorView}"> <ui:define name="label">State</ui:define> <h:outputText id="vState" value="#{addressBean.state}" rendered="#{addressHomeBean.allowMinorViewNotEdit}"/> <h:inputText id="eState" size="20" maxlength="20" value="#{addressBean.state}" rendered="#{addressHomeBean.allowEdit}"> <a:support event="onblur" reRender="stateField" bypassUpdates="true" ajaxSingle="true" /> </h:inputText> </s:decorate> <div style="clear: both"><span class="required">*</span> required fields</div> </ui:composition>
This works fine for the initial display. I can see both of the address values populated correctly. But on any form submit of the personEdit page (e.g. toggling a simpleTogglePanel or clicking the save button) it throws me to a debug page with the exception:
"Exception during request processing: Caused by javax.servlet.ServletException with message: "/comp/Address.xhtml @18,75 value="#{addressBean.street1}": Target Unreachable, identifier 'addressBean' resolved to null""
If I make a second template that references the address bean directly from personHome e.g.
<s:decorate id="street1Field" template="/layout/edit.xhtml" rendered="#{addressHome.allowView}"> <ui:define name="label">Street1</ui:define> <h:outputText id="vStreet1" value="#{personHome.instance.addressByAddress1.street1}" rendered="#{addressHome.allowViewNotEdit}" /> <h:inputText id="sStreet1" required="true" size="45" maxlength="45" value="#{personHome.instance.addressByAddress1.street1}" rendered="#{addressHome.allowEdit}"> <a:support event="onblur" reRender="street1Field" bypassUpdates="true" ajaxSingle="true" /> </h:inputText> </s:decorate>
It works fine but of course that makes the template pointless since I need a seperate one for address1 and address2.
It seems that the ui:param doesn't reevaluate on an ajax update or a full page update. I've tried all sorts of combinations of propagation values. I can see that the conversation is being passed to the template because if I use second template I can output the conversation ID and see it is the same as the main form. I'm not sure if this is conversation related at all though?
Can anyone help? I'm quite new to seam/JSF so if this is the wrong approach to what I'm trying to achieve please put me on the right track.