From 5b13307e3936cf5779f1c420fb36d1dc0b6d6906 Mon Sep 17 00:00:00 2001 From: Maciej Walkowiak Date: Mon, 23 Apr 2012 18:09:18 +0200 Subject: [PATCH] DATAMONGO-36 - Added support for JSR-303 validation Added event listener that uses a java.validation.Validator to trigger validation on an entity before persisting it. This validation is enabled by default if the javx.validation API is present on the classpath. Added namespace attribute 'disable-validation' to allow disabling that auto enabling behavior. --- spring-data-mongodb/pom.xml | 16 + .../data/mongodb/config/BeanNames.java | 1 + .../config/MappingMongoConverterParser.java | 60 ++- .../event/ValidatingMongoEventListener.java | 68 +++ .../main/resources/META-INF/spring.schemas | 3 +- .../data/mongodb/config/spring-mongo-1.1.xsd | 479 ++++++++++++++++++ ...gMongoConverterParserIntegrationTests.java | 4 +- ...erterParserValidationIntegrationTests.java | 68 +++ .../data/mongodb/core/mapping/event/User.java | 48 ++ .../ValidatingMongoEventListenerTest.java | 61 +++ .../resources/namespace/converter-default.xml | 10 + .../converter-validation-disabled.xml | 10 + .../converter-validation-enabled.xml | 10 + ...lidatingMongoEventListenerTest-context.xml | 19 + spring-data-mongodb/template.mf | 1 + 15 files changed, 851 insertions(+), 7 deletions(-) create mode 100644 spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/mapping/event/ValidatingMongoEventListener.java create mode 100644 spring-data-mongodb/src/main/resources/org/springframework/data/mongodb/config/spring-mongo-1.1.xsd create mode 100644 spring-data-mongodb/src/test/java/org/springframework/data/mongodb/config/MappingMongoConverterParserValidationIntegrationTests.java create mode 100644 spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/mapping/event/User.java create mode 100644 spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/mapping/event/ValidatingMongoEventListenerTest.java create mode 100644 spring-data-mongodb/src/test/resources/namespace/converter-default.xml create mode 100644 spring-data-mongodb/src/test/resources/namespace/converter-validation-disabled.xml create mode 100644 spring-data-mongodb/src/test/resources/namespace/converter-validation-enabled.xml create mode 100644 spring-data-mongodb/src/test/resources/org/springframework/data/mongodb/core/mapping/event/ValidatingMongoEventListenerTest-context.xml diff --git a/spring-data-mongodb/pom.xml b/spring-data-mongodb/pom.xml index ad546153e..48342b594 100644 --- a/spring-data-mongodb/pom.xml +++ b/spring-data-mongodb/pom.xml @@ -15,6 +15,7 @@ 2.7.1 2.3.2 1.0 + 1.0.0.GA 1.1.3 @@ -130,6 +131,21 @@ test + + + javax.validation + validation-api + ${validation.version} + true + + + + org.hibernate + hibernate-validator + 4.2.0.Final + test + + diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/config/BeanNames.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/config/BeanNames.java index c1d21bf09..2c4ef69d5 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/config/BeanNames.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/config/BeanNames.java @@ -25,4 +25,5 @@ public abstract class BeanNames { static final String INDEX_HELPER = "indexCreationHelper"; static final String MONGO = "mongo"; static final String DB_FACTORY = "mongoDbFactory"; + static final String VALIDATING_EVENT_LISTENER = "validatingMongoEventListener"; } diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/config/MappingMongoConverterParser.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/config/MappingMongoConverterParser.java index 5e007e34c..dfb7e9791 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/config/MappingMongoConverterParser.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/config/MappingMongoConverterParser.java @@ -1,11 +1,11 @@ /* - * Copyright (c) 2011 by the original author(s). + * Copyright 2011-2012 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * - * http://www.apache.org/licenses/LICENSE-2.0 + * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, @@ -13,7 +13,6 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - package org.springframework.data.mongodb.config; import static org.springframework.data.mongodb.config.BeanNames.*; @@ -30,12 +29,14 @@ import org.springframework.beans.factory.NoSuchBeanDefinitionException; import org.springframework.beans.factory.config.BeanDefinition; import org.springframework.beans.factory.config.BeanDefinitionHolder; import org.springframework.beans.factory.config.RuntimeBeanReference; +import org.springframework.beans.factory.parsing.BeanComponentDefinition; import org.springframework.beans.factory.support.AbstractBeanDefinition; import org.springframework.beans.factory.support.BeanDefinitionBuilder; import org.springframework.beans.factory.support.BeanDefinitionRegistry; import org.springframework.beans.factory.support.GenericBeanDefinition; import org.springframework.beans.factory.support.ManagedList; import org.springframework.beans.factory.support.ManagedSet; +import org.springframework.beans.factory.support.RootBeanDefinition; import org.springframework.beans.factory.xml.AbstractBeanDefinitionParser; import org.springframework.beans.factory.xml.ParserContext; import org.springframework.context.annotation.ClassPathScanningCandidateComponentProvider; @@ -52,18 +53,25 @@ import org.springframework.data.mongodb.core.convert.MappingMongoConverter; import org.springframework.data.mongodb.core.index.MongoPersistentEntityIndexCreator; import org.springframework.data.mongodb.core.mapping.Document; import org.springframework.data.mongodb.core.mapping.MongoMappingContext; +import org.springframework.data.mongodb.core.mapping.event.ValidatingMongoEventListener; import org.springframework.util.Assert; +import org.springframework.util.ClassUtils; import org.springframework.util.StringUtils; import org.springframework.util.xml.DomUtils; import org.w3c.dom.Element; /** - * @author Jon Brisbin + * Bean definition parser for the {@code mapping-converter} element. + * + * @author Jon Brisbin * @author Oliver Gierke + * @author Maciej Walkowiak */ public class MappingMongoConverterParser extends AbstractBeanDefinitionParser { private static final String BASE_PACKAGE = "base-package"; + private static final boolean jsr303Present = ClassUtils.isPresent("javax.validation.Validator", + MappingMongoConverterParser.class.getClassLoader()); @Override protected String resolveId(Element element, AbstractBeanDefinition definition, ParserContext parserContext) @@ -107,9 +115,53 @@ public class MappingMongoConverterParser extends AbstractBeanDefinitionParser { registry.registerBeanDefinition(INDEX_HELPER, indexHelperBuilder.getBeanDefinition()); } + BeanDefinition validatingMongoEventListener = potentiallyCreateValidatingMongoEventListener(element, parserContext); + + if (validatingMongoEventListener != null) { + registry.registerBeanDefinition(VALIDATING_EVENT_LISTENER, validatingMongoEventListener); + } + return converterBuilder.getBeanDefinition(); } + private BeanDefinition potentiallyCreateValidatingMongoEventListener(Element element, ParserContext parserContext) { + + String disableValidation = element.getAttribute("disable-validation"); + boolean validationDisabled = StringUtils.hasText(disableValidation) && Boolean.valueOf(disableValidation); + + if (!validationDisabled) { + + BeanDefinitionBuilder builder = BeanDefinitionBuilder.genericBeanDefinition(); + RuntimeBeanReference validator = getValidator(builder, parserContext); + + if (validator != null) { + + builder.getRawBeanDefinition().setBeanClass(ValidatingMongoEventListener.class); + builder.addConstructorArgValue(validator); + + return builder.getBeanDefinition(); + } + } + + return null; + } + + private RuntimeBeanReference getValidator(Object source, ParserContext parserContext) { + + if (!jsr303Present) { + return null; + } + + RootBeanDefinition validatorDef = new RootBeanDefinition( + "org.springframework.validation.beanvalidation.LocalValidatorFactoryBean"); + validatorDef.setSource(source); + validatorDef.setRole(BeanDefinition.ROLE_INFRASTRUCTURE); + String validatorName = parserContext.getReaderContext().registerWithGeneratedName(validatorDef); + parserContext.registerComponent(new BeanComponentDefinition(validatorDef, validatorName)); + + return new RuntimeBeanReference(validatorName); + } + private String potentiallyCreateMappingContext(Element element, ParserContext parserContext, BeanDefinition conversionsDefinition) { diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/mapping/event/ValidatingMongoEventListener.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/mapping/event/ValidatingMongoEventListener.java new file mode 100644 index 000000000..4dd8e96dd --- /dev/null +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/mapping/event/ValidatingMongoEventListener.java @@ -0,0 +1,68 @@ +/* + * Copyright 2012 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.springframework.data.mongodb.core.mapping.event; + +import java.util.Set; + +import javax.validation.ConstraintViolationException; +import javax.validation.Validator; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.util.Assert; + +import com.mongodb.DBObject; + +/** + * javax.validation dependant entities validator. When it is registered as Spring component its automatically invoked + * before entities are saved in database. + * + * @author Maciej Walkowiak + */ +public class ValidatingMongoEventListener extends AbstractMongoEventListener { + + private static final Logger LOG = LoggerFactory.getLogger(ValidatingMongoEventListener.class); + + private final Validator validator; + + /** + * Creates a new {@link ValidatingMongoEventListener} using the given {@link Validator}. + * + * @param validator must not be {@literal null}. + */ + public ValidatingMongoEventListener(Validator validator) { + Assert.notNull(validator); + this.validator = validator; + } + + /* + * (non-Javadoc) + * @see org.springframework.data.mongodb.core.mapping.event.AbstractMongoEventListener#onBeforeSave(java.lang.Object, com.mongodb.DBObject) + */ + @Override + @SuppressWarnings({ "rawtypes", "unchecked" }) + public void onBeforeSave(Object source, DBObject dbo) { + + LOG.debug("Validating object: {}", source); + Set violations = validator.validate(source); + + if (!violations.isEmpty()) { + + LOG.info("During object: {} validation violations found: {}", source, violations); + throw new ConstraintViolationException(violations); + } + } +} diff --git a/spring-data-mongodb/src/main/resources/META-INF/spring.schemas b/spring-data-mongodb/src/main/resources/META-INF/spring.schemas index 5044417cd..c516faaa8 100644 --- a/spring-data-mongodb/src/main/resources/META-INF/spring.schemas +++ b/spring-data-mongodb/src/main/resources/META-INF/spring.schemas @@ -1,2 +1,3 @@ +http\://www.springframework.org/schema/data/mongo/spring-mongo-1.1.xsd=org/springframework/data/mongodb/config/spring-mongo-1.1.xsd http\://www.springframework.org/schema/data/mongo/spring-mongo-1.0.xsd=org/springframework/data/mongodb/config/spring-mongo-1.0.xsd -http\://www.springframework.org/schema/data/mongo/spring-mongo.xsd=org/springframework/data/mongodb/config/spring-mongo-1.0.xsd +http\://www.springframework.org/schema/data/mongo/spring-mongo.xsd=org/springframework/data/mongodb/config/spring-mongo-1.1.xsd diff --git a/spring-data-mongodb/src/main/resources/org/springframework/data/mongodb/config/spring-mongo-1.1.xsd b/spring-data-mongodb/src/main/resources/org/springframework/data/mongodb/config/spring-mongo-1.1.xsd new file mode 100644 index 000000000..feae5468b --- /dev/null +++ b/spring-data-mongodb/src/main/resources/org/springframework/data/mongodb/config/spring-mongo-1.1.xsd @@ -0,0 +1,479 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + The reference to a Mongo. Will default to 'mongo'. + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + The WriteConcern that will be the default value used when asking the MongoDbFactory for a DB object + + + + + + + + + + + + + + + + + + + + + + + The reference to a MongoTemplate. Will default to 'mongoTemplate'. + + + + + + + Enables creation of indexes for queries that get derived from the method name + and thus reference domain class properties. Defaults to false. + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + The reference to a DbFactory. + + + + + + + + + + + + The reference to a Mongo. Will default to 'mongo'. + + + + + + + The reference to a MappingContext. Will default to 'mappingContext'. + + + + + + + The reference to a MongoTemplate. Will default to 'mongoTemplate'. + + + + + + + Disables JSR-303 validation on MongoDB documents before they are saved. By default it is set to false. + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + The WriteConcern that will be the default value used when asking the MongoDbFactory for a DB object + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + A reference to a custom converter. + + + + + + + + + \ No newline at end of file diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/config/MappingMongoConverterParserIntegrationTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/config/MappingMongoConverterParserIntegrationTests.java index 533b6ce97..75242761e 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/config/MappingMongoConverterParserIntegrationTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/config/MappingMongoConverterParserIntegrationTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2011 the original author or authors. + * Copyright 2011-2012 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -37,7 +37,7 @@ import org.springframework.stereotype.Component; import com.mongodb.DBObject; /** - * Integration tests for {@link MongoParser}. + * Integration tests for {@link MappingMongoConverterParser}. * * @author Oliver Gierke */ diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/config/MappingMongoConverterParserValidationIntegrationTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/config/MappingMongoConverterParserValidationIntegrationTests.java new file mode 100644 index 000000000..762c8a8bd --- /dev/null +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/config/MappingMongoConverterParserValidationIntegrationTests.java @@ -0,0 +1,68 @@ +/* + * Copyright 2012 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.springframework.data.mongodb.config; + +import static org.hamcrest.Matchers.*; +import static org.junit.Assert.*; + +import org.junit.Before; +import org.junit.Test; +import org.springframework.beans.factory.NoSuchBeanDefinitionException; +import org.springframework.beans.factory.support.BeanDefinitionReader; +import org.springframework.beans.factory.support.DefaultListableBeanFactory; +import org.springframework.beans.factory.xml.XmlBeanDefinitionReader; +import org.springframework.core.io.ClassPathResource; + +/** + * Integration test for creation of instance of + * {@link org.springframework.data.mongodb.core.mapping.event.ValidatingMongoEventListener} by defining + * {@code } in context XML. + * + * @see DATAMONGO-36 + * @author Maciej Walkowiak + */ +public class MappingMongoConverterParserValidationIntegrationTests { + + DefaultListableBeanFactory factory; + BeanDefinitionReader reader; + + @Before + public void setUp() { + factory = new DefaultListableBeanFactory(); + reader = new XmlBeanDefinitionReader(factory); + } + + @Test + public void validatingEventListenerCreatedWithDefaultConfig() { + + reader.loadBeanDefinitions(new ClassPathResource("namespace/converter-default.xml")); + assertThat(factory.getBean(BeanNames.VALIDATING_EVENT_LISTENER), is(not(nullValue()))); + } + + @Test + public void validatingEventListenerCreatedWhenValidationEnabled() { + + reader.loadBeanDefinitions(new ClassPathResource("namespace/converter-validation-enabled.xml")); + assertThat(factory.getBean(BeanNames.VALIDATING_EVENT_LISTENER), is(not(nullValue()))); + } + + @Test(expected = NoSuchBeanDefinitionException.class) + public void validatingEventListenersIsNotCreatedWhenDisabled() { + + reader.loadBeanDefinitions(new ClassPathResource("namespace/converter-validation-disabled.xml")); + factory.getBean(BeanNames.VALIDATING_EVENT_LISTENER); + } +} diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/mapping/event/User.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/mapping/event/User.java new file mode 100644 index 000000000..c638aeadc --- /dev/null +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/mapping/event/User.java @@ -0,0 +1,48 @@ +/* + * Copyright 2012 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.springframework.data.mongodb.core.mapping.event; + +import javax.validation.constraints.Min; +import javax.validation.constraints.Size; + +/** + * Class used to test JSR-303 validation + * {@link org.springframework.data.mongodb.core.mapping.event.ValidatingMongoEventListener} + * + * @see DATAMONGO-36 + * @author Maciej Walkowiak + */ +public class User { + + @Size(min = 10) + private String name; + + @Min(18) + private Integer age; + + public User(String name, Integer age) { + this.name = name; + this.age = age; + } + + public String getName() { + return name; + } + + public Integer getAge() { + return age; + } +} diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/mapping/event/ValidatingMongoEventListenerTest.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/mapping/event/ValidatingMongoEventListenerTest.java new file mode 100644 index 000000000..fff4fdf5c --- /dev/null +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/mapping/event/ValidatingMongoEventListenerTest.java @@ -0,0 +1,61 @@ +/* + * Copyright 2012 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.springframework.data.mongodb.core.mapping.event; + +import static org.hamcrest.core.IsEqual.*; +import static org.junit.Assert.*; + +import javax.validation.ConstraintViolationException; + +import org.junit.Test; +import org.junit.runner.RunWith; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.data.mongodb.core.MongoTemplate; +import org.springframework.test.context.ContextConfiguration; +import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; + +/** + * Integration test for {@link ValidatingMongoEventListener}. + * + * @see DATAMONGO-36 + * @author Maciej Walkowiak + * @author Oliver Gierke + */ +@RunWith(SpringJUnit4ClassRunner.class) +@ContextConfiguration +public class ValidatingMongoEventListenerTest { + + @Autowired + MongoTemplate mongoTemplate; + + @Test + public void shouldThrowConstraintViolationException() { + + User user = new User("john", 17); + + try { + mongoTemplate.save(user); + fail(); + } catch (ConstraintViolationException e) { + assertThat(e.getConstraintViolations().size(), equalTo(2)); + } + } + + @Test + public void shouldNotThrowAnyExceptions() { + mongoTemplate.save(new User("john smith", 18)); + } +} diff --git a/spring-data-mongodb/src/test/resources/namespace/converter-default.xml b/spring-data-mongodb/src/test/resources/namespace/converter-default.xml new file mode 100644 index 000000000..6692e304d --- /dev/null +++ b/spring-data-mongodb/src/test/resources/namespace/converter-default.xml @@ -0,0 +1,10 @@ + + + + + + diff --git a/spring-data-mongodb/src/test/resources/namespace/converter-validation-disabled.xml b/spring-data-mongodb/src/test/resources/namespace/converter-validation-disabled.xml new file mode 100644 index 000000000..345e7d12b --- /dev/null +++ b/spring-data-mongodb/src/test/resources/namespace/converter-validation-disabled.xml @@ -0,0 +1,10 @@ + + + + + + diff --git a/spring-data-mongodb/src/test/resources/namespace/converter-validation-enabled.xml b/spring-data-mongodb/src/test/resources/namespace/converter-validation-enabled.xml new file mode 100644 index 000000000..2b7e4519a --- /dev/null +++ b/spring-data-mongodb/src/test/resources/namespace/converter-validation-enabled.xml @@ -0,0 +1,10 @@ + + + + + + diff --git a/spring-data-mongodb/src/test/resources/org/springframework/data/mongodb/core/mapping/event/ValidatingMongoEventListenerTest-context.xml b/spring-data-mongodb/src/test/resources/org/springframework/data/mongodb/core/mapping/event/ValidatingMongoEventListenerTest-context.xml new file mode 100644 index 000000000..2e03229b7 --- /dev/null +++ b/spring-data-mongodb/src/test/resources/org/springframework/data/mongodb/core/mapping/event/ValidatingMongoEventListenerTest-context.xml @@ -0,0 +1,19 @@ + + + + + + + + + + + + + diff --git a/spring-data-mongodb/template.mf b/spring-data-mongodb/template.mf index ae1431b31..cb0df0d8b 100644 --- a/spring-data-mongodb/template.mf +++ b/spring-data-mongodb/template.mf @@ -12,6 +12,7 @@ Import-Template: javax.annotation.processing.*;version="0", javax.enterprise.*;version="${cdi.version:[=.=.=,+1.0.0)}";resolution:=optional, javax.tools.*;version="0", + javax.validation.*;version="${validation.version:[=.=.=.=,+1.0.0)}";resolution:=optional, org.aopalliance.*;version="[1.0.0, 2.0.0)";resolution:=optional, org.apache.commons.collections15.*;version="[4.0.0,5.0.0)";resolution:=optional, org.bson.*;version="0",