diff --git a/ebean-api/pom.xml b/ebean-api/pom.xml index 1edc0a655..80d8db37a 100644 --- a/ebean-api/pom.xml +++ b/ebean-api/pom.xml @@ -102,20 +102,6 @@ true - - - javax.validation - validation-api - 1.1.0.Final - true - - - jakarta.validation - jakarta.validation-api - 3.0.0 - true - - javax.servlet javax.servlet-api diff --git a/ebean-core/src/main/java/io/ebeaninternal/server/deploy/meta/DeployBeanProperty.java b/ebean-core/src/main/java/io/ebeaninternal/server/deploy/meta/DeployBeanProperty.java index bccc21bcc..5b9e8d687 100644 --- a/ebean-core/src/main/java/io/ebeaninternal/server/deploy/meta/DeployBeanProperty.java +++ b/ebean-core/src/main/java/io/ebeaninternal/server/deploy/meta/DeployBeanProperty.java @@ -34,7 +34,6 @@ import javax.persistence.EmbeddedId; import javax.persistence.FetchType; import javax.persistence.Id; import javax.persistence.Version; -import javax.validation.constraints.Size; import java.lang.annotation.Annotation; import java.lang.reflect.Field; import java.lang.reflect.Type; @@ -1140,24 +1139,6 @@ public class DeployBeanProperty { return result; } - public List getMetaAnnotationJavaxSize() { - final List size = getMetaAnnotations(Size.class); - final List lists = getMetaAnnotations(Size.List.class); - for (Size.List list : lists) { - Collections.addAll(size, list.value()); - } - return size; - } - - public List getMetaAnnotationJakartaSize() { - final List size = getMetaAnnotations(jakarta.validation.constraints.Size.class); - final List lists = getMetaAnnotations(jakarta.validation.constraints.Size.List.class); - for (jakarta.validation.constraints.Size.List list : lists) { - Collections.addAll(size, list.value()); - } - return size; - } - public Formula getMetaAnnotationFormula(Platform platform) { Formula fallback = null; for (Annotation ann : metaAnnotations) { diff --git a/ebean-core/src/main/java/io/ebeaninternal/server/deploy/parse/AnnotationAssocOnes.java b/ebean-core/src/main/java/io/ebeaninternal/server/deploy/parse/AnnotationAssocOnes.java index aa38d93e6..d313ce925 100644 --- a/ebean-core/src/main/java/io/ebeaninternal/server/deploy/parse/AnnotationAssocOnes.java +++ b/ebean-core/src/main/java/io/ebeaninternal/server/deploy/parse/AnnotationAssocOnes.java @@ -26,7 +26,6 @@ import javax.persistence.JoinTable; import javax.persistence.ManyToOne; import javax.persistence.OneToOne; import javax.persistence.PrimaryKeyJoinColumn; -import javax.validation.constraints.NotNull; /** * Read the deployment annotations for Associated One beans. @@ -115,21 +114,10 @@ public class AnnotationAssocOnes extends AnnotationAssoc { if (nonNull != null) { prop.setNullable(false); } - if (javaxValidationAnnotations) { - NotNull notNull = get(prop, NotNull.class); - if (notNull != null && isEbeanValidationGroups(notNull.groups())) { - prop.setNullable(false); - // overrides optional attribute of ManyToOne etc - prop.getTableJoin().setType(SqlJoinType.INNER); - } - } - if (jakartaValidationAnnotations) { - jakarta.validation.constraints.NotNull notNull = get(prop, jakarta.validation.constraints.NotNull.class); - if (notNull != null && isEbeanValidationGroups(notNull.groups())) { - prop.setNullable(false); - // overrides optional attribute of ManyToOne etc - prop.getTableJoin().setType(SqlJoinType.INNER); - } + if (readConfig.isValidationNotNull(prop)) { + // overrides optional attribute of ManyToOne etc + prop.setNullable(false); + prop.getTableJoin().setType(SqlJoinType.INNER); } // check for manually defined joins diff --git a/ebean-core/src/main/java/io/ebeaninternal/server/deploy/parse/AnnotationFields.java b/ebean-core/src/main/java/io/ebeaninternal/server/deploy/parse/AnnotationFields.java index 413929098..8079f156f 100644 --- a/ebean-core/src/main/java/io/ebeaninternal/server/deploy/parse/AnnotationFields.java +++ b/ebean-core/src/main/java/io/ebeaninternal/server/deploy/parse/AnnotationFields.java @@ -69,8 +69,6 @@ import javax.persistence.Temporal; import javax.persistence.TemporalType; import javax.persistence.Transient; import javax.persistence.Version; -import javax.validation.constraints.NotNull; -import javax.validation.constraints.Size; import java.sql.Types; import java.util.Set; import java.util.UUID; @@ -258,48 +256,19 @@ public class AnnotationFields extends AnnotationParser { } private void initValidation(DeployBeanProperty prop) { - if (javaxValidationAnnotations) { - NotNull notNull = get(prop, NotNull.class); - if (notNull != null && isEbeanValidationGroups(notNull.groups())) { - // Not null on all validation groups so enable - // DDL generation of Not Null Constraint - prop.setNullable(false); - } + if (readConfig.isValidationNotNull(prop)) { + prop.setNullable(false); } - if (jakartaValidationAnnotations) { - jakarta.validation.constraints.NotNull notNull = get(prop, jakarta.validation.constraints.NotNull.class); - if (notNull != null && isEbeanValidationGroups(notNull.groups())) { - // Not null on all validation groups so enable - // DDL generation of Not Null Constraint - prop.setNullable(false); - } - } - if (!prop.isLob()) { - // take the max size of all @Size annotations - int maxSize = -1; - if (javaxValidationAnnotations) { - for (Size size : prop.getMetaAnnotationJavaxSize()) { - if (size.max() < Integer.MAX_VALUE) { - maxSize = Math.max(maxSize, size.max()); - } - } - } - if (jakartaValidationAnnotations) { - for (jakarta.validation.constraints.Size size : prop.getMetaAnnotationJakartaSize()) { - if (size.max() < Integer.MAX_VALUE) { - maxSize = Math.max(maxSize, size.max()); - } - } - } - if (maxSize != -1) { + int maxSize = readConfig.maxValidationSize(prop); + if (maxSize > 0) { prop.setDbLength(maxSize); } } } private void initTenantId(DeployBeanProperty prop) { - if (javaxValidationAnnotations || jakartaValidationAnnotations) { + if (readConfig.checkValidationAnnotations()) { initValidation(prop); } if (has(prop, TenantId.class)) { diff --git a/ebean-core/src/main/java/io/ebeaninternal/server/deploy/parse/AnnotationParser.java b/ebean-core/src/main/java/io/ebeaninternal/server/deploy/parse/AnnotationParser.java index 8a27981b4..af015e1f5 100644 --- a/ebean-core/src/main/java/io/ebeaninternal/server/deploy/parse/AnnotationParser.java +++ b/ebean-core/src/main/java/io/ebeaninternal/server/deploy/parse/AnnotationParser.java @@ -9,7 +9,6 @@ import io.ebeaninternal.server.deploy.meta.DeployBeanPropertyAssocOne; import javax.persistence.AttributeOverride; import javax.persistence.CascadeType; import javax.persistence.Column; -import javax.validation.groups.Default; import java.util.HashMap; import java.util.Map; import java.util.Set; @@ -26,17 +25,11 @@ public abstract class AnnotationParser extends AnnotationBase { final Class beanType; - final boolean javaxValidationAnnotations; - - final boolean jakartaValidationAnnotations; - final ReadAnnotationConfig readConfig; AnnotationParser(DeployBeanInfo info, ReadAnnotationConfig readConfig) { super(info.getUtil()); this.readConfig = readConfig; - this.javaxValidationAnnotations = readConfig.isJavaxValidationAnnotations(); - this.jakartaValidationAnnotations = readConfig.isJakartaValidationAnnotations(); this.info = info; this.beanType = info.getDescriptor().getBeanType(); this.descriptor = info.getDescriptor(); @@ -130,17 +123,6 @@ public abstract class AnnotationParser extends AnnotationBase { } } - /** - * Return true if the validation groups are {@link Default} (respectively empty) - * can be applied to DDL generation. - */ - boolean isEbeanValidationGroups(Class[] groups) { - if (!util.isUseValidationNotNull()) { - return false; - } - return groups.length == 0 || groups.length == 1 && Default.class.isAssignableFrom(groups[0]); - } - String[] convertColumnNames(String[] columnNames) { for (int i = 0; i < columnNames.length; i++) { columnNames[i] = databasePlatform.convertQuotedIdentifiers(columnNames[i]); diff --git a/ebean-core/src/main/java/io/ebeaninternal/server/deploy/parse/InitMetaJakartaValidationAnnotation.java b/ebean-core/src/main/java/io/ebeaninternal/server/deploy/parse/InitMetaJakartaValidationAnnotation.java deleted file mode 100644 index 41ea9a8c7..000000000 --- a/ebean-core/src/main/java/io/ebeaninternal/server/deploy/parse/InitMetaJakartaValidationAnnotation.java +++ /dev/null @@ -1,11 +0,0 @@ -package io.ebeaninternal.server.deploy.parse; - -import jakarta.validation.constraints.Size; - -class InitMetaJakartaValidationAnnotation { - - static void init(ReadAnnotationConfig readConfig) { - readConfig.addMetaAnnotation(Size.class); - readConfig.addMetaAnnotation(Size.List.class); - } -} diff --git a/ebean-core/src/main/java/io/ebeaninternal/server/deploy/parse/InitMetaJavaxValidationAnnotation.java b/ebean-core/src/main/java/io/ebeaninternal/server/deploy/parse/InitMetaJavaxValidationAnnotation.java deleted file mode 100644 index 495d26ff5..000000000 --- a/ebean-core/src/main/java/io/ebeaninternal/server/deploy/parse/InitMetaJavaxValidationAnnotation.java +++ /dev/null @@ -1,11 +0,0 @@ -package io.ebeaninternal.server.deploy.parse; - -import javax.validation.constraints.Size; - -class InitMetaJavaxValidationAnnotation { - - static void init(ReadAnnotationConfig readConfig) { - readConfig.addMetaAnnotation(Size.class); - readConfig.addMetaAnnotation(Size.List.class); - } -} diff --git a/ebean-core/src/main/java/io/ebeaninternal/server/deploy/parse/ReadAnnotationConfig.java b/ebean-core/src/main/java/io/ebeaninternal/server/deploy/parse/ReadAnnotationConfig.java index d7d46e9ce..1daf37564 100644 --- a/ebean-core/src/main/java/io/ebeaninternal/server/deploy/parse/ReadAnnotationConfig.java +++ b/ebean-core/src/main/java/io/ebeaninternal/server/deploy/parse/ReadAnnotationConfig.java @@ -3,8 +3,10 @@ package io.ebeaninternal.server.deploy.parse; import io.ebean.annotation.Aggregation; import io.ebean.annotation.Formula; import io.ebean.annotation.Where; +import io.ebean.config.ClassLoadConfig; import io.ebean.config.DatabaseConfig; import io.ebeaninternal.server.deploy.generatedproperty.GeneratedPropertyFactory; +import io.ebeaninternal.server.deploy.meta.DeployBeanProperty; import javax.persistence.Column; import java.util.HashSet; @@ -24,7 +26,9 @@ class ReadAnnotationConfig { private final boolean jakartaValidationAnnotations; private final boolean jacksonAnnotations; private final boolean idGeneratorAutomatic; - + private final boolean useValidationNotNull; + private final ReadValidationAnnotations javaxValidation; + private final ReadValidationAnnotations jakartaValidation; private final Set> metaAnnotations = new HashSet<>(); ReadAnnotationConfig(GeneratedPropertyFactory generatedPropFactory, String asOfViewSuffix, String versionsBetweenSuffix, DatabaseConfig config) { @@ -34,21 +38,32 @@ class ReadAnnotationConfig { this.disableL2Cache = config.isDisableL2Cache(); this.eagerFetchLobs = config.isEagerFetchLobs(); this.idGeneratorAutomatic = config.isIdGeneratorAutomatic(); - this.javaxValidationAnnotations = generatedPropFactory.getClassLoadConfig().isJavaxValidationAnnotationsPresent(); - this.jakartaValidationAnnotations = generatedPropFactory.getClassLoadConfig().isJakartaValidationAnnotationsPresent(); - this.jacksonAnnotations = generatedPropFactory.getClassLoadConfig().isJacksonAnnotationsPresent(); + this.useValidationNotNull = config.isUseValidationNotNull(); + ClassLoadConfig classLoadConfig = generatedPropFactory.getClassLoadConfig(); + this.javaxValidationAnnotations = classLoadConfig.isJavaxValidationAnnotationsPresent(); + this.jakartaValidationAnnotations = classLoadConfig.isJakartaValidationAnnotationsPresent(); + this.jacksonAnnotations = classLoadConfig.isJacksonAnnotationsPresent(); this.metaAnnotations.add(Column.class); this.metaAnnotations.add(Formula.class); this.metaAnnotations.add(Formula.List.class); this.metaAnnotations.add(Where.class); this.metaAnnotations.add(Where.List.class); this.metaAnnotations.add(Aggregation.class); + this.javaxValidation = javaxValidationAnnotations ? new ReadValidationAnnotationsJavax(this) : null; + this.jakartaValidation = jakartaValidationAnnotations ? new ReadValidationAnnotationsJakarta(this) : null; + if (jacksonAnnotations) { + InitMetaJacksonAnnotation.init(this); + } } - public void addMetaAnnotation(Class annotation) { + void addMetaAnnotation(Class annotation) { metaAnnotations.add(annotation); } + boolean checkValidationAnnotations() { + return javaxValidationAnnotations || jakartaValidationAnnotations; + } + GeneratedPropertyFactory getGeneratedPropFactory() { return generatedPropFactory; } @@ -73,14 +88,6 @@ class ReadAnnotationConfig { return idGeneratorAutomatic; } - boolean isJavaxValidationAnnotations() { - return javaxValidationAnnotations; - } - - boolean isJakartaValidationAnnotations() { - return jakartaValidationAnnotations; - } - boolean isJacksonAnnotations() { return jacksonAnnotations; } @@ -88,4 +95,35 @@ class ReadAnnotationConfig { public Set> getMetaAnnotations() { return metaAnnotations; } + + /** + * Return true if a NotNull validation annotation is on the property. + */ + boolean isValidationNotNull(DeployBeanProperty property) { + if (!useValidationNotNull) { + return false; + } + if (javaxValidation != null && javaxValidation.isValidationNotNull(property)) { + return true; + } + if (jakartaValidation != null && jakartaValidation.isValidationNotNull(property)) { + return true; + } + return false; + } + + /** + * Return the max size of all validation @Size annotations. + */ + int maxValidationSize(DeployBeanProperty prop) { + int maxSize = 0; + if (javaxValidation != null) { + maxSize = Math.max(maxSize, javaxValidation.maxSize(prop)); + } + if (jakartaValidation != null) { + maxSize = Math.max(maxSize, jakartaValidation.maxSize(prop)); + } + return maxSize; + } + } diff --git a/ebean-core/src/main/java/io/ebeaninternal/server/deploy/parse/ReadAnnotations.java b/ebean-core/src/main/java/io/ebeaninternal/server/deploy/parse/ReadAnnotations.java index 796a975aa..da2bc6030 100644 --- a/ebean-core/src/main/java/io/ebeaninternal/server/deploy/parse/ReadAnnotations.java +++ b/ebean-core/src/main/java/io/ebeaninternal/server/deploy/parse/ReadAnnotations.java @@ -14,15 +14,6 @@ public class ReadAnnotations { public ReadAnnotations(GeneratedPropertyFactory generatedPropFactory, String asOfViewSuffix, String versionsBetweenSuffix, DatabaseConfig config) { this.readConfig = new ReadAnnotationConfig(generatedPropFactory, asOfViewSuffix, versionsBetweenSuffix, config); - if (readConfig.isJavaxValidationAnnotations()) { - InitMetaJavaxValidationAnnotation.init(readConfig); - } - if (readConfig.isJakartaValidationAnnotations()) { - InitMetaJakartaValidationAnnotation.init(readConfig); - } - if (readConfig.isJacksonAnnotations()) { - InitMetaJacksonAnnotation.init(readConfig); - } } /** diff --git a/ebean-core/src/main/java/io/ebeaninternal/server/deploy/parse/ReadValidationAnnotations.java b/ebean-core/src/main/java/io/ebeaninternal/server/deploy/parse/ReadValidationAnnotations.java new file mode 100644 index 000000000..a2c0b8890 --- /dev/null +++ b/ebean-core/src/main/java/io/ebeaninternal/server/deploy/parse/ReadValidationAnnotations.java @@ -0,0 +1,19 @@ +package io.ebeaninternal.server.deploy.parse; + +import io.ebeaninternal.server.deploy.meta.DeployBeanProperty; + +/** + * Reads validation NotNull and Size annotations for mapping. + */ +interface ReadValidationAnnotations { + + /** + * Return true if the property has a NotNull validation annotation. + */ + boolean isValidationNotNull(DeployBeanProperty property); + + /** + * Return the max value of the Size validation annotations on the property. + */ + int maxSize(DeployBeanProperty property); +} diff --git a/ebean-core/src/main/java/io/ebeaninternal/server/deploy/parse/ReadValidationAnnotationsJakarta.java b/ebean-core/src/main/java/io/ebeaninternal/server/deploy/parse/ReadValidationAnnotationsJakarta.java new file mode 100644 index 000000000..016e9f13a --- /dev/null +++ b/ebean-core/src/main/java/io/ebeaninternal/server/deploy/parse/ReadValidationAnnotationsJakarta.java @@ -0,0 +1,51 @@ +package io.ebeaninternal.server.deploy.parse; + +import io.ebean.util.AnnotationUtil; +import io.ebeaninternal.server.deploy.meta.DeployBeanProperty; +import jakarta.validation.constraints.NotNull; +import jakarta.validation.constraints.Size; +import jakarta.validation.groups.Default; + +import java.util.Collections; +import java.util.List; + +/** + * Jakarta validation annotations reader. + */ +class ReadValidationAnnotationsJakarta implements ReadValidationAnnotations { + + ReadValidationAnnotationsJakarta(ReadAnnotationConfig readConfig) { + readConfig.addMetaAnnotation(Size.class); + readConfig.addMetaAnnotation(Size.List.class); + } + + @Override + public boolean isValidationNotNull(DeployBeanProperty property) { + NotNull notNull = AnnotationUtil.get(property.getField(), NotNull.class); + return (notNull != null && isEbeanValidationGroups(notNull.groups())); + } + + private boolean isEbeanValidationGroups(Class[] groups) { + return groups.length == 0 || groups.length == 1 && Default.class.isAssignableFrom(groups[0]); + } + + @Override + public int maxSize(DeployBeanProperty property) { + int maxSize = 0; + for (Size size : getMetaAnnotationJavaxSize(property)) { + if (size.max() < Integer.MAX_VALUE) { + maxSize = Math.max(maxSize, size.max()); + } + } + return maxSize; + } + + private List getMetaAnnotationJavaxSize(DeployBeanProperty prop) { + final List size = prop.getMetaAnnotations(Size.class); + final List lists = prop.getMetaAnnotations(Size.List.class); + for (Size.List list : lists) { + Collections.addAll(size, list.value()); + } + return size; + } +} diff --git a/ebean-core/src/main/java/io/ebeaninternal/server/deploy/parse/ReadValidationAnnotationsJavax.java b/ebean-core/src/main/java/io/ebeaninternal/server/deploy/parse/ReadValidationAnnotationsJavax.java new file mode 100644 index 000000000..a690e69de --- /dev/null +++ b/ebean-core/src/main/java/io/ebeaninternal/server/deploy/parse/ReadValidationAnnotationsJavax.java @@ -0,0 +1,52 @@ +package io.ebeaninternal.server.deploy.parse; + +import io.ebean.util.AnnotationUtil; +import io.ebeaninternal.server.deploy.meta.DeployBeanProperty; + +import javax.validation.constraints.NotNull; +import javax.validation.constraints.Size; +import javax.validation.groups.Default; +import java.util.Collections; +import java.util.List; + +/** + * Javax validation annotations reader. + */ +class ReadValidationAnnotationsJavax implements ReadValidationAnnotations { + + ReadValidationAnnotationsJavax(ReadAnnotationConfig readConfig) { + readConfig.addMetaAnnotation(Size.class); + readConfig.addMetaAnnotation(Size.List.class); + } + + @Override + public boolean isValidationNotNull(DeployBeanProperty property) { + NotNull notNull = AnnotationUtil.get(property.getField(), NotNull.class); + return (notNull != null && isEbeanValidationGroups(notNull.groups())); + } + + private boolean isEbeanValidationGroups(Class[] groups) { + return groups.length == 0 || groups.length == 1 && Default.class.isAssignableFrom(groups[0]); + } + + @Override + public int maxSize(DeployBeanProperty prop) { + int maxSize = 0; + for (Size size : getMetaAnnotationJavaxSize(prop)) { + if (size.max() < Integer.MAX_VALUE) { + maxSize = Math.max(maxSize, size.max()); + } + } + return maxSize; + } + + private List getMetaAnnotationJavaxSize(DeployBeanProperty prop) { + final List size = prop.getMetaAnnotations(Size.class); + final List lists = prop.getMetaAnnotations(Size.List.class); + for (Size.List list : lists) { + Collections.addAll(size, list.value()); + } + return size; + } + +}