Search code examples
jpaseamvalidationfacelets

How to compare and validate 2 fields when persisting an entity using Facelets + JPA?


I am using Seam 2.2 with Facelets and I need to validate 2 fields from a JPA entity comparing both to check its values before insert.

Here is fragment from my enttity:

@Entity
@Scope(ScopeType.CONVERSATION)
@Name("metaAbastecimento")
public class MetaAbastecimento  implements Serializable{
 private float abastecimentoMinimo;

 private float abastecimentoMaximo;


 @Column
 public float getAbastecimentoMinimo() {
  return abastecimentoMinimo;
 }

 @Column
 public float getAbastecimentoMaximo() {
  return abastecimentoMaximo;
 }

 public void setAbastecimentoMinimo(float abastecimentoMinimo) {
  this.abastecimentoMinimo = abastecimentoMinimo;
 }

 public void setAbastecimentoMaximo(float abastecimentoMaximo) {
  this.abastecimentoMaximo = abastecimentoMaximo;
 }
}

Than I have an xhtml which persists this entity:

<rich:panel>
        <f:facet name="header">Detalhe de Meta de Abastecimento</f:facet>


        <s:decorate id="abastecimentoMinimo" template="../layout/display.xhtml">
            <ui:define name="label">Meta(R$) de Abastecimento M&iacute;nimo</ui:define>
            <h:outputText value="#{metaAbastecimentoHome.instance.abastecimentoMinimo}">
            </h:outputText>
        </s:decorate>

        <s:decorate id="abastecimentoMaximo" template="../layout/display.xhtml">
            <ui:define name="label">Meta(R$) Abastecimento M&aacute;ximo</ui:define>
            <h:outputText value="#{metaAbastecimentoHome.instance.abastecimentoMaximo}"/>
        </s:decorate>

        <div style="clear:both"/>

    </rich:panel>

I need to compare these 2 fields before I persist them and check if they are different than 0f and also if abastecimentoMinimo is smaller than abastecimentoMaximo. How can I do this using Seam + Facelets + JPA?

[]s


Solution

  • Cross field validation in JSF 1 is not possible. So you have to do this manually.

    This can in your case either be done by using the @PrePersist and @PreUpdate, or you can do this in your action method manually.

    One tip for you. Avoid having Entity beans as seam components. It's better to make a separate seam component.

    The reasons for this are:

    Entity beans may be bound to a context variable and function as a seam component. Because entities have a persistent identity in addition to their contextual identity, entity instances are usually bound explicitly in Java code, rather than being instantiated implicitly by Seam.

    Entity bean components do not support bijection or context demarcation. Nor does invocation of an entity bean trigger validation. Entity beans are not usually used as JSF action listeners, but do often function as backing beans that provide properties to JSF components for display or form submission. In particular, it is common to use an entity as a backing bean, together with a stateless session bean action listener to implement create/update/delete type functionality. By default, entity beans are bound to the conversation context. They may never be bound to the stateless context.

    Note that it in a clustered environment is somewhat less efficient to bind an entity bean directly to a conversation or session scoped Seam context variable than it would be to hold a reference to the entity bean in a stateful session bean. For this reason, not all Seam applications define entity beans to be Seam components.

    @Entity
    public class MetaAbastecimento {
      .....
    
        //If check fails you can throw exception, thus rollback will occur, and commit will not be made
        @PrePersist
        @PreUpdate
        public void check() {
          if(abastecimentoMinimo == 0f || abastecimentoMaximo == 0f && abastecimentoMinimo > abastecimentoMaximo) 
            throw new RuntimeException("Failed!");
        }
    }