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();
| }
|
|
| }
|
View the original post :
http://www.jboss.com/index.html?module=bb&op=viewtopic&p=4119394#...
Reply to the post :
http://www.jboss.com/index.html?module=bb&op=posting&mode=reply&a...