8 Replies Latest reply on Jul 5, 2007 12:21 PM by nebukadnezzar

    EntityManager in custom validator

    shakenbrain

      Can you inject an EntityManager into a custom JSF validator class, assuming you've made the validator a seam component? I've tried, but the entityManager is always null.

        • 1. Re: EntityManager in custom validator
          pmuir

          Yes, use the @Converter annotation to register your converter (rather than registering it through faces-config.xml), use the @Transactional annotation on the getAsXXX methods, and do a entityManager.joinTransaction() before accessing the entityManager. We seem to be missing docs for @Converter and @Validator so post back if you are stuck.

          • 2. Re: EntityManager in custom validator
            shakenbrain

            Thanks for the quick response. That's fantastic. I think I'm almost there, but I'm not sure how to reference the validator from the page; it's not going to be with the <f:validator> tag, right?

            @Name("prefixValidator")
            @Validator
            public class PrefixValidator implements javax.faces.validator.Validator {
            
             @In
             EntityManager entityManager;
            
             @Transactional
             public void validate(FacesContext context, UIComponent component, Object value)
             throws ValidatorException {
            
             entityManager.joinTransaction();
            
             String prefix = (String) value;
            
             Query q = entityManager.createQuery("from Organization o where o.prefix = :prefix");
             q.setParameter("prefix", prefix.toUpperCase());
             if (q.getResultList().size() > 0) {
             throw new ValidatorException(makeMessage("Prefix is being used already"));
             }
             }
            ...
            }

            <s:decorate id="prefixDecorator" template="decorateField.xhtml">
             <ui:define name="label">Prefix</ui:define>
             <h:inputText id="prefix" size="4" value="#{organizationEditor.instance.prefix}" required="true" disabled="#{!organizationEditor.new}">
             <f:validator validatorId="prefixValidator"/>
             <a:support event="onblur" reRender="prefixDecorator"/>
             </h:inputText>
            </s:decorate>




            • 3. Re: EntityManager in custom validator
              shakenbrain

              Turns out that's exactly the way you do it. I had to make my validator class implement Serializable. For reference, here's the code:

              @Name("prefixValidator")
              @Validator
              public class PrefixValidator implements javax.faces.validator.Validator, Serializable {
              
               @In
               EntityManager entityManager;
              
               @Transactional
               public void validate(FacesContext context, UIComponent component, Object value)
               throws ValidatorException {
              
               entityManager.joinTransaction();
              
               String prefix = (String) value;
              
               Query q = entityManager.createQuery("from Organization o where o.prefix = :prefix");
               q.setParameter("prefix", prefix.toUpperCase());
               if (q.getResultList().size() > 0) {
               throw new ValidatorException(makeMessage("Prefix is being used already"));
               }
               }
              
               private FacesMessage makeMessage(String s) {
               FacesMessage message = new FacesMessage();
               message.setDetail(s);
               message.setSummary(s);
               message.setSeverity(FacesMessage.SEVERITY_ERROR);
               return message;
               }
              }


              <s:decorate id="prefixDecorator" template="decorateField.xhtml">
               <ui:define name="label">Prefix</ui:define>
               <h:inputText id="prefix" size="4" value="#{organizationEditor.instance.prefix}" required="true" disabled="#{!organizationEditor.new}">
               <f:validator validatorId="prefixValidator"/>
               <a:support event="onblur" reRender="prefixDecorator"/>
               </h:inputText>
               </s:decorate>


              • 4. Re: EntityManager in custom validator
                monkeyden

                Now that is sweet. I feel like I just found a $20 on the ground.

                • 5. Re: EntityManager in custom validator

                  Can the this be used with a SLSB to avoid the @Transactional annotation and the entityManager.joinTransaction()?

                  • 6. Re: EntityManager in custom validator
                    pmuir

                    Give it a go, let us know how you get on :)

                    • 7. Re: EntityManager in custom validator

                      It seems to work fine for a SLSB.

                      • 8. Re: EntityManager in custom validator
                        nebukadnezzar

                        i've got some problems with the validator...

                        When the onblur-event from ajax4jsf is triggered

                        a SelectOneMenu in the form is redrawn too and the selectItems are from an EntityQuery.
                        I always get an exception "the transaction is not active" in the function getResultList from the EntityQuery