Keith Donald opened SPR-7651 and commented

Have you seen the new @ScriptAssert constraint annotation in Hibernate Validator 4.1.0:

* A class-level constraint, that evaluates a script expression against the
* annotated element. This constraint can be used to implement validation
* routines, that depend on multiple attributes of the annotated element.

It'd be great if SpEL could be plugged in as the script expression language:

* For evaluation of expressions the Java Scripting API as defined by <a
* href="http://jcp.org/en/jsr/detail?id=223">JSR 223</a>
* ("Scripting for the Java<sup>TM</sup> Platform") is used. Therefore an
* implementation of that API must part of the class path. This is automatically
* the case when running on Java 6. For older Java versions, the JSR 223 RI can
* be added manually to the class path.

I noticed this when I needed a @FieldMatch type capability for doing field confirmation constraints. There is no such thing in JSR 303, Hibernate Validator, or Apachje Bean Validator, so I rolled my own class-level constraint from an example I found but then discovered this annotation after upgrading to Hibernate Validator 4.1.0.

References: http://stackoverflow.com/questions/1972933/cross-field-validation-with-hibernate-validator-jsr-303


Affects: 3.0.3

Referenced from: commits https://github.com/spring-projects/spring-framework/commit/9008e08171c0e284f338d44dab672c48cf98a93e

6 votes, 5 watchers

Comment From: spring-projects-issues

James Howe commented

Giving this a little kick as it seems to be stuck Waiting for Triage but with no Assignee.

Comment From: OrangeDog

Again in a situation where this feature would've made everything easier.

Comment From: rubensa

I've just tried https://github.com/eobermuhlner/spel-scriptengine

You just need too add this to your pom.xml

    <dependency>
      <groupId>ch.obermuhlner</groupId>
      <artifactId>spel-scriptengine</artifactId>
      <version>1.0.0</version>
    </dependency>

And then use it with Hibernate Validator like this:

package org.eu.rubensa.model;

import java.time.Instant;

import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.SequenceGenerator;
import javax.persistence.Table;
import javax.validation.constraints.Min;
import javax.validation.constraints.NotNull;

import org.hibernate.validator.constraints.ScriptAssert;

import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.NoArgsConstructor;

@Entity
@Table(name = "sample")
@Data
@EqualsAndHashCode(callSuper = false)
@NoArgsConstructor
@AllArgsConstructor
@ScriptAssert.List({
    // Month valiadation
    @ScriptAssert(lang = "spel", alias = "_this", script = "#_this.getLower() == null || #_this.getHigher() == null || #_this.getHigher().compareTo(#_this.getLower()) >= 0", reportOn = "finalMonth", message = "{org.eu.rubensa.validation.LowerGreaterThanHigher.message}"),
    // Instant validation
    @ScriptAssert(lang = "spel", alias = "_this", script = "#_this.getStart() == null || #_this.getEnd() == null || #_this.getEnd().compareTo(#_this.getStart()) >= 0", reportOn = "fechaFinPresentacion", message = "{org.eu.rubensa.validation.StartGreaterThanEnd.message}") })
public class SampleEntity {
  @Id
  @Column(name = "id", nullable = false)
  @GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "sample_seq")
  @SequenceGenerator(name = "sample_seq", sequenceName = "sample_seq", allocationSize = 1)
  private Long id;

  @Column(name = "lower", nullable = false)
  @NotNull
  @Min(1)
  private Integer lower;

  @Column(name = "higher", nullable = false)
  @NotNull
  @Min(1)
  private Integer higher;

  @Column(name = "start", nullable = true)
  private Instant start;

  @Column(name = "end", nullable = true)
  private Instant end;
}

Comment From: sbrannen

We do not have any plans to implement a javax.script.ScriptEngine for SpEL, and there is already a third-party SpEL ScriptEngine as mentioned by @rubensa.

In light of that, I am closing this issue.