Author: rmannibucau Date: Mon Oct 6 07:24:30 2014 New Revision: 1629580 URL: http://svn.apache.org/r1629580 Log: TOMEE-1381 passing good ValidatorFactory property to JPA
Added: tomee/tomee/trunk/container/openejb-core/src/main/java/org/apache/openejb/assembler/classic/ComparableValidationConfig.java Modified: tomee/tomee/trunk/container/openejb-core/src/main/java/org/apache/openejb/assembler/classic/Assembler.java tomee/tomee/trunk/container/openejb-core/src/main/java/org/apache/openejb/assembler/classic/EntityManagerFactoryCallable.java tomee/tomee/trunk/container/openejb-core/src/main/java/org/apache/openejb/assembler/classic/PersistenceBuilder.java tomee/tomee/trunk/container/openejb-core/src/main/java/org/apache/openejb/assembler/classic/ValidatorFactoryWrapper.java tomee/tomee/trunk/container/openejb-core/src/main/java/org/apache/openejb/bval/ValidatorUtil.java Modified: tomee/tomee/trunk/container/openejb-core/src/main/java/org/apache/openejb/assembler/classic/Assembler.java URL: http://svn.apache.org/viewvc/tomee/tomee/trunk/container/openejb-core/src/main/java/org/apache/openejb/assembler/classic/Assembler.java?rev=1629580&r1=1629579&r2=1629580&view=diff ============================================================================== --- tomee/tomee/trunk/container/openejb-core/src/main/java/org/apache/openejb/assembler/classic/Assembler.java (original) +++ tomee/tomee/trunk/container/openejb-core/src/main/java/org/apache/openejb/assembler/classic/Assembler.java Mon Oct 6 07:24:30 2014 @@ -711,6 +711,9 @@ public class Assembler extends Assembler final Map<String, LazyValidatorFactory> lazyValidatorFactories = new HashMap<String, LazyValidatorFactory>(); final Map<String, LazyValidator> lazyValidators = new HashMap<String, LazyValidator>(); final boolean isGeronimo = SystemInstance.get().hasProperty("openejb.geronimo"); + + // try to not create N times the same validator for a single app + final Map<ComparableValidationConfig, ValidatorFactory> validatorFactoriesByConfig = new HashMap<ComparableValidationConfig, ValidatorFactory>(); if (!isGeronimo) { // Bean Validation // ValidatorFactory needs to be put in the map sent to the entity manager factory @@ -719,15 +722,27 @@ public class Assembler extends Assembler final Map<String, ValidatorFactory> validatorFactories = new HashMap<String, ValidatorFactory>(); for (final CommonInfoObject info : vfs) { - ValidatorFactory factory = null; - try { // lazy cause of CDI :( - final LazyValidatorFactory handler = new LazyValidatorFactory(classLoader, info.validationInfo); - factory = (ValidatorFactory) Proxy.newProxyInstance( - appContext.getClassLoader(), VALIDATOR_FACTORY_INTERFACES, handler); - lazyValidatorFactories.put(info.uniqueId, handler); - } catch (final ValidationException ve) { - logger.warning("can't build the validation factory for module " + info.uniqueId, ve); - continue; + final ComparableValidationConfig conf = new ComparableValidationConfig( + info.validationInfo.providerClassName, info.validationInfo.messageInterpolatorClass, + info.validationInfo.traversableResolverClass, info.validationInfo.constraintFactoryClass, + info.validationInfo.parameterNameProviderClass, info.validationInfo.version, + info.validationInfo.propertyTypes, info.validationInfo.constraintMappings, + info.validationInfo.executableValidationEnabled, info.validationInfo.validatedTypes + ); + ValidatorFactory factory = validatorFactoriesByConfig.get(conf); + if (factory == null) { + try { // lazy cause of CDI :( + final LazyValidatorFactory handler = new LazyValidatorFactory(classLoader, info.validationInfo); + factory = (ValidatorFactory) Proxy.newProxyInstance( + appContext.getClassLoader(), VALIDATOR_FACTORY_INTERFACES, handler); + lazyValidatorFactories.put(info.uniqueId, handler); + } catch (final ValidationException ve) { + logger.warning("can't build the validation factory for module " + info.uniqueId, ve); + continue; + } + validatorFactoriesByConfig.put(conf, factory); + } else { + lazyValidatorFactories.put(info.uniqueId, LazyValidatorFactory.class.cast(Proxy.getInvocationHandler(factory))); } validatorFactories.put(info.uniqueId, factory); } @@ -767,7 +782,7 @@ public class Assembler extends Assembler for (final PersistenceUnitInfo info : appInfo.persistenceUnits) { final ReloadableEntityManagerFactory factory; try { - factory = persistenceBuilder.createEntityManagerFactory(info, classLoader); + factory = persistenceBuilder.createEntityManagerFactory(info, classLoader, validatorFactoriesByConfig); containerSystem.getJNDIContext().bind(PERSISTENCE_UNIT_NAMING_CONTEXT + info.id, factory); units.put(info.name, PERSISTENCE_UNIT_NAMING_CONTEXT + info.id); } catch (final NameAlreadyBoundException e) { Added: tomee/tomee/trunk/container/openejb-core/src/main/java/org/apache/openejb/assembler/classic/ComparableValidationConfig.java URL: http://svn.apache.org/viewvc/tomee/tomee/trunk/container/openejb-core/src/main/java/org/apache/openejb/assembler/classic/ComparableValidationConfig.java?rev=1629580&view=auto ============================================================================== --- tomee/tomee/trunk/container/openejb-core/src/main/java/org/apache/openejb/assembler/classic/ComparableValidationConfig.java (added) +++ tomee/tomee/trunk/container/openejb-core/src/main/java/org/apache/openejb/assembler/classic/ComparableValidationConfig.java Mon Oct 6 07:24:30 2014 @@ -0,0 +1,101 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You 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.apache.openejb.assembler.classic; + +import java.util.List; +import java.util.Properties; + +public class ComparableValidationConfig { + private final String providerClassName; + private final String messageInterpolatorClass; + private final String traversableResolverClass; + private final String constraintFactoryClass; + private final String parameterNameProviderClass; + private final String version; + private final Properties propertyTypes; + private final List<String> constraintMappings; + private final boolean executableValidationEnabled; + private final List<String> validatedTypes; + + private final int hash; + + public ComparableValidationConfig(final String providerClassName, final String messageInterpolatorClass, + final String traversableResolverClass, final String constraintFactoryClass, + final String parameterNameProviderClass, final String version, + final Properties propertyTypes, final List<String> constraintMappings, + final boolean executableValidationEnabled, final List<String> validatedTypes) { + this.providerClassName = providerClassName; + this.messageInterpolatorClass = messageInterpolatorClass; + this.traversableResolverClass = traversableResolverClass; + this.constraintFactoryClass = constraintFactoryClass; + this.parameterNameProviderClass = parameterNameProviderClass; + this.version = version; + this.propertyTypes = propertyTypes; + this.constraintMappings = constraintMappings; + this.executableValidationEnabled = executableValidationEnabled; + this.validatedTypes = validatedTypes; + + int result = providerClassName != null ? providerClassName.hashCode() : 0; + result = 31 * result + (messageInterpolatorClass != null ? messageInterpolatorClass.hashCode() : 0); + result = 31 * result + (traversableResolverClass != null ? traversableResolverClass.hashCode() : 0); + result = 31 * result + (constraintFactoryClass != null ? constraintFactoryClass.hashCode() : 0); + result = 31 * result + (parameterNameProviderClass != null ? parameterNameProviderClass.hashCode() : 0); + result = 31 * result + (version != null ? version.hashCode() : 0); + result = 31 * result + (propertyTypes != null ? propertyTypes.hashCode() : 0); + result = 31 * result + (constraintMappings != null ? constraintMappings.hashCode() : 0); + result = 31 * result + (executableValidationEnabled ? 1 : 0); + result = 31 * result + (validatedTypes != null ? validatedTypes.hashCode() : 0); + hash = result; + } + + @Override + public boolean equals(final Object o) { + if (this == o) { + return true; + } + if (o == null || getClass() != o.getClass()) { + return false; + } + + final ComparableValidationConfig that = (ComparableValidationConfig) o; + + if (executableValidationEnabled != that.executableValidationEnabled) return false; + if (constraintFactoryClass != null ? !constraintFactoryClass.equals(that.constraintFactoryClass) : that.constraintFactoryClass != null) + return false; + if (constraintMappings != null ? !constraintMappings.equals(that.constraintMappings) : that.constraintMappings != null) + return false; + if (messageInterpolatorClass != null ? !messageInterpolatorClass.equals(that.messageInterpolatorClass) : that.messageInterpolatorClass != null) + return false; + if (parameterNameProviderClass != null ? !parameterNameProviderClass.equals(that.parameterNameProviderClass) : that.parameterNameProviderClass != null) + return false; + if (propertyTypes != null ? !propertyTypes.equals(that.propertyTypes) : that.propertyTypes != null) + return false; + if (providerClassName != null ? !providerClassName.equals(that.providerClassName) : that.providerClassName != null) + return false; + if (traversableResolverClass != null ? !traversableResolverClass.equals(that.traversableResolverClass) : that.traversableResolverClass != null) + return false; + if (validatedTypes != null ? !validatedTypes.equals(that.validatedTypes) : that.validatedTypes != null) + return false; + if (version != null ? !version.equals(that.version) : that.version != null) return false; + return true; + } + + @Override + public int hashCode() { + return hash; + } +} Modified: tomee/tomee/trunk/container/openejb-core/src/main/java/org/apache/openejb/assembler/classic/EntityManagerFactoryCallable.java URL: http://svn.apache.org/viewvc/tomee/tomee/trunk/container/openejb-core/src/main/java/org/apache/openejb/assembler/classic/EntityManagerFactoryCallable.java?rev=1629580&r1=1629579&r2=1629580&view=diff ============================================================================== --- tomee/tomee/trunk/container/openejb-core/src/main/java/org/apache/openejb/assembler/classic/EntityManagerFactoryCallable.java (original) +++ tomee/tomee/trunk/container/openejb-core/src/main/java/org/apache/openejb/assembler/classic/EntityManagerFactoryCallable.java Mon Oct 6 07:24:30 2014 @@ -23,6 +23,7 @@ import org.apache.openejb.persistence.Pe import javax.persistence.EntityManagerFactory; import javax.persistence.ValidationMode; import javax.persistence.spi.PersistenceProvider; +import javax.validation.ValidatorFactory; import java.util.HashMap; import java.util.Map; import java.util.concurrent.Callable; @@ -33,12 +34,15 @@ public class EntityManagerFactoryCallabl private final String persistenceProviderClassName; private final PersistenceUnitInfoImpl unitInfo; + private final Map<ComparableValidationConfig, ValidatorFactory> potentialValidators; private ClassLoader appClassLoader; - public EntityManagerFactoryCallable(final String persistenceProviderClassName, final PersistenceUnitInfoImpl unitInfo, final ClassLoader cl) { + public EntityManagerFactoryCallable(final String persistenceProviderClassName, final PersistenceUnitInfoImpl unitInfo, + final ClassLoader cl, final Map<ComparableValidationConfig, ValidatorFactory> validators) { this.persistenceProviderClassName = persistenceProviderClassName; this.unitInfo = unitInfo; this.appClassLoader = cl; + this.potentialValidators = validators; } @Override @@ -52,7 +56,7 @@ public class EntityManagerFactoryCallabl // Create entity manager factories with the validator factory final Map<String, Object> properties = new HashMap<String, Object>(); if (!ValidationMode.NONE.equals(unitInfo.getValidationMode())) { - properties.put("javax.persistence.validator.ValidatorFactory", new ValidatorFactoryWrapper()); + properties.put("javax.persistence.validation.factory", new ValidatorFactoryWrapper(potentialValidators)); } customizeProperties(properties); Modified: tomee/tomee/trunk/container/openejb-core/src/main/java/org/apache/openejb/assembler/classic/PersistenceBuilder.java URL: http://svn.apache.org/viewvc/tomee/tomee/trunk/container/openejb-core/src/main/java/org/apache/openejb/assembler/classic/PersistenceBuilder.java?rev=1629580&r1=1629579&r2=1629580&view=diff ============================================================================== --- tomee/tomee/trunk/container/openejb-core/src/main/java/org/apache/openejb/assembler/classic/PersistenceBuilder.java (original) +++ tomee/tomee/trunk/container/openejb-core/src/main/java/org/apache/openejb/assembler/classic/PersistenceBuilder.java Mon Oct 6 07:24:30 2014 @@ -32,6 +32,8 @@ import javax.persistence.SharedCacheMode import javax.persistence.ValidationMode; import javax.persistence.spi.PersistenceUnitTransactionType; import javax.sql.DataSource; +import javax.validation.ValidatorFactory; +import java.util.Map; public class PersistenceBuilder { @@ -46,7 +48,8 @@ public class PersistenceBuilder { this.persistenceClassLoaderHandler = persistenceClassLoaderHandler; } - public ReloadableEntityManagerFactory createEntityManagerFactory(final PersistenceUnitInfo info, final ClassLoader classLoader) throws Exception { + public ReloadableEntityManagerFactory createEntityManagerFactory(final PersistenceUnitInfo info, final ClassLoader classLoader, + final Map<ComparableValidationConfig, ValidatorFactory> validators) throws Exception { final PersistenceUnitInfoImpl unitInfo = new PersistenceUnitInfoImpl(persistenceClassLoaderHandler); // Persistence Unit Id @@ -147,7 +150,7 @@ public class PersistenceBuilder { final String persistenceProviderClassName = unitInfo.getPersistenceProviderClassName(); unitInfo.setPersistenceProviderClassName(persistenceProviderClassName); - final EntityManagerFactoryCallable callable = new EntityManagerFactoryCallable(persistenceProviderClassName, unitInfo, classLoader); + final EntityManagerFactoryCallable callable = new EntityManagerFactoryCallable(persistenceProviderClassName, unitInfo, classLoader, validators); return new ReloadableEntityManagerFactory(classLoader, callable, unitInfo); } Modified: tomee/tomee/trunk/container/openejb-core/src/main/java/org/apache/openejb/assembler/classic/ValidatorFactoryWrapper.java URL: http://svn.apache.org/viewvc/tomee/tomee/trunk/container/openejb-core/src/main/java/org/apache/openejb/assembler/classic/ValidatorFactoryWrapper.java?rev=1629580&r1=1629579&r2=1629580&view=diff ============================================================================== --- tomee/tomee/trunk/container/openejb-core/src/main/java/org/apache/openejb/assembler/classic/ValidatorFactoryWrapper.java (original) +++ tomee/tomee/trunk/container/openejb-core/src/main/java/org/apache/openejb/assembler/classic/ValidatorFactoryWrapper.java Mon Oct 6 07:24:30 2014 @@ -21,6 +21,7 @@ import org.apache.openejb.bval.Validator import org.apache.openejb.util.LogCategory; import org.apache.openejb.util.Logger; +import javax.naming.NamingException; import javax.validation.ConstraintValidatorFactory; import javax.validation.MessageInterpolator; import javax.validation.ParameterNameProvider; @@ -29,12 +30,26 @@ import javax.validation.Validator; import javax.validation.ValidatorContext; import javax.validation.ValidatorFactory; import java.io.Serializable; +import java.util.Map; public class ValidatorFactoryWrapper implements ValidatorFactory, Serializable { public static final Logger logger = Logger.getInstance(LogCategory.OPENEJB, ValidatorFactoryWrapper.class); - private static ValidatorFactory factory() { - return ValidatorUtil.validatorFactory(); + private final Map<ComparableValidationConfig, ValidatorFactory> fallbackValidators; + + private ValidatorFactory factory() { + try { + return ValidatorUtil.lookupFactory(); + } catch (final NamingException e) { // in absolute we should sort them to get the closest one of the persistence-unit? + if (!fallbackValidators.isEmpty()) { + return fallbackValidators.values().iterator().next(); + } + return ValidatorUtil.tryJndiLaterFactory(); + } + } + + public ValidatorFactoryWrapper(final Map<ComparableValidationConfig, ValidatorFactory> validators) { + fallbackValidators = validators; } @Override Modified: tomee/tomee/trunk/container/openejb-core/src/main/java/org/apache/openejb/bval/ValidatorUtil.java URL: http://svn.apache.org/viewvc/tomee/tomee/trunk/container/openejb-core/src/main/java/org/apache/openejb/bval/ValidatorUtil.java?rev=1629580&r1=1629579&r2=1629580&view=diff ============================================================================== --- tomee/tomee/trunk/container/openejb-core/src/main/java/org/apache/openejb/bval/ValidatorUtil.java (original) +++ tomee/tomee/trunk/container/openejb-core/src/main/java/org/apache/openejb/bval/ValidatorUtil.java Mon Oct 6 07:24:30 2014 @@ -43,12 +43,20 @@ public final class ValidatorUtil { public static ValidatorFactory validatorFactory() { try { - return (ValidatorFactory) new InitialContext().lookup("java:comp/ValidatorFactory"); + return lookupFactory(); } catch (final NamingException e) { - return proxy(ValidatorFactory.class, "java:comp/ValidatorFactory"); + return tryJndiLaterFactory(); } } + public static ValidatorFactory lookupFactory() throws NamingException { + return (ValidatorFactory) new InitialContext().lookup("java:comp/ValidatorFactory"); + } + + public static ValidatorFactory tryJndiLaterFactory() { + return proxy(ValidatorFactory.class, "java:comp/ValidatorFactory"); + } + public static Validator validator() { try { return (Validator) new InitialContext().lookup("java:comp/Validator"); @@ -113,7 +121,9 @@ public final class ValidatorUtil { } } } - break; + if (ClassLoader.getSystemClassLoader() != appContextClassLoader) { + break; + } // else we surely have a single AppContext so let's try WebContext } for (final WebContext web : appContext.getWebContexts()) { final ClassLoader webClassLoader = web.getClassLoader();