diff --git a/README.md b/README.md index 2cd837683..f2682079e 100644 --- a/README.md +++ b/README.md @@ -47,7 +47,7 @@ Here is a brief summary of each module: - `restx-factory`: RESTX Dependency Injection (DI) container. Brought as transitive dependency from restx-core. - `restx-classloader`: Hot reload / hot compile support - `restx-apidocs-doclet`: Some javadoc doclets used when generating apidocs -- `restx-core`: Core module, includes the REST framework, base security, JSON support, Validation, ... +- `restx-core`: Core module, includes the REST framework, base security, JSON support, ... *By relying on `restx-core` module, every modules described above will be retrieved as transitive dependencies* @@ -63,6 +63,7 @@ Here is a brief summary of each module: - `restx-specs-tests-java8`: Support for java 8 time API during specs tests - `restx-specs-server`: Enables using RESTX specs as HTTP mocks (running a server serving spec files responses given spec files requests). - `restx-factory-testing`: A module dedicated to test `restx-factory` features involving annotation processing. +- `restx-validation`: Bean validation support (based on `hibernate-validator` implementation) for POJOs BODY parameters #### MongoDB support through Jongo API: diff --git a/pom.xml b/pom.xml index 43d9267bc..e0389f76f 100644 --- a/pom.xml +++ b/pom.xml @@ -158,6 +158,7 @@ restx-shell-manager restx-build-shell restx-specs-shell + restx-validation diff --git a/restx-core-annotation-processor/src/main/java/restx/annotations/Annotations.java b/restx-core-annotation-processor/src/main/java/restx/annotations/Annotations.java new file mode 100644 index 000000000..eae7b200e --- /dev/null +++ b/restx-core-annotation-processor/src/main/java/restx/annotations/Annotations.java @@ -0,0 +1,38 @@ +package restx.annotations; + +import com.sun.tools.javac.code.Attribute; + +import javax.lang.model.element.AnnotationMirror; +import javax.lang.model.element.AnnotationValue; +import javax.lang.model.element.ExecutableElement; +import javax.lang.model.element.VariableElement; +import javax.lang.model.type.DeclaredType; +import java.util.ArrayList; +import java.util.List; +import java.util.Map; + +/** + * @author fcamblor + */ +public class Annotations { + public static String[] getAnnotationClassValuesAsFQCN(VariableElement p, Class annotationClazz, String methodName) { + List annotationMirrors = p.getAnnotationMirrors(); + for(AnnotationMirror annotationMirror : annotationMirrors){ + if(annotationMirror.getAnnotationType().toString().equals(annotationClazz.getCanonicalName())){ + for(Map.Entry entry : annotationMirror.getElementValues().entrySet()){ + if(entry.getKey().getSimpleName().contentEquals(methodName)){ + Attribute.Array array = (Attribute.Array) entry.getValue(); + + List fqcns = new ArrayList<>(); + for(Attribute attribute : array.getValue()) { + DeclaredType type = (DeclaredType) attribute.getValue(); + fqcns.add(type.toString()); + } + return fqcns.toArray(new String[fqcns.size()]); + } + } + } + } + return null; + } +} diff --git a/restx-core-annotation-processor/src/main/java/restx/annotations/processor/RestxAnnotationProcessor.java b/restx-core-annotation-processor/src/main/java/restx/annotations/processor/RestxAnnotationProcessor.java index 5c2aa30ae..af8859f2b 100644 --- a/restx-core-annotation-processor/src/main/java/restx/annotations/processor/RestxAnnotationProcessor.java +++ b/restx-core-annotation-processor/src/main/java/restx/annotations/processor/RestxAnnotationProcessor.java @@ -1,6 +1,7 @@ package restx.annotations.processor; import com.google.common.base.CaseFormat; +import com.google.common.base.Function; import com.google.common.base.Joiner; import com.google.common.base.Optional; import com.google.common.collect.*; @@ -14,6 +15,7 @@ import restx.http.HttpStatus; import restx.security.PermitAll; import restx.security.RolesAllowed; +import restx.validation.ValidatedFor; import javax.annotation.processing.RoundEnvironment; import javax.annotation.processing.SupportedAnnotationTypes; @@ -38,6 +40,13 @@ public class RestxAnnotationProcessor extends RestxAbstractProcessor { final Template routerTpl; + private static final Function FQN_EXTRACTOR = new Function(){ + @Override + public String apply(Class clazz) { + return clazz.getCanonicalName(); + } + }; + public RestxAnnotationProcessor() { routerTpl = Mustaches.compile(RestxAnnotationProcessor.class, "RestxRouter.mustache"); } @@ -163,11 +172,19 @@ private void buildResourceMethodParams(ResourceMethodAnnotation annotation, Reso } } + ValidatedFor validatedFor = p.getAnnotation(ValidatedFor.class); + + String[] validationGroups = new String[0]; + if(validatedFor != null) { + validationGroups = Annotations.getAnnotationClassValuesAsFQCN(p, ValidatedFor.class, "value"); + } + resourceMethod.parameters.add(new ResourceMethodParameter( p.asType().toString(), paramName, reqParamName, - parameterKind)); + parameterKind, + validationGroups)); } if (!pathParamNamesToMatch.isEmpty()) { error( @@ -492,8 +509,16 @@ private static class ResourceMethodParameter { final String name; final String reqParamName; final ResourceMethodParameterKind kind; + final List validationGroupsFQNs; + + private static final Function CLASS_APPENDER_FCT = new Function() { + @Override + public String apply(String fqn) { + return fqn+".class"; + } + }; - private ResourceMethodParameter(String type, String name, String reqParamName, ResourceMethodParameterKind kind) { + private ResourceMethodParameter(String type, String name, String reqParamName, ResourceMethodParameterKind kind, String[] validationGroupsFQNs) { Matcher guavaOptionalMatcher = guavaOptionalPattern.matcher(type); Matcher java8OptionalMatcher = java8OptionalPattern.matcher(type); this.realType = type; @@ -513,6 +538,15 @@ private ResourceMethodParameter(String type, String name, String reqParamName, R this.name = name; this.reqParamName = reqParamName; this.kind = kind; + this.validationGroupsFQNs = Arrays.asList(validationGroupsFQNs); + } + + public Optional joinedValidationGroupFQNExpression(){ + if(this.validationGroupsFQNs == null || this.validationGroupsFQNs.isEmpty()) { + return Optional.absent(); + } else { + return Optional.of(Joiner.on(", ").join(Iterables.transform(this.validationGroupsFQNs, CLASS_APPENDER_FCT))); + } } } @@ -539,7 +573,8 @@ public String fetchFromReqCode(ResourceMethodParameter parameter) { }, BODY { public String fetchFromReqCode(ResourceMethodParameter parameter) { - return String.format("checkValid(validator, body)", parameter.type); + Optional validationGroupsExpr = parameter.joinedValidationGroupFQNExpression(); + return String.format("checkValid(validator, body%s)", validationGroupsExpr.isPresent()?","+validationGroupsExpr.get():""); } }, CONTEXT { diff --git a/restx-core-annotation-processor/src/main/resources/restx/annotations/processor/RestxRouter.mustache b/restx-core-annotation-processor/src/main/resources/restx/annotations/processor/RestxRouter.mustache index b07e7c539..4b2ea2183 100644 --- a/restx-core-annotation-processor/src/main/resources/restx/annotations/processor/RestxRouter.mustache +++ b/restx-core-annotation-processor/src/main/resources/restx/annotations/processor/RestxRouter.mustache @@ -32,7 +32,7 @@ public class {{router}} extends RestxRouter { final EntityRequestBodyReaderRegistry readerRegistry, final EntityResponseWriterRegistry writerRegistry, final MainStringConverter converter, - final Validator validator, + final Optional validator, final RestxSecurityManager securityManager) { super( "{{routerGroup}}", "{{router}}", new RestxRoute[] { diff --git a/restx-core/pom.xml b/restx-core/pom.xml index 9e497b88b..83cb31b4e 100644 --- a/restx-core/pom.xml +++ b/restx-core/pom.xml @@ -25,7 +25,7 @@ 2.3 2.3.3 1.13 - 5.0.1.Final + 1.1.0.Final 0.9.9-RC1 1 4.11 @@ -94,9 +94,9 @@ ${slf4j-api.version} - org.hibernate - hibernate-validator - ${hibernate-validator.version} + javax.validation + validation-api + ${validation-api.version} org.reflections diff --git a/restx-core/src/main/java/restx/validation/ValidatedFor.java b/restx-core/src/main/java/restx/validation/ValidatedFor.java new file mode 100644 index 000000000..d38952583 --- /dev/null +++ b/restx-core/src/main/java/restx/validation/ValidatedFor.java @@ -0,0 +1,13 @@ +package restx.validation; + +import java.lang.annotation.*; + +/** + * @author fcamblor + */ +@Target(ElementType.PARAMETER) +@Retention(RetentionPolicy.RUNTIME) +@Documented +public @interface ValidatedFor { + Class[] value(); +} diff --git a/restx-core/src/main/java/restx/validation/Validations.java b/restx-core/src/main/java/restx/validation/Validations.java index 65f4f74ab..bef2dcb4f 100644 --- a/restx-core/src/main/java/restx/validation/Validations.java +++ b/restx-core/src/main/java/restx/validation/Validations.java @@ -1,9 +1,11 @@ package restx.validation; import com.google.common.base.Joiner; +import com.google.common.base.Optional; import javax.validation.ConstraintViolation; import javax.validation.Validator; +import javax.validation.groups.Default; import java.util.Set; /** @@ -12,11 +14,27 @@ * Time: 9:57 PM */ public class Validations { + + /** + * @deprecated Kept for backward compat. Use checkValid(Optional<Validator>, T, Class...) instead + */ + @Deprecated public static T checkValid(Validator validator, T o) { - Set> violations = validator.validate(o); - if (!violations.isEmpty()) { - throw new IllegalArgumentException(Joiner.on(", ").join(violations)); + return checkValid(Optional.of(validator), o); + } + + public static T checkValid(Optional validator, T o, Class... groups) { + if(validator.isPresent()) { + if(groups == null || groups.length==0) { + groups = new Class[]{ Default.class }; + } + + Set> violations = validator.get().validate(o, groups); + if (!violations.isEmpty()) { + throw new IllegalArgumentException(Joiner.on(", ").join(violations)); + } } + return o; } } diff --git a/restx-core/src/main/java/restx/validation/ValidatorFactory.java b/restx-core/src/main/java/restx/validation/ValidatorFactory.java deleted file mode 100644 index 1ff510ff8..000000000 --- a/restx-core/src/main/java/restx/validation/ValidatorFactory.java +++ /dev/null @@ -1,25 +0,0 @@ -package restx.validation; - -import org.hibernate.validator.HibernateValidator; -import restx.factory.*; - -import javax.inject.Named; -import javax.validation.Validation; -import javax.validation.Validator; - -/** - * User: xavierhanin - * Date: 2/3/13 - * Time: 9:48 PM - */ -@Module -public class ValidatorFactory { - public static final String VALIDATOR_NAME = "validator"; - public static final Name VALIDATOR = Name.of(Validator.class, VALIDATOR_NAME); - - @Provides @Named(VALIDATOR_NAME) - public Validator validator() { - return Validation.byProvider(HibernateValidator.class).configure() - .ignoreXmlConfiguration().buildValidatorFactory().getValidator(); - } -} diff --git a/restx-core/src/main/java/restx/validation/stereotypes/FormValidations.java b/restx-core/src/main/java/restx/validation/stereotypes/FormValidations.java new file mode 100644 index 000000000..4aaec3864 --- /dev/null +++ b/restx-core/src/main/java/restx/validation/stereotypes/FormValidations.java @@ -0,0 +1,14 @@ +package restx.validation.stereotypes; + +import javax.validation.groups.Default; + +/** + * @author fcamblor + */ +public interface FormValidations { + public static final String DefaultFQN = "javax.validation.groups.Default"; + public static final String CreateFQN = "restx.validation.stereotypes.FormValidations.Create"; + public static interface Create extends Default{} + public static final String UpdateFQN = "restx.validation.stereotypes.FormValidations.Update"; + public static interface Update extends Default{} +} diff --git a/restx-samplest/pom.xml b/restx-samplest/pom.xml index 09c60036b..42c570397 100644 --- a/restx-samplest/pom.xml +++ b/restx-samplest/pom.xml @@ -30,6 +30,11 @@ restx-core ${restx.version} + + io.restx + restx-validation + ${restx.version} + io.restx restx-core-annotation-processor @@ -123,6 +128,20 @@ -restx-target-dir ${project.basedir}/target/classes + diff --git a/restx-samplest/src/main/java/samplest/validation/POJO.java b/restx-samplest/src/main/java/samplest/validation/POJO.java new file mode 100644 index 000000000..f9b567670 --- /dev/null +++ b/restx-samplest/src/main/java/samplest/validation/POJO.java @@ -0,0 +1,52 @@ +package samplest.validation; + +import org.hibernate.validator.constraints.Email; +import restx.validation.stereotypes.FormValidations; + +import javax.validation.Valid; +import javax.validation.constraints.NotNull; +import javax.validation.constraints.Size; + +public class POJO { + @NotNull(groups={FormValidations.Update.class}) + Long id; + @NotNull + @Size(min=10, groups={ValidationResource.MyCustomValidationGroup.class}) + String name; + @Valid + SubPOJO subPOJO; + @Email + String email; + + public Long getId() { + return id; + } + + public void setId(Long id) { + this.id = id; + } + + public String getEmail() { + return email; + } + + public void setEmail(String email) { + this.email = email; + } + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + public SubPOJO getSubPOJO() { + return subPOJO; + } + + public void setSubPOJO(SubPOJO subPOJO) { + this.subPOJO = subPOJO; + } +} diff --git a/restx-samplest/src/main/java/samplest/validation/SubPOJO.java b/restx-samplest/src/main/java/samplest/validation/SubPOJO.java new file mode 100644 index 000000000..dd72ac8fa --- /dev/null +++ b/restx-samplest/src/main/java/samplest/validation/SubPOJO.java @@ -0,0 +1,16 @@ +package samplest.validation; + +import javax.validation.constraints.Size; + +public class SubPOJO { + @Size(min=10) + String label; + + public String getLabel() { + return label; + } + + public void setLabel(String label) { + this.label = label; + } +} diff --git a/restx-samplest/src/main/java/samplest/validation/ValidationResource.java b/restx-samplest/src/main/java/samplest/validation/ValidationResource.java new file mode 100644 index 000000000..c702f2695 --- /dev/null +++ b/restx-samplest/src/main/java/samplest/validation/ValidationResource.java @@ -0,0 +1,41 @@ +package samplest.validation; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import restx.annotations.POST; +import restx.annotations.PUT; +import restx.annotations.Param; +import restx.annotations.RestxResource; +import restx.factory.Component; +import restx.security.PermitAll; +import restx.validation.ValidatedFor; +import restx.validation.stereotypes.FormValidations; + +/** + * @author fcamblor + */ +@RestxResource @Component +public class ValidationResource { + + private static final Logger LOG = LoggerFactory.getLogger(ValidationResource.class); + + public static interface MyCustomValidationGroup{} + + @PermitAll + @POST("/valid/pojos") + public void createPOJOWithoutAnnotation(POJO myPojo) { + LOG.info("Pojo {} {} created !", myPojo.getName(), myPojo.getSubPOJO().getLabel()); + } + + @PermitAll + @POST("/valid/pojos2") + public void createPOJOWithAnnotation(@ValidatedFor(FormValidations.Create.class) POJO myPojo) { + LOG.info("Pojo {} {} created !", myPojo.getName(), myPojo.getSubPOJO().getLabel()); + } + + @PermitAll + @PUT("/valid/pojos/{id}") + public void createPOJOWithoutAnnotation(Long id, @ValidatedFor({MyCustomValidationGroup.class, FormValidations.Update.class}) POJO myPojo) { + LOG.info("Pojo {} {} updated !", myPojo.getName(), myPojo.getSubPOJO().getLabel()); + } +} diff --git a/restx-samplest/src/main/resources/specs/core/Hello_msg_20140427_170121.spec.yaml b/restx-samplest/src/main/resources/specs/core/Hello_msg_20140427_170121.spec.yaml new file mode 100644 index 000000000..595683e91 --- /dev/null +++ b/restx-samplest/src/main/resources/specs/core/Hello_msg_20140427_170121.spec.yaml @@ -0,0 +1,11 @@ +title: Hello msg 20140427 170121 +given: + - time: 2014-04-27T17:01:21.795+02:00 +wts: + - when: | + GET core/hellomsg?who=xavier + Cookie: RestxSession={"_expires":"2014-05-27T17:01:21.795+02:00","principal":"admin","sessionKey":"81b92e9b-49eb-4c54-9c78-79a4a79feae5"}; RestxSessionSignature=g3KnRfPE2SAaoXbR3Iq7XHv5L3M= + then: | + { + "msg" : "hello xavier" + } diff --git a/restx-samplest/src/main/resources/specs/validation/createPOJO_ko.spec.yaml b/restx-samplest/src/main/resources/specs/validation/createPOJO_ko.spec.yaml new file mode 100644 index 000000000..13fa51d4b --- /dev/null +++ b/restx-samplest/src/main/resources/specs/validation/createPOJO_ko.spec.yaml @@ -0,0 +1,34 @@ +title: Create Validation POJO - KO +given: + - time: 2014-12-24T17:01:21.795+02:00 +wts: + - when: | + POST valid/pojos + {"email": "toto@acme.com", "subPOJO": { "label": "a very long label" }} + then: | + 400 + - when: | + POST valid/pojos + {"name": "blah", "email": "toto", "subPOJO": { "label": "a very long label" }} + then: | + 400 + - when: | + POST valid/pojos + {"name": "blah", "email": "toto@acme.com", "subPOJO": { "label": "a label" }} + then: | + 400 + - when: | + POST valid/pojos2 + {"email": "toto@acme.com", "subPOJO": { "label": "a very long label" }} + then: | + 400 + - when: | + POST valid/pojos2 + {"name": "blah", "email": "toto", "subPOJO": { "label": "a very long label" }} + then: | + 400 + - when: | + POST valid/pojos2 + {"name": "blah", "email": "toto@acme.com", "subPOJO": { "label": "a label" }} + then: | + 400 diff --git a/restx-samplest/src/main/resources/specs/validation/createPOJO_ok.spec.yaml b/restx-samplest/src/main/resources/specs/validation/createPOJO_ok.spec.yaml new file mode 100644 index 000000000..82ecd04f9 --- /dev/null +++ b/restx-samplest/src/main/resources/specs/validation/createPOJO_ok.spec.yaml @@ -0,0 +1,14 @@ +title: Create Validation POJO - OK +given: + - time: 2014-12-24T17:01:21.795+02:00 +wts: + - when: | + POST valid/pojos + {"name": "blah", "email": "toto@acme.com", "subPOJO": { "label": "a very long label" }} + then: | + 204 + - when: | + POST valid/pojos2 + {"name": "blah", "email": "toto@acme.com", "subPOJO": { "label": "a very long label" }} + then: | + 204 diff --git a/restx-samplest/src/main/resources/specs/validation/updatePOJO_ko.spec.yaml b/restx-samplest/src/main/resources/specs/validation/updatePOJO_ko.spec.yaml new file mode 100644 index 000000000..8cde5c8e4 --- /dev/null +++ b/restx-samplest/src/main/resources/specs/validation/updatePOJO_ko.spec.yaml @@ -0,0 +1,24 @@ +title: Update Validation POJO - KO +given: + - time: 2014-12-24T17:01:21.795+02:00 +wts: + - when: | + PUT valid/pojos/123 + {"name": "a very long name", "email": "toto@acme.com", "subPOJO": { "label": "a very long label" }} + then: | + 400 + - when: | + PUT valid/pojos/123 + {"id": 123, "name": "a name", "email": "toto@acme.com", "subPOJO": { "label": "a very long label" }} + then: | + 400 + - when: | + PUT valid/pojos/123 + {"id": 123, "name": "a very long name", "email": "toto", "subPOJO": { "label": "a very long label" }} + then: | + 400 + - when: | + PUT valid/pojos/123 + {"id": 123, "name": "a very long name", "email": "toto@acme.com", "subPOJO": { "label": "a label" }} + then: | + 400 diff --git a/restx-samplest/src/main/resources/specs/validation/updatePOJO_ok.spec.yaml b/restx-samplest/src/main/resources/specs/validation/updatePOJO_ok.spec.yaml new file mode 100644 index 000000000..286f73326 --- /dev/null +++ b/restx-samplest/src/main/resources/specs/validation/updatePOJO_ok.spec.yaml @@ -0,0 +1,9 @@ +title: Create Validation POJO - OK +given: + - time: 2014-12-24T17:01:21.795+02:00 +wts: + - when: | + PUT valid/pojos/123 + {"id": 123, "name": "a very long name", "email": "toto@acme.com", "subPOJO": { "label": "a very long label" }} + then: | + 204 diff --git a/restx-samplest/src/test/java/samplest/validation/ValidationResourceTest.java b/restx-samplest/src/test/java/samplest/validation/ValidationResourceTest.java new file mode 100644 index 000000000..e1d6d7c6e --- /dev/null +++ b/restx-samplest/src/test/java/samplest/validation/ValidationResourceTest.java @@ -0,0 +1,13 @@ +package samplest.validation; + +import org.junit.runner.RunWith; +import restx.tests.FindSpecsIn; +import restx.tests.RestxSpecTestsRunner; + +/** + * @author fcamblor + */ +@RunWith(RestxSpecTestsRunner.class) +@FindSpecsIn("specs/validation") +public class ValidationResourceTest { +} diff --git a/restx-validation/md.restx.json b/restx-validation/md.restx.json new file mode 100644 index 000000000..1489f5671 --- /dev/null +++ b/restx-validation/md.restx.json @@ -0,0 +1,19 @@ +{ + "parent": "io.restx:restx-parent:${restx.version}", + "module": "io.restx:restx-validation:${restx.version}", + + "properties": { + "@files": ["../restx.build.properties.json"] + }, + + "dependencies": { + "compile": [ + "io.restx:restx-factory:${restx.version}", + "org.hibernate:hibernate-validator:${hibernate-validator.version}", + "javax.el:el-api:${el.api.version}" + ], + "runtime": [ + "org.glassfish.web:el-impl:${el.api.version}" + ] + } +} diff --git a/restx-validation/module.ivy b/restx-validation/module.ivy new file mode 100644 index 000000000..d04220028 --- /dev/null +++ b/restx-validation/module.ivy @@ -0,0 +1,22 @@ + + + + + + + + + + + + + + + + + + + diff --git a/restx-validation/pom.xml b/restx-validation/pom.xml new file mode 100644 index 000000000..fba93c314 --- /dev/null +++ b/restx-validation/pom.xml @@ -0,0 +1,55 @@ + + + + io.restx + restx-parent + 0.34-SNAPSHOT + + 4.0.0 + + io.restx + restx-validation + 0.34-SNAPSHOT + jar + restx-validation + + + 0.34-SNAPSHOT + 1.7 + 1.7 + 5.0.1.Final + 2.2 + + + + + io.restx + restx-factory + ${restx.version} + + + org.hibernate + hibernate-validator + ${hibernate-validator.version} + + compile + + + javax.el + el-api + ${el.api.version} + + + org.glassfish.web + el-impl + ${el.api.version} + runtime + + + + \ No newline at end of file diff --git a/restx-validation/src/main/java/restx/validation/ValidatorFactory.java b/restx-validation/src/main/java/restx/validation/ValidatorFactory.java new file mode 100644 index 000000000..b8cd83b0a --- /dev/null +++ b/restx-validation/src/main/java/restx/validation/ValidatorFactory.java @@ -0,0 +1,38 @@ +package restx.validation; + +import org.hibernate.validator.HibernateValidator; +import org.hibernate.validator.HibernateValidatorConfiguration; +import restx.factory.Module; +import restx.factory.Name; +import restx.factory.Provides; + +import javax.inject.Named; +import javax.validation.Validation; +import javax.validation.Validator; + +/** + * User: xavierhanin + * Date: 2/3/13 + * Time: 9:48 PM + */ +@Module +public class ValidatorFactory { + public static final String VALIDATOR_NAME = "hibernate.validator"; + public static final String IGNORE_XML_CONFIGURATION_NAME = "hibernate.validator.ignore.xml.configuration"; + public static final Name VALIDATOR = Name.of(Validator.class, VALIDATOR_NAME); + + @Provides @Named(VALIDATOR_NAME) + public Validator validator(@Named(IGNORE_XML_CONFIGURATION_NAME) Boolean ignoreXmlConfiguration) { + HibernateValidatorConfiguration config = Validation.byProvider(HibernateValidator.class).configure(); + if(ignoreXmlConfiguration) { + config.ignoreXmlConfiguration(); + } + return config.buildValidatorFactory().getValidator(); + } + + // Perf improvement to greatly fasten startup time + @Provides @Named(IGNORE_XML_CONFIGURATION_NAME) + public Boolean ignoreXmlConfigurationFlag(){ + return Boolean.TRUE; + } +} diff --git a/restx.build.properties.json b/restx.build.properties.json index 375fc7662..ceb755e65 100644 --- a/restx.build.properties.json +++ b/restx.build.properties.json @@ -16,6 +16,7 @@ "snakeyaml.version": "1.13", "hibernate-validator.version": "5.0.1.Final", + "el.api.version": "2.2", "reflections.version": "0.9.9-RC1", "janino.version": "2.6.1",