4 Replies Latest reply on Oct 27, 2013 4:37 PM by Tomaz Cerar

    JSF 2.0, Custom Validations Defined outside the Application (Inside a Jboss Module) - Jboss AS 7/EAP 6.1

    Hlulani Mhlongo Newbie

      I'm all out of ideas as to what I'm doing wrong. I have my custom validation in a jar called my-validation.jar, the reason I've packaged this as a separete jar is that. we need to use the same validations rules across all out applications (about 15 different apps)


      package za.company.constraint;
      ...
      import org.slf4j.Logger;
      import org.slf4j.LoggerFactory;

      @Retention(RetentionPolicy.RUNTIME)
      @Target({
        ElementType.FIELD,
        ElementType.METHOD,
        ElementType.PARAMETER})
      @Documented
      @Constraint(validatedBy = {Email.EmailValidator.class})
      public @interface Email {

        String message() default "You have entered an invalid email address";

        Class<?>[] groups() default {};

        Class<? extends Payload>[] payload() default {};

        class EmailValidator implements ConstraintValidator<Email, String> {

        Logger LOG = LoggerFactory.getLogger(EmailValidator.class);

        @Override
        public void initialize(Email constraintAnnotation) {
        LOG.debug("INIT");
        }

        @Override
        public boolean isValid(String value, ConstraintValidatorContext context) {
        LOG.debug("VALIDATION: {}, CONTEXT: {}", value, context);

        if (value == null) {
        return false;
        }

        return value.matches("^[\\w.]+@[\\w]+([.]{1}[a-zA-Z]+){1}([.][a-zA-Z]+)?+$");
        }
        }
      }


      I created a Jboss 7 Module with this jar included:

      /opt/jboss/7.1.1/modules/za/fnb/common/main/my-validation.jar (my jar)/opt/jboss/7.1.1/modules/za/fnb/common/main/module.xml (This module is referenced by the test-web.war in the META-INF/MANIFEST.MF or WEB-INF/jboss-deployment-structure.xml)

      module.xml

      <module xmlns="urn:jboss:module:1.1" name="za.company.validation">

           <resources>

                <resource-root path="my-validation.jar"/>

           </resources>

           <dependencies>

                <module name="org.slf4j" />

                <module name="javax.api" />

           </dependencies>

      </module>

      I created a Web Application called test-web.war, consisting of a CID managed bean (Normal JSF Managed bean has the same issue) and a .xhtml page

      User.java (CDI managed bean)

      @Named

      @RequestScoped

      public class User {

       

      private String firstName;

      private String surname;

       

      @Accepted //This is not being validated

      private boolean accept;

       

      @Email //This is not being validated

      private String email;

       

      @Pattern (regexp = "(MALE|FEMALE|M|F)", message = "Invalid gender supplied (Correct values include MALE, FEMALE, F, M)") //Validated ok

      private String gender;

       

      public String getFirstName() {

           return firstName;

      }

       

      public void setFirstName(String firstName) {

           this.firstName = firstName;

      }

       

      public String getSurname() {

           return surname;

      }

      public void setSurname(String surname) {

           this.surname = surname;

      }

      //...

      }

      test.xhtml

      ...

      <table>

           <tr>

                <td><h:outputLabel for="firstName">First Name</h:outputLabel></td>

                <td><h:inputText id="firstName" value="#{user.firstName}" required="true" /></td>

           </tr>

           <tr>

                <td><h:outputLabel for="surname">Surname</h:outputLabel></td>

                <td><h:inputText id="surname" value="#{user.surname}" /> </td>

           </tr>

           <tr>

                <td><h:outputLabel for="gender">Gender</h:outputLabel></td>

                <td><h:inputText id="gender" value="#{user.gender}" /> </td>

           </tr>

           <tr>

                <td><h:outputLabel for="email">Email</h:outputLabel></td>

                <td><h:inputText id="email" value="#{user.email}" /></td>

           </tr>

      </table>

       

      <h:outputLabel for="accept"> <h:selectBooleanCheckbox id="accept" value="#{user.accept}" /> I accept that all information is correct</h:outputLabel>

       

      <h:commandButton action="#{testBacking.submitAction}" value="Submit" />

      ...

      The problem is that the @Email annotated field is NOT being validated, The only way I could make this work is to have the is to have the @Email definition in the same Source code (Inside the war) as the web application

      test-web/src/main/java/za/company/constraint/Email.java

      test-web/src/main/java/za/company/bean/User.java

      test-web/src/main/webapp/test.xhtml

      test-web/src/main/webapp/WEB-INF/faces-config.xml

      test-web/src/main/webapp/WEB-INF/beans.xml

      test-web/src/main/webapp/WEB-INF/web.xml

      test-web/pom.xml

      I've tried including this my-validation.jar inside the test-web.war/WEB-INF/lib/my-validation.jar with NO Luck.

      I thought maybe I'm missing the implementation of the validation, so I packaged the hibernate-validate jars with my project, No Luck test-web.war/WEB-INF/lib/hibernate-validator-4.2.0.Final.jar test-web.war/WEB-INF/lib/validation-api-1.0.0.GA.jar

      I've also tried packaging the faces-config.xml inside the my-validation.jar/META-INF/faces-config.xml

      The funny thing is that this WORKS on Glassfish 3 and even JBoss 6 but NOT Jboss AS 7 and itsjboss-EAP 6.1.0 Final big brother.

      My money is on the suspicion that with all this module concepts I might be missing a certain dependancy.

      Thank you in advance

        • 1. Re: JSF 2.0, Custom Validations Defined outside the Application (Inside a Jboss Module) - Jboss AS 7/EAP 6.1
          Tomaz Cerar Master

          Hi,

           

          you need to create jandex index of your jars that have annotations, and add that index to your module.

          then when you add dependency to that common module you need to explicitly import also annotations.

          2 of 2 people found this helpful
          • 2. Re: Re: JSF 2.0, Custom Validations Defined outside the Application (Inside a Jboss Module) - Jboss AS 7/EAP 6.1
            Hlulani Mhlongo Newbie
            you need to create jandex index of your jars that have annotations

             

            I've created the jandex index (jandex.idx) of my-validation.jar using maven:


            This is inside the pom.xml of my-validator project

                <plugin>

                      <groupId>org.jboss.jandex</groupId>

                      <artifactId>jandex-maven-plugin</artifactId>

                      <version>1.0.1</version>

                      <executions>

                          <execution>

                          <id>make-index</id>

                          <goals>

                                <goal>jandex</goal>

                          </goals>

                          <!-- phase is 'process-classes by default' -->

                          <configuration>

                          <!-- Nothing needed here for simple cases -->   

                          </configuration>

                          </execution>

                    </executions>

                </plugin>

             

            add that index to your module

             

            When I build this creates the jandex.idx file inside the generated jar, so the structure would look like this:

            my-validation.jar/META-INF/jandex.idx

             

            then I add this jar to the to jboss modules directory

            /opt/jboss/current/modules/za/company/validator/main/my-validator.jar

             

            then created the module.xml in the same directory:

             

                <module xmlns="urn:jboss:module:1.1" name="za.company.validator">

                    <resources>

                       <resource-root path="my-validator.jar" />

                    </resources>

                    <dependencies>

                       <module name="javax.api" />

                       <module name="org.slf4j"/>

                    </dependencies>

                </module>

            when you add dependency to that common module you need to explicitly import also annotations

            Inside the my application that uses the annotations (validate-web.war), I have a jboss-deployment-structure.xml file with the following content:

             

                <?xml version="1.0" encoding="UTF-8"?>

                <jboss-deployment-structure>

                    <deployment>

                        <exclusions>

                        </exclusions>

                        <dependencies>

                            <module name="za.company.validator" annotations="true" />

                        </dependencies>

                    </deployment>

                </jboss-deployment-structure>

             

            When I finally deploy the application (validate-web) I get the following logs (Similar to Problem packaging wsimport generated classes as AS 7 module):

            ...

              09:30:50,319 TRACE [org.jboss.modules] (MSC service thread 1-5) Finding class org.jboss.modules.ModuleClassLoader from Module "org.jboss.as.server:main" from local module loader @1ceb49a5 (roots: /opt/jboss/7.1.1/modules)

              09:30:50,321 TRACE [org.jboss.modules] (MSC service thread 1-5) Attempting to find all resources META-INF/jandex.idx in Module "za.company.validator:main" from local module loader @1ceb49a5 (roots: /opt/jboss/7.1.1/modules)

              09:30:50,324 TRACE [org.jboss.modules] (MSC service thread 1-5) Finding class org.jboss.jandex.IndexReader from Module "org.jboss.as.server:main" from local module loader @1ceb49a5 (roots: /opt/jboss/7.1.1/modules)

              09:30:50,326 TRACE [org.jboss.modules] (MSC service thread 1-5) Finding local class org.jboss.jandex.IndexReader from Module "org.jboss.jandex:main" from local module loader @1ceb49a5 (roots: /opt/jboss/7.1.1/modules)

              09:30:50,328 TRACE [org.jboss.modules] (MSC service thread 1-5) Loading class org.jboss.jandex.IndexReader locally from Module "org.jboss.jandex:main" from local module loader @1ceb49a5 (roots: /opt/jboss/7.1.1/modules)

              09:30:50,331 TRACE [org.jboss.modules] (MSC service thread 1-5) Attempting to define class org.jboss.jandex.IndexReader in Module "org.jboss.jandex:main" from local module loader @1ceb49a5 (roots: /opt/jboss/7.1.1/modules)

              09:30:50,333 TRACE [org.jboss.modules] (MSC service thread 1-5) Defined class org.jboss.jandex.IndexReader in Module "org.jboss.jandex:main" from local module loader @1ceb49a5 (roots: /opt/jboss/7.1.1/modules)

              09:30:50,335 TRACE [org.jboss.modules] (MSC service thread 1-5) Finding class org.jboss.jandex.UnsupportedVersion from Module "org.jboss.jandex:main" from local module loader @1ceb49a5 (roots: /opt/jboss/7.1.1/modules)

              09:30:50,336 TRACE [org.jboss.modules] (MSC service thread 1-5) Finding local class org.jboss.jandex.UnsupportedVersion from Module "org.jboss.jandex:main" from local module loader @1ceb49a5 (roots: /opt/jboss/7.1.1/modules)

              09:30:50,340 TRACE [org.jboss.modules] (MSC service thread 1-5) Loading class org.jboss.jandex.UnsupportedVersion locally from Module "org.jboss.jandex:main" from local module loader @1ceb49a5 (roots: /opt/jboss/7.1.1/modules)

              09:30:50,342 TRACE [org.jboss.modules] (MSC service thread 1-5) Attempting to define class org.jboss.jandex.UnsupportedVersion in Module "org.jboss.jandex:main" from local module loader @1ceb49a5 (roots: /opt/jboss/7.1.1/modules)

              09:30:50,345 TRACE [org.jboss.modules] (MSC service thread 1-5) Defined class org.jboss.jandex.UnsupportedVersion in Module "org.jboss.jandex:main" from local module loader @1ceb49a5 (roots: /opt/jboss/7.1.1/modules)

              09:30:50,348 TRACE [org.jboss.modules] (MSC service thread 1-5) Finding class org.jboss.jandex.PackedDataInputStream from Module "org.jboss.jandex:main" from local module loader @1ceb49a5 (roots: /opt/jboss/7.1.1/modules)

            ...

             

            This tells me that the jandex was loaded ok

             

            But sadly my validation annotation is still not invoked, is there a way to find out the exact dependancies for my module?

             

            Thanks again for such a prompt response

            • 3. Re: Re: JSF 2.0, Custom Validations Defined outside the Application (Inside a Jboss Module) - Jboss AS 7/EAP 6.1
              Hlulani Mhlongo Newbie

              After hours of guess work

              I finally figured out with dependency I needed, In my module I need to replace javax.api with javaee.api

               

              <module xmlns="urn:jboss:module:1.1" name="za.company.validator">

                  <resources>

                     <resource-root path="my-validator.jar" />

                  </resources>

                  <dependencies>

                  <!-- <module name="javax.api" /> -->

                      <module name="javaee.api" />

                      <module name="org.slf4j"/>

                  </dependencies>

              </module>

               

              Works like a charm, it would be nice to be able to figure out which dependencies are required for which annotations/modules

               

              Thanks a lot for pointing me in to the write direction.

              • 4. Re: Re: JSF 2.0, Custom Validations Defined outside the Application (Inside a Jboss Module) - Jboss AS 7/EAP 6.1
                Tomaz Cerar Master

                Hey,

                 

                for cases like that best thing to do is to enable trace logging for "org.jboss.modules"

                 

                General rule is that you need to add dependencies to modules from which you use annotations.

                otherwise classloader cannot resolve annotations when it is loading them.

                 

                 

                --

                tomaz