13 Replies Latest reply on Jan 17, 2008 9:57 AM by pmuir

    Form Validation Question:Entity Bean @NotNull vs. required=

      I am trying to figure how this seam entity bean validation and form validation fit together. Here are a couple questions:

      1. Are the @NotNull validation annotations and the validation attributes like 'required="true" mutually exclusive? In other words, can I only use one or the other?

      2. What mechanism in seam causes the form to be re-displayed instead of the seam debug page when there are Hibernate validation errors? (Particularily when the EntityHome.persist() method is called)

      A little background on question 2: When my application was first created using seam-gen, when fields on the form were invalid, the form would be redisplayed and the entity would not be persisted to the database. Since then I have made many changes, and now it appears that when the form is submitted that my EntityHome object tries to persist the object instance whether the form is valid or not. If I remove the hibernate validation annotations from the Entity Bean, then the object is persisted to the DB even if the fields violate the "requrired=true" attrubute in the form fields. But if I keep the hibernate validation annotations in the entity bean, the Seam debug page is displayed instead of the form and error messages. The debug page stack trace contains this error message:

      org.hibernate.PropertyValueException: not-null property references a null or transient value

      Here is my form page:

      <!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:a="https://ajax4jsf.dev.java.net/ajax"
       xmlns:rich="http://richfaces.ajax4jsf.org/rich"
       template="layout/frametemplate.xhtml">
      
      <style>
       .gridContent {
       vertical-align:top;
       }
      
       .outpanelHeader {
       height:4px;
       border-width: 0;
       }
       .inpanelBody {
       height:580px;
       overflow:auto;
       }
      
      </style>
       <ui:define name="body">
       <h:messages globalOnly="true" styleClass="message" id="globalMessages" />
      
       <h:form id="rptprdmgbinder" styleClass="edit">
      
       <h:inputHidden id="clientaddress"
       value="#{rptprdmgbinderHome.instance.clientaddress}">
       </h:inputHidden>
      
       <h:inputHidden id="lienaddress"
       value="#{rptprdmgbinderHome.instance.lienaddress}">
       </h:inputHidden>
      
       <rich:panel>
       <f:facet name="header">Edit Property Damage Binder</f:facet>
      
       <h:inputHidden id="lineOfBusiness"
       value="#{rptprdmgbinderHome.instance.lineOfBusiness}">
       </h:inputHidden>
      
       <h:inputHidden id="id"
       value="#{rptprdmgbinderHome.instance.id}">
       </h:inputHidden>
      
      
      <!-- </rich:panel>-->
      
      <!-- <rich:panel>-->
      <!-- <f:facet name="header">Client</f:facet>-->
       <h:panelGroup>
       <h:panelGrid columns="2" style="width:100%" columnClasses="list2, list2">
       <s:decorate id="clientname1Decoration"
       template="layout/edit.xhtml">
       <ui:define name="label">Client Name 1</ui:define>
       <s:validateAll>
       <h:inputText id="clientNameLine1" size="40" maxlength="50"
       styleClass="list2" required="true"
       value="#{rptprdmgbinderHome.instance.clientNameLine1}">
      
       </h:inputText>
       </s:validateAll>
       </s:decorate>
       </h:panelGrid>
      
      
       </h:panelGroup>
      
      
      
       <h:inputHidden id="policyid"
       value="#{rptprdmgbinderHome.instance.policyid}">
       </h:inputHidden>
      
       <h:inputHidden id="companyname"
       value="#{rptprdmgbinderHome.instance.company}">
       </h:inputHidden>
      
       <div style="clear:both">
       <span class="required">*</span>required fields
       </div>
      
       <div class="actionButtons">
       <s:button action="#{rptprdmgbinderHome.persist}" id="save"
       value="Save" disabled="#{!rptprdmgbinderHome.wired}"
       rendered="#{!rptprdmgbinderHome.managed}">
       <f:param name="rptprdmgbinderFrom" value="#{rptprdmgbinderFrom}" />
       </s:button>
      
       <h:commandButton id="update" value="Save"
       action="#{rptprdmgbinderHome.update}"
       rendered="#{rptprdmgbinderHome.managed}" />
      
       <s:button action="#{rptprdmgbinderHome.remove}" id="delete"
       value="Delete" rendered="#{rptprdmgbinderHome.managed}">
       <f:param name="rptprdmgbinderFrom" value="#{rptprdmgbinderFrom}" />
       </s:button>
      
       <s:button id="done" value="Done" propagation="end"
       view="/Rptprdmgbinder.xhtml"
       rendered="#{rptprdmgbinderHome.managed}" />
      
       <s:button id="cancel" value="Cancel" propagation="end"
       view="/#{empty rptprdmgbinderFrom ? 'RptprdmgbinderList' : rptprdmgbinderFrom}.xhtml"
       rendered="#{!rptprdmgbinderHome.managed}" />
       </div>
       </rich:panel>
      
       </h:form>
       </ui:define>
      </ui:composition>
      
      


      Here is my Entity Home class:
      Note that I have commented out the overridden persist() method. This was because I thought that this was causing my problem.
      package com.idfbins.nexus.common.vo.reports;
      
      import java.util.Calendar;
      import java.util.Date;
      
      import org.jboss.seam.ScopeType;
      import org.jboss.seam.annotations.IfInvalid;
      import org.jboss.seam.annotations.In;
      import org.jboss.seam.annotations.Name;
      import org.jboss.seam.annotations.Out;
      import org.jboss.seam.annotations.RequestParameter;
      import org.jboss.seam.framework.EntityHome;
      import org.jboss.seam.security.Identity;
      
      import com.idfbins.nexus.common.vo.busent.FBWorker;
      
      @Name("rptprdmgbinderHome")
      public class RptprdmgbinderHome extends EntityHome<Rptprdmgbinder> {
       //@In PolicyVO policy;
      
       @In
       Identity identity;
      
       @In(required = false)
       private FBWorker worker;
      
       @Out(required=false)
       String from;
      
       @RequestParameter()
       String rptprdmgbinderFrom;
      
       @RequestParameter()
       String showFrameMenuParam;
      
       @In(required=false, scope=ScopeType.CONVERSATION)
       @Out(required=false, scope=ScopeType.CONVERSATION)
       String showFrameMenu;
      
       @Out (required=false, scope=ScopeType.CONVERSATION,value="rptprdmgbinderFrom")
       String fromLocation;
      
       public void setRptprdmgbinderId(Integer id) {
       setId(id);
       }
      
       public Integer getRptprdmgbinderId() {
       return (Integer) getId();
       }
      
       @Override
       protected Rptprdmgbinder createInstance() {
       Rptprdmgbinder rptprdmgbinder = new Rptprdmgbinder();
       //rptprdmgbinder.setPropertyCity("Pocatello");
       return rptprdmgbinder;
       }
      
       public void wire() {
       }
      
       public boolean isWired() {
       return true;
       }
      
       public Rptprdmgbinder getDefinedInstance() {
       return isIdDefined() ? getInstance() : null;
       }
      
       /* (non-Javadoc)
       * @see org.jboss.seam.framework.EntityHome#persist()
       */
      /*
       @Override
       public String persist() {
       Date createDate=Calendar.getInstance().getTime();
       getInstance().setDateTimeCreated(createDate);
       getInstance().setOfficeId(worker.getOffice().getId());
       if (identity!=null)
       {
       getInstance().setCreatedBy(identity.getUsername());
       }
       if (getInstance().getLienholderMailSameAs())
       {
       getInstance().setLienholderMailAddressLine1(getInstance().getLienAddressLine1());
       getInstance().setLienholderMailAddressLine2(getInstance().getLienAddressLine2());
       getInstance().setLienholderMailAddressLine3(getInstance().getLienAddressLine3());
       getInstance().setLienholderMailNameLine1(getInstance().getLienholderName1());
       getInstance().setLienholderMailNameLine2(getInstance().getLienholderName2());
       getInstance().setLienholderMailNameLine3(getInstance().getLienholderName3());
       getInstance().setLienholderMailNameLine4(getInstance().getLienholderName4());
       }
       return super.persist();
       }
       */
       public String lookupLender()
       {
       from="RptprdmgbinderEdit";
       return "success";
       }
      
       @Override
       public String remove()
       {
      
       //String fromString=rptphdmgbinderFrom;
       String returnString =super.remove();
       if (rptprdmgbinderFrom!=null)
       {
       if (rptprdmgbinderFrom.equalsIgnoreCase("CountyOfficeDocumentsList"))
       {
       returnString= "removedFromOfficeDocumentsList";
       }
       }
       return returnString;
       }
      
      
       @Override
       public void create()
       {
       //showFrameMenuParam
      
       //because the report pages can be called from the client in a frame or from the workbench, we need to toggle the menu depending upon where this is getting called from.
       if (showFrameMenu==null)
       {
       showFrameMenu=showFrameMenuParam;
       }
      
       //set the fromLocation with conversational scope equal to the request parameter. This m
       //makes it so the request parameter does not need to be passed from page to page. As long
       //as the conversation is active the variable will be outjected with the same name as the
       //request parameter.
       if (fromLocation==null)
       {
       fromLocation=rptprdmgbinderFrom;
       }
      
       super.create();
       }
      
       /* (non-Javadoc)
       * @see org.jboss.seam.framework.EntityHome#update()
       */
       @Override
       public String update()
       {
       if (getInstance().getLienholderMailSameAs())
       {
       getInstance().setLienholderMailAddressLine1(getInstance().getLienAddressLine1());
       getInstance().setLienholderMailAddressLine2(getInstance().getLienAddressLine2());
       getInstance().setLienholderMailAddressLine3(getInstance().getLienAddressLine3());
       getInstance().setLienholderMailNameLine1(getInstance().getLienholderName1());
       getInstance().setLienholderMailNameLine2(getInstance().getLienholderName2());
       getInstance().setLienholderMailNameLine3(getInstance().getLienholderName3());
       getInstance().setLienholderMailNameLine4(getInstance().getLienholderName4());
       }
      
       return super.update();
       }
      
      
      }