4 Replies Latest reply on Apr 27, 2009 11:54 PM by dzakharov.dmitri.zakharov.gmail.com

    Seam newbie question - default db field values

    dzakharov.dmitri.zakharov.gmail.com

      Hello everybody,


      Seam: 2.1.1.GA
      JBoss: 5.0.1.GA


      I have generated project prototype with seam generate command based on existing database schema. Now I am doing some customization.


      My project allows to the user to submit claim information. When I create a new claim (Add Claim view) there are some fields in the database that do not require user's input, but can be set automatically. For example, fields:


      CREATE_DATE
      CREATE_USER
      CREATE_APPLICATION



      For the CREATE DATE, I just need to use current timestamp and for CREATE USER and APPLICATION I can just use constant values.


      How/where can I set these values automatically at the time of creation of new claim?


      Any leads or suggestion are appreciated.


        • 1. Re: Seam newbie question - default db field values
          gonorrhea

          Depending on whether your form is causing setter/getter methods to be fired on an entity class directly or on an action backing bean (i.e. SFSB or JavaBean), the code would look something similar to this (this example is assuming the former scenario):


          @In EntityManager entityManager;
          
          private EquipmentRepair equipmentRepairCost;
          
          public void submit() {
             //setter methods from form input text fields, etc. have already been called on entity class by now...
             equipmentRepairCost.setDate(new Date());   
             entityManager.persist(equipmentRepairCost);
             entityManager.flush();  //assuming you are using Hibernate MANUAL flush mode set in @Begin
          }



          The entity needs to be persisted by invoking the persist() method b/c it is in transient state.  The default flush mode in JPA is AUTO, so if you're not using Hibernate manual flush, you can delete the last line in the submit() method above and the persistence context will be automatically flushed/synchronized with the db when the tx commits successfully at the end of the method.  We are assuming you're using SFSB and CMT (tx is required by default).


          • 2. Re: Seam newbie question - default db field values
            gonorrhea

            Here is a very good example from SIA book.  Note that the call to the add() method passes the tip entity as a param.  In the add() method you would call the add'l setters for that entity instance, like my code above.


            <h:form id="golfTip">
                           <rich:simpleTogglePanel switchType="client" opened="false">
                                <f:facet name="header">Do you have golf wisdom to share?</f:facet>
            
                                <div class="prop">
                                     <h:outputLabel styleClass="name" for="author">Author <span class="required">*</span></h:outputLabel>
                                     <span class="value">
                                          <h:inputText id="author" value="#{tip.author}" required="true" style="width: 150px;"/>
                                     </span>
                                     <span class="error">
                                          <h:graphicImage value="/img/error.gif" rendered="#{not empty facesMessages.getCurrentMessagesForControl('author')}" styleClass="errors"/>
                                          <h:message for="author" styleClass="errors"/>
                                     </span>
                                </div>
            
                                <div class="prop">
                                     <h:outputLabel styleClass="name" for="category">Category <span class="required">*</span></h:outputLabel>
                                     <span class="value">
                                          <h:selectOneMenu id="category" value="#{tip.category}" required="true" style="width: 153px;">
                                               <f:selectItem itemValue="" itemLabel="-- Select --"/>
                                               <f:selectItem itemValue="The Swing"/>
                                               <f:selectItem itemValue="Putting"/>
                                               <f:selectItem itemValue="Attitude"/>
                                          </h:selectOneMenu>
                                     </span>
                                     <span class="error">
                                          <h:graphicImage value="/img/error.gif" rendered="#{not empty facesMessages.getCurrentMessagesForControl('category')}" styleClass="errors"/>
                                          <h:message for="category" styleClass="errors"/>
                                     </span>
                                </div>
            
                                <div class="prop">
                                     <h:outputLabel styleClass="name" for="content">Content <span class="required">*</span></h:outputLabel>
                                     <span class="value">
                                          <h:inputTextarea id="content" value="#{tip.content}" cols="20" rows="4" style="width: 200px;" required="true"/>
                                     </span>
                                     <span class="error">
                                          <h:graphicImage value="/img/error.gif" rendered="#{not empty facesMessages.getCurrentMessagesForControl('content')}" styleClass="errors"/>
                                          <h:message for="content" styleClass="errors"/>
                                     </span>
                                </div>
            
                                <div style="clear: both;">
                                     <span class="required">*</span> required fields
                                </div>
            
                                <div class="actionButtons">
                                     <h:commandButton action="#{tipAction.add(tip)}" value="Submit Tip"/>
                                </div>
                                
                           </rich:simpleTogglePanel>
                      </h:form>



            tipAction:


            @Name("tipAction")
            public class TipAction {
            
                 @Logger private Log log;
            
                 @In     private EntityManager entityManager;
            
                @In private FacesMessages facesMessages;
                
                 @DataModel(scope = ScopeType.PAGE)
                 private List<GolfTip> tips;
            
                 @DataModelSelection
                 @Out(required = false)
                 private GolfTip activeTip;
            
                 @Factory("tips")
                 public void retrieveAllTips() {
                      log.info("Factory for tips called. Retrieving all golf tips...");
                      tips = (List<GolfTip>) entityManager.createQuery("select t from GolfTip t").getResultList();
                 }
            
                 public void add(GolfTip tip)
                 {
                      log.info("tipAction.add(GolfTip) action called");
                      if (tip.getContent().trim().length() == 0) {
                           FacesMessages.instance().add("Please provide a tip from which we may all learn.");
                           return;
                      }
            
                      log.info("Adding new golf tip...");
                      entityManager.persist(tip);
                      activeTip = tip;
                      facesMessages.add("Thanks for the tip, #{activeTip.author}!");
                      retrieveAllTips();
            
                      // required to reset form (because the submitted GolfTip is still populated)
                      // another option is to outject a null value to the context variable tip
                      Contexts.removeFromAllContexts("tip");
                 }
            
                 public void delete() {
                      log.info("tipAction.delete() action called");
                      log.info("Removing golf tip...");
                      activeTip = entityManager.find(GolfTip.class, activeTip.getId());
                      entityManager.remove(activeTip);
                      facesMessages.add("The selected golf tip, contributed by #{activeTip.author}, has been deleted.");
                      retrieveAllTips();
                 }
            }
            

            • 3. Re: Seam newbie question - default db field values
              dzakharov.dmitri.zakharov.gmail.com

              Thanks for the leads Arbi.


              Here's what I found in my project... I generated it as EAR project. And here's what seam-gen generated for me. The action of my Save button in ClaimEdit.xhtml looks like this:


              <div class="actionButtons">
              
                  <h:commandButton id="save"
                                value="Save"
                               action="#{claimHome.persist}"
                             disabled="#{!claimHome.wired}"
                             rendered="#{!claimHome.managed}"/>
              ...



              As far as I understand the action method persist() of the claimHome is called. ClaimHome class contains the following code:



              @Name("claimHome")
              public class ClaimHome extends EntityHome<Claim> {
              
                   @In(create = true)
                   ClaimStatusHome claimStatusHome;
                   @In(create = true)
                   ExporterHome exporterHome;
                   @In(create = true)
                   TransmissionHome transmissionHome;
              
                   public void setClaimClaimId(Integer id) {
                        setId(id);
                   }
              
                   public Integer getClaimClaimId() {
                        return (Integer) getId();
                   }
              
                   @Override
                   protected Claim createInstance() {
                        Claim claim = new Claim();
                        return claim;
                   }
              
                   public void wire() {
                        getInstance();
                        ClaimStatus claimStatus = claimStatusHome.getDefinedInstance();
                        if (claimStatus != null) {
                             getInstance().setClaimStatus(claimStatus);
                        }
                        Exporter exporter = exporterHome.getDefinedInstance();
                        if (exporter != null) {
                             getInstance().setExporter(exporter);
                        }
                        Transmission transmission = transmissionHome.getDefinedInstance();
                        if (transmission != null) {
                             getInstance().setTransmission(transmission);
                        }
                   }
              
                   public boolean isWired() {
                        if (getInstance().getClaimStatus() == null)
                             return false;
                        if (getInstance().getExporter() == null)
                             return false;
                        return true;
                   }
              
                   public Claim getDefinedInstance() {
                        return isIdDefined() ? getInstance() : null;
                   }
              
                   public List<Reject> getRejects() {
                        return getInstance() == null ? null : new ArrayList<Reject>(
                                  getInstance().getRejects());
                   }
              
              }



              I double checked the API docs and found that persist() method comes from the class EntityHome which ClaimHome extends. So my guess is that I should add another method to ClaimHome class, something like



              public void add()
              {
                  // ... set constants and current date here
              
                  persist();
              
              }
              



              I'll try it out and let you know.


              Thank you.

              • 4. Re: Seam newbie question - default db field values
                dzakharov.dmitri.zakharov.gmail.com

                Arbi, thanks alot for the tips again.


                Here's the method that I added to ClaimHome class that does the trick:



                ...
                @Override
                public String persist() {
                    Claim c = getInstance();
                    c.setCreateDate(new Date());
                    c.setCreateApplication("credits");
                    //TODO: set with the current application user 
                    //c.setCreateUser("");
                          
                    return super.persist();
                }
                ...