0 Replies Latest reply on Feb 18, 2006 2:48 AM by Chris Hane

    Why do I need the @Valid tag?

    Chris Hane Novice

      I generated a sample CRUD application using the Hibernate Reverse Eng. tool. Worked like a charm - very nice work.

      I am trying to do something similar to the example.issue....IssueFinderBean with the property example. For some reason, I can't seem to make it work without the @Valid tag.

      When I add a property to the generated SFSB, I must add the @Valid tag to the property. If this tag is not added, and I hit the create button, the request is submitted but returns to the create screen and does not execute the create method on the SFSB (no exception thrown).

      The property I am adding is an instance of a second entity bean - although it is not being persisted to the db - I am using it to hold a value to use in a search query.

      Is the @Valid tag required? I thought this was only used to indicate Hib Validator should be run on the property.

      Thoughts on what I am doing wrong.

      Thanks,
      Chris....

      Seam Beta 2
      Jboss 4.0.4
      Hib Tools Nightly 2/17/06

      Here is the code that was generated and I am modifying slightly:

      There are two objects: Person, Sale (included below)

      The SFSB is:

      package com.its;
      
      // Generated Feb 17, 2006 6:06:18 PM by Hibernate Tools 3.1.0.beta4
      
      import java.util.ResourceBundle;
      import javax.ejb.Interceptors;
      import javax.ejb.Remove;
      import javax.ejb.Stateful;
      import javax.ejb.TransactionAttribute;
      import static javax.ejb.TransactionAttributeType.NOT_SUPPORTED;
      import javax.faces.application.FacesMessage;
      import javax.faces.context.FacesContext;
      import javax.persistence.EntityManager;
      import org.hibernate.validator.Valid;
      import org.jboss.seam.Component;
      import org.jboss.seam.InterceptionType;
      
      import static org.jboss.seam.ScopeType.CONVERSATION;
      import org.jboss.seam.annotations.Begin;
      import org.jboss.seam.annotations.Destroy;
      import org.jboss.seam.annotations.End;
      import org.jboss.seam.annotations.IfInvalid;
      import org.jboss.seam.annotations.In;
      import org.jboss.seam.annotations.Intercept;
      import org.jboss.seam.annotations.Name;
      import org.jboss.seam.annotations.Out;
      import org.jboss.seam.annotations.Outcome;
      import org.jboss.seam.ejb.SeamInterceptor;
      
      @Name("saleEditor")
      @Stateful
      @Interceptors(SeamInterceptor.class)
      public class SaleEditorBean implements SaleEditor{
      
       @In(create = true)
       private EntityManager entityManager;
      
       @Valid
       private Sale instance = new Sale();
      
       @TransactionAttribute(NOT_SUPPORTED)
       public Sale getInstance(){
       return instance;
       }
      
       public void setInstance(Sale instance){
       this.instance = instance;
       }
      
       @Valid
       Person myBillToPerson = new Person(); // <- This is the property I am adding
      
       public Person getMyBillToPerson(){
       return myBillToPerson;
       }
      
       public void setMyBillToPerson(Person myBillToPerson){
       this.myBillToPerson = myBillToPerson;
       }
      
       private boolean isNew = true;
      
       @TransactionAttribute(NOT_SUPPORTED)
       public boolean isNew(){
       return isNew;
       }
      
       public void setNew(boolean isNew){
       this.isNew = isNew;
       }
      
       private String doneOutcome = "find";
      
       public void setDoneOutcome(String outcome){
       doneOutcome = outcome;
       }
      
       @In(required = false)
       private transient SaleFinder saleFinder;
      
       @In
       private transient ResourceBundle resourceBundle;
      
       @Begin(join = true)
       @IfInvalid(outcome = Outcome.REDISPLAY)
       public String create(){
       if(entityManager.find(Sale.class, instance.getId()) != null) {
       FacesContext.getCurrentInstance().addMessage(
       null,
       new FacesMessage(resourceBundle.getString("Sale_id") + " "
       + resourceBundle.getString("AlreadyExists")));
       return null;
       }
      
       entityManager.persist(instance);
       isNew = false;
      
       refreshFinder();
       FacesContext.getCurrentInstance().addMessage( // <- modified to see if I get here
       null,
       new FacesMessage("made it here"));
       return null;
      // return "editSale";
       }
      
       @IfInvalid(outcome = Outcome.REDISPLAY)
       public String update(){
       refreshFinder();
       return null;
       }
      
       @End(ifOutcome = "find")
       public String delete(){
       entityManager.remove(instance);
       instance.getPerson().getSales().remove(instance);
       refreshFinder();
       return doneOutcome;
       }
      
       @End(ifOutcome = "find")
       public String done(){
       if(!isNew)
       entityManager.refresh(instance);
       return doneOutcome;
       }
      
       private void refreshFinder(){
       if(saleFinder != null)
       saleFinder.refresh();
       }
      
       @Destroy
       @Remove
       public void destroy(){
       }
      
       @In(create = true)
       private transient PersonEditor personEditor;
      
       public String person(){
       personEditor.setNew(false);
       personEditor.setInstance(instance.getPerson());
       personEditor.setDoneOutcome("editSale");
       return "editPerson";
       }
      
       @Begin(join = true)
       public String selectPerson(){
       CONVERSATION.getContext().set("personSelector",
       Component.getInstance("salePersonSelector", true));
       return "selectPerson";
       }
      
      
      }
      


      And the page I am modifying:
      <%@ taglib uri="http://java.sun.com/jsf/html" prefix="h" %>
      <%@ taglib uri="http://java.sun.com/jsf/core" prefix="f" %>
      <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
      <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
       <f:view>
       <f:loadBundle basename="messages" var="msg"/>
       <head>
       <meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1" />
       <title>
       <h:outputText value="#{msg.Create} #{msg.Sale}" rendered="#{saleEditor.new}"/>
       <h:outputText value="#{msg.Update}/#{msg.Delete} #{msg.Sale}" rendered="#{!saleEditor.new}"/>
       </title>
       <style type="text/css" media="all">
       @import "style/default/screen.css";
       </style>
       </head>
       <body>
       <h:form>
      
       <h1>
       <h:outputText value="#{msg.Create} #{msg.Sale}" rendered="#{saleEditor.new}"/>
       <h:outputText value="#{msg.Update}/#{msg.Delete} #{msg.Sale}" rendered="#{!saleEditor.new}"/>
       </h1>
      
       <div class="rvgSwitch">
       <h:selectOneMenu value="#{switcher.conversationIdOrOutcome}">
       <f:selectItem itemLabel="Create Sale" itemValue="editSale"/>
       <f:selectItem itemLabel="Create Person" itemValue="editPerson"/>
       <f:selectItem itemLabel="Find Sale" itemValue="findSale"/>
       <f:selectItem itemLabel="Find Person" itemValue="findPerson"/>
       <f:selectItems value="#{switcher.selectItems}"/>
       </h:selectOneMenu>
       <h:commandButton action="#{switcher.select}" value="Switch"/>
       </div>
      
       <div class="rvgFind">
       <fieldset class="rvgFieldSet">
       <legend><h:outputText value="#{msg.Sale} #{msg.Attributes}"/></legend>
      
       <span class="rvgInputs">
       <span class="rvgMessage"><h:messages globalOnly="true"/></span>
       <h:outputLabel value="#{msg.Sale_id}" for="xxxx">
       <h:inputText value="#{saleEditor.instance.id}" id="xxxx" disabled="#{!saleEditor.new}"/>
       <span class="rvgMessage"><h:message for="xxxx"/></span>
       </h:outputLabel>
       <h:outputLabel value="#{msg.Sale_orderdate}" for="orderdate">
       <h:inputText value="#{saleEditor.instance.orderdate}" id="orderdate">
       <f:convertDateTime type="both" dateStyle="short"/>
       </h:inputText>
       <span class="rvgMessage"><h:message for="orderdate"/></span>
       </h:outputLabel>
       <h:outputLabel value="#{msg.Sale_person}" for="aaa">
       <h:inputText value="#{saleEditor.myBillToPerson.id}" id="aaa"/> <!-- here is the input box I added
       </h:outputLabel>
       <h:outputLabel value="#{msg.Sale_shipTo}" for="shipTo">
       <h:inputText value="#{saleEditor.instance.shipTo}" id="shipTo"/>
       <span class="rvgMessage"><h:message for="shipTo"/></span>
       </h:outputLabel>
       </span>
      
       <span class="rvgActions">
       <h:commandButton type="submit" value="#{msg.Create}" action="#{saleEditor.create}" rendered="#{saleEditor.new}"/>
       <h:commandButton type="submit" value="#{msg.Update}" action="#{saleEditor.update}" rendered="#{!saleEditor.new}"/>
       <h:commandButton type="submit" value="#{msg.Delete}" action="#{saleEditor.delete}" rendered="#{!saleEditor.new}"/>
       <h:commandButton type="submit" value="#{msg.Done}" action="#{saleEditor.done}"/>
       </span>
      
       </fieldset>
       </div>
      
       <div class="rvgResults">
       <h2><h:outputText value="#{msg.Sale_person}"/></h2>
       <h:outputText value="#{msg.No} #{msg.Sale_person}" rendered="#{saleEditor.instance.person == null}"/>
       <h:dataTable var="parent" value="#{saleEditor.instance.person}"
       rendered="#{saleEditor.instance.person != null}" rowClasses="rvgRowOne,rvgRowTwo">
       <h:column>
       <f:facet name="header"><h:outputText value="#{msg.Person_id}"/></f:facet>
       <h:outputText value="#{parent.id}"/>
       </h:column>
       <h:column>
       <f:facet name="header"><h:outputText value="#{msg.Person_fname}"/></f:facet>
       <h:outputText value="#{parent.fname}"/>
       </h:column>
       <h:column>
       <f:facet name="header"><h:outputText value="#{msg.Action}"/></f:facet>
       <h:commandButton action="#{saleEditor.person}" value="#{msg.View} #{msg.Person}"/>
       </h:column>
       </h:dataTable>
      
       <span class="rvgPage">
       <h:commandButton type="submit" value="#{msg.Select} #{msg.Person}" action="#{saleEditor.selectPerson}" />
       </span>
      
       </div>
      
       </h:form>
      
       </body>
       </f:view>
      </html>


      package com.its;
      
      // Generated Feb 17, 2006 6:06:17 PM by Hibernate Tools 3.1.0.beta4
      
      import java.util.Date;
      
      import javax.persistence.CascadeType;
      import javax.persistence.Column;
      import javax.persistence.Entity;
      import javax.persistence.FetchType;
      import javax.persistence.Id;
      import javax.persistence.JoinColumn;
      import javax.persistence.ManyToOne;
      import javax.persistence.Table;
      
      /**
       * Sale generated by hbm2java
       */
      @Entity
      @Table(name = "sale", uniqueConstraints = {})
      public class Sale implements java.io.Serializable{
      
       // Fields
      
       private long id;
       private Person person;// = new Person();
       private Date orderdate;
       private Long shipTo;
      
       // Constructors
      
       /** default constructor */
       public Sale(){
       }
      
       /** minimal constructor */
       public Sale(long id){
       this.id = id;
       }
      
       /** full constructor */
       public Sale(long id, Person person, Date orderdate, Long shipTo){
       this.id = id;
       this.person = person;
       this.orderdate = orderdate;
       this.shipTo = shipTo;
       }
      
       // Property accessors
       @Id
       @Column(name = "id", unique = true, nullable = false, insertable = true, updatable = true)
       public long getId(){
       return this.id;
       }
      
       public void setId(long id){
       this.id = id;
       }
      
       @ManyToOne(cascade = {}, fetch = FetchType.LAZY)
       @JoinColumn(name = "billTo", unique = false, nullable = true, insertable = true, updatable = true)
       public Person getPerson(){
       return this.person;
       }
      
       public void setPerson(Person person){
       this.person = person;
       }
      
       @Column(name = "orderdate", unique = false, nullable = true, insertable = true, updatable = true, length = 19)
       public Date getOrderdate(){
       return this.orderdate;
       }
      
       public void setOrderdate(Date orderdate){
       this.orderdate = orderdate;
       }
      
       @Column(name = "shipTo", unique = false, nullable = true, insertable = true, updatable = true)
       public Long getShipTo(){
       return this.shipTo;
       }
      
       public void setShipTo(Long shipTo){
       this.shipTo = shipTo;
       }
      
      }
      


      package com.its;
      
      // Generated Feb 17, 2006 6:06:17 PM by Hibernate Tools 3.1.0.beta4
      
      import java.util.HashSet;
      import java.util.Set;
      import javax.persistence.CascadeType;
      import javax.persistence.Column;
      import javax.persistence.Entity;
      import javax.persistence.FetchType;
      import javax.persistence.Id;
      import javax.persistence.OneToMany;
      import javax.persistence.Table;
      
      /**
       * Person generated by hbm2java
       */
      @Entity
      @Table(name = "person", uniqueConstraints = {})
      public class Person implements java.io.Serializable{
      
       // Fields
      
       private long id;
       private String fname;
       private Set<Sale> sales = new HashSet<Sale>(0);
      
       // Constructors
      
       /** default constructor */
       public Person(){
       }
      
       /** minimal constructor */
       public Person(long id){
       this.id = id;
       }
      
       /** full constructor */
       public Person(long id, String fname, Set<Sale> sales){
       this.id = id;
       this.fname = fname;
       this.sales = sales;
       }
      
       // Property accessors
       @Id
       @Column(name = "id", unique = true, nullable = false, insertable = true, updatable = true)
       public long getId(){
       return this.id;
       }
      
       public void setId(long id){
       this.id = id;
       }
      
       @Column(name = "fname", unique = false, nullable = true, insertable = true, updatable = true, length = 50)
       public String getFname(){
       return this.fname;
       }
      
       public void setFname(String fname){
       this.fname = fname;
       }
      
       @OneToMany(cascade = { CascadeType.ALL }, fetch = FetchType.LAZY, mappedBy = "person")
       public Set<Sale> getSales(){
       return this.sales;
       }
      
       public void setSales(Set<Sale> sales){
       this.sales = sales;
       }
      
      }