Icon

Software Engineering, Architecture, Web Development and beyond…

Bean Validation (JSR-303) and validating Cron Expressions, extending constraints

To validate cron expressions using bean validation stuff, the best practice is to write your own custom validators and to use quartz framework’s cron expression facilities.
To write your custom validator, you need to implement

ConstraintValidator<A extends java.lang.annotation.Annotation,T>

from javax.validation.* package.

public class CronExpressionValidator implements
        ConstraintValidator<CronExpression, String> {
 
    public void initialize(CronExpression cronExpression) {
        //To change body of implemented methods use File | Settings | File Templates.
    }
 
    public boolean isValid(String s, ConstraintValidatorContext constraintValidatorContext) {
        return org.quartz.CronExpression.isValidExpression(s);
    }
}

To validate cron expressions in isValid() method, the isValidExpression() static method is used from Quartz Framework. To add Quartz to our maven project add the following dependency into your pom:

        <dependency>
            <groupId>org.opensymphony.quartz</groupId>
            <artifactId>quartz</artifactId>
            <version>1.6.5</version>
            <type>jar</type>
            <scope>compile</scope>
        </dependency>

CronExpression defined as parameterized type is the annotation class that we will use for cron constraints and seems like following;

@Documented
@Constraint(validatedBy = CronExpressionValidator.class)
@Target({ METHOD, FIELD, ANNOTATION_TYPE, CONSTRUCTOR, PARAMETER })
@Retention(RetentionPolicy.RUNTIME)
public @interface CronExpression {
    String message() default "Cron expression is not valid!";
    Class<?>[] groups() default {};
    Class<? extends Payload>[] payload() default {};
}

@Documented indicates that annotations with a type are to be documented by javadoc and similar tools by default.
@Constraint(validatedBy=CronExpressionValidator.class) defines validator class.
@Target defines that this annotation is applicable to methods, fields, annotation types, constructors and parameters.
@Retention defines that the annotation is a runtime annotation not a compile time annotation like @SupressWarnings, @Override etc.

We are now ready to annotate our fields, parameters etc. with our new constraint just like this:

class MyCronBean {
    @NotNull
    @CronExpression
    private String cronExpression;
    /** setters and getters */
}

Best Practices: java.lang.NoSuchMethodError: javax.persistence.Persistence.getPersistenceUtil() JSR 303 Bean Validation and Hibernate validator

As soon as my form is submitted to be validated by Bean Validation facilities, i got the following exception:

java.lang.NoSuchMethodError: javax.persistence.Persistence.getPersistenceUtil()

After doing a little research i could solve the problem related to Persistence methods and Bean Validation (see Bean Validation JSR-303).
First of all, i needed to understand what the relation between Persistence and Validation is.
My Project includes Spring 3.1 and Hibernate 3.5 libraries. And i wanted to use JSR303 and annotations.

To enable Bean Validation facility in a spring project, Spring needs a default validator if you don’t give an explicit validator interface like this:

<mvc:annotation-driven validator="globalValidator"/>

globalValidator is a global validator interface, bean, which the developer must provide. But, I wanted to just make my fields be validated according to annotations. For that reason i added into my config just:

<mvc:annotation-driven/>

and added Hibernate-Validator 4.1 into my project.

(Solution) It seems that the Hibernate-Validator version 4.0 works only with J2EE 6 (JEE). Here is the stacktrace:

java.lang.NoSuchMethodError: javax.persistence.Persistence.getPersistenceUtil()Ljavax/persistence/PersistenceUtil;
at org.hibernate.validator.engine.resolver.JPATraversableResolver.isReachable(JPATraversableResolver.java:62)
at org.hibernate.validator.engine.resolver.DefaultTraversableResolver.isReachable(DefaultTraversableResolver.java:94)
at org.hibernate.validator.engine.resolver.SingleThreadCachedTraversableResolver.isReachable(SingleThreadCachedTraversableResolver.java:47)
at org.hibernate.validator.engine.ValidatorImpl.isValidationRequired(ValidatorImpl.java:757)
at org.hibernate.validator.engine.ValidatorImpl.validateConstraint(ValidatorImpl.java:324)
at org.hibernate.validator.engine.ValidatorImpl.validateConstraintsForRedefinedDefaultGroup(ValidatorImpl.java:273)
at org.hibernate.validator.engine.ValidatorImpl.validateConstraintsForCurrentGroup(ValidatorImpl.java:256)
at org.hibernate.validator.engine.ValidatorImpl.validateInContext(ValidatorImpl.java:210)
at org.hibernate.validator.engine.ValidatorImpl.validate(ValidatorImpl.java:119)
at org.springframework.validation.beanvalidation.SpringValidatorAdapter.validate(SpringValidatorAdapter.java:86)
at org.springframework.validation.DataBinder.validate(DataBinder.java:692)

Here is the Persistence class API doc of J2EE5:

http://download.oracle.com/javaee/5/api/javax/persistence/Persistence.html

and PersistenceUtil has no such a method called getPersistenceUtil() while Persistence has this method in the sixth version:

http://download.oracle.com/javaee/6/api/javax/persistence/Persistence.html

Don’t use Hibernate-Validator 4.1 with J2EE5 otherwise you could get a headache.

erhan

Author


Hello, I'm Erhan Bagdemir and this is my blog. I talk about Java, J2EE, Frameworks, web application development, OOAD and various other topics often related to programming.

Erhan Bagdemir  Profil von Erhan Bagdemir auf LinkedIn anzeigen

ebagdemir on Stackoverflow

ebagdemir on Twitter

    Hamburg

    Slideshow