Author: rmannibucau Date: Mon Oct 6 07:26:04 2014 New Revision: 1629582 URL: http://svn.apache.org/r1629582 Log: TOMEE-1381 passing good ValidatorFactory property to JPA
Added: tomee/tomee/branches/tomee-1.7.x/container/openejb-core/src/main/java/org/apache/openejb/assembler/classic/ComparableValidationConfig.java tomee/tomee/branches/tomee-1.7.x/container/openejb-core/src/main/java/org/apache/openejb/assembler/classic/LazyValidatorFactory.java Modified: tomee/tomee/branches/tomee-1.7.x/container/openejb-core/src/main/java/org/apache/openejb/assembler/classic/Assembler.java tomee/tomee/branches/tomee-1.7.x/container/openejb-core/src/main/java/org/apache/openejb/assembler/classic/EntityManagerFactoryCallable.java tomee/tomee/branches/tomee-1.7.x/container/openejb-core/src/main/java/org/apache/openejb/assembler/classic/LazyValidator.java tomee/tomee/branches/tomee-1.7.x/container/openejb-core/src/main/java/org/apache/openejb/assembler/classic/PersistenceBuilder.java tomee/tomee/branches/tomee-1.7.x/container/openejb-core/src/main/java/org/apache/openejb/assembler/classic/ValidatorFactoryWrapper.java tomee/tomee/branches/tomee-1.7.x/container/openejb-core/src/main/java/org/apache/openejb/bval/ValidatorUtil.java Modified: tomee/tomee/branches/tomee-1.7.x/container/openejb-core/src/main/java/org/apache/openejb/assembler/classic/Assembler.java URL: http://svn.apache.org/viewvc/tomee/tomee/branches/tomee-1.7.x/container/openejb-core/src/main/java/org/apache/openejb/assembler/classic/Assembler.java?rev=1629582&r1=1629581&r2=1629582&view=diff ============================================================================== --- tomee/tomee/branches/tomee-1.7.x/container/openejb-core/src/main/java/org/apache/openejb/assembler/classic/Assembler.java (original) +++ tomee/tomee/branches/tomee-1.7.x/container/openejb-core/src/main/java/org/apache/openejb/assembler/classic/Assembler.java Mon Oct 6 07:26:04 2014 @@ -36,16 +36,13 @@ import org.apache.openejb.Injection; import org.apache.openejb.JndiConstants; import org.apache.openejb.MethodContext; import org.apache.openejb.NoSuchApplicationException; -import org.apache.openejb.OpenEJB; import org.apache.openejb.OpenEJBException; import org.apache.openejb.OpenEJBRuntimeException; import org.apache.openejb.UndeployException; -import org.apache.openejb.api.DestroyableResource; import org.apache.openejb.assembler.classic.event.AssemblerAfterApplicationCreated; import org.apache.openejb.assembler.classic.event.AssemblerBeforeApplicationDestroyed; import org.apache.openejb.assembler.classic.event.AssemblerCreated; import org.apache.openejb.assembler.classic.event.AssemblerDestroyed; -import org.apache.openejb.assembler.classic.event.BeanContextsInitializedEvent; import org.apache.openejb.assembler.classic.event.ContainerSystemPostCreate; import org.apache.openejb.assembler.classic.event.ContainerSystemPreDestroy; import org.apache.openejb.assembler.monitoring.JMXContainer; @@ -95,7 +92,6 @@ import org.apache.openejb.jpa.integratio import org.apache.openejb.loader.IO; import org.apache.openejb.loader.JarLocation; import org.apache.openejb.loader.Options; -import org.apache.openejb.loader.ProvisioningUtil; import org.apache.openejb.loader.SystemInstance; import org.apache.openejb.monitoring.DynamicMBeanWrapper; import org.apache.openejb.monitoring.LocalMBeanServer; @@ -227,7 +223,8 @@ public class Assembler extends Assembler public static final String TIMER_STORE_CLASS = "timerStore.class"; private static final ReentrantLock lock = new ReentrantLock(true); public static final String OPENEJB_TIMERS_ON = "openejb.timers.on"; - + public static final Class<?>[] VALIDATOR_FACTORY_INTERFACES = new Class<?>[]{ValidatorFactory.class}; + public static final Class<?>[] VALIDATOR_INTERFACES = new Class<?>[]{Validator.class}; private final boolean skipLoaderIfPossible; Messages messages = new Messages(Assembler.class.getPackage().getName()); @@ -325,8 +322,6 @@ public class Assembler extends Assembler final Collection<URL> urls = NewLoaderLogic.applyBuiltinExcludes(new UrlSet(Assembler.class.getClassLoader()).excludeJvm()).getUrls(); Extensions.installExtensions(new ResourceFinder("META-INF", urls.toArray(new URL[urls.size()]))); return; - } catch (final MalformedURLException e) { - // no-op } catch (final IOException e) { // no-op } @@ -475,8 +470,9 @@ public class Assembler extends Assembler */ @SuppressWarnings("ThrowableResultOfMethodCallIgnored") public void buildContainerSystem(final OpenEjbConfiguration configInfo) throws Exception { - if (SystemInstance.get().getOptions().get(OPENEJB_JPA_DEPLOY_TIME_ENHANCEMENT_PROP, false)) { - SystemInstance.get().addObserver(new DeployTimeEnhancer()); + final SystemInstance systemInstance = SystemInstance.get(); + if (systemInstance.getOptions().get(OPENEJB_JPA_DEPLOY_TIME_ENHANCEMENT_PROP, false)) { + systemInstance.addObserver(new DeployTimeEnhancer()); } for (final ServiceInfo serviceInfo : configInfo.facilities.services) { @@ -517,14 +513,14 @@ public class Assembler extends Assembler } catch (final Throwable e) { logger.error("appNotDeployed", e, appInfo.path); - final DeploymentExceptionManager exceptionManager = SystemInstance.get().getComponent(DeploymentExceptionManager.class); + final DeploymentExceptionManager exceptionManager = systemInstance.getComponent(DeploymentExceptionManager.class); if (exceptionManager != null && e instanceof Exception) { exceptionManager.saveDeploymentException(appInfo, (Exception) e); } } } - SystemInstance.get().fireEvent(new ContainerSystemPostCreate()); + systemInstance.fireEvent(new ContainerSystemPostCreate()); } private void createJavaGlobal() { @@ -535,10 +531,6 @@ public class Assembler extends Assembler } } - public boolean isDeployed(final String path) { - return deployedApplications.containsKey(ProvisioningUtil.realLocation(path)); - } - public Collection<AppInfo> getDeployedApplications() { return new ArrayList<AppInfo>(deployedApplications.values()); } @@ -623,7 +615,7 @@ public class Assembler extends Assembler return createApplication(appInfo, classLoader, true); } - public AppContext createApplication(final AppInfo appInfo, ClassLoader classLoader, final boolean start) throws OpenEJBException, IOException, NamingException { + private AppContext createApplication(final AppInfo appInfo, ClassLoader classLoader, final boolean start) throws OpenEJBException, IOException, NamingException { // The path is used in the UrlCache, command line deployer, JNDI name templates, tomcat integration and a few other places if (appInfo.appId == null) { throw new IllegalArgumentException("AppInfo.appId cannot be null"); @@ -636,13 +628,6 @@ public class Assembler extends Assembler logger.info("createApplication.start", appInfo.path); - // try { - // Thread.sleep(5000); - // } catch (InterruptedException e) { - // e.printStackTrace(); - // Thread.interrupted(); - // } - // To start out, ensure we don't already have any beans deployed with duplicate IDs. This // is a conflict we can't handle. final List<String> used = new ArrayList<String>(); @@ -698,23 +683,41 @@ public class Assembler extends Assembler final Context containerSystemContext = containerSystem.getJNDIContext(); - if (!SystemInstance.get().hasProperty("openejb.geronimo")) { + 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 // so it has to be constructed before final List<CommonInfoObject> vfs = listCommonInfoObjectsForAppInfo(appInfo); - final Map<String, ValidatorFactory> validatorFactories = new HashMap<String, ValidatorFactory>(); + for (final CommonInfoObject info : vfs) { - ValidatorFactory factory = null; - try { - factory = ValidatorBuilder.buildFactory(classLoader, info.validationInfo); - } catch (final ValidationException ve) { - logger.warning("can't build the validation factory for module " + info.uniqueId, ve); - } - if (factory != null) { - validatorFactories.put(info.uniqueId, factory); + final ComparableValidationConfig conf = new ComparableValidationConfig( + info.validationInfo.providerClassName, info.validationInfo.messageInterpolatorClass, + info.validationInfo.traversableResolverClass, info.validationInfo.constraintFactoryClass, + info.validationInfo.propertyTypes, info.validationInfo.constraintMappings + ); + 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); } // validators bindings @@ -726,9 +729,12 @@ public class Assembler extends Assembler Validator validator; try { - validator = factory.usingContext().getValidator(); + final LazyValidator lazyValidator = new LazyValidator(factory); + validator = (Validator) Proxy.newProxyInstance(appContext.getClassLoader(), VALIDATOR_INTERFACES, lazyValidator); + lazyValidators.put(id, lazyValidator); } catch (final Exception e) { - validator = (Validator) Proxy.newProxyInstance(appContext.getClassLoader(), new Class<?>[]{Validator.class}, new LazyValidator(factory)); + logger.error(e.getMessage(), e); + continue; } containerSystemContext.bind(VALIDATOR_NAMING_CONTEXT + id, validator); @@ -738,6 +744,8 @@ public class Assembler extends Assembler throw new OpenEJBException(e); } } + + validatorFactories.clear(); } // JPA - Persistence Units MUST be processed first since they will add ClassFileTransformers @@ -747,7 +755,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) { @@ -800,9 +808,31 @@ public class Assembler extends Assembler appContext.getBindings().put("app/BeanManager", appContext.getBeanManager()); } - // before starting everything, give the user the opportunity to hack on the AppContext/BeanContext - final SystemInstance systemInstance = SystemInstance.get(); - systemInstance.fireEvent(new BeanContextsInitializedEvent(appInfo, appContext, allDeployments)); + // now cdi is started we can try to bind real validator factory and validator + if (!isGeronimo) { + for (final Entry<String, LazyValidator> lazyValidator : lazyValidators.entrySet()) { + final String id = lazyValidator.getKey(); + final ValidatorFactory factory = lazyValidatorFactories.get(lazyValidator.getKey()).getFactory(); + try { + final String factoryName = VALIDATOR_FACTORY_NAMING_CONTEXT + id; + containerSystemContext.unbind(factoryName); + containerSystemContext.bind(factoryName, factory); + + final String validatoryName = VALIDATOR_NAMING_CONTEXT + id; + try { // do it after factory cause of TCKs which expects validator to be created later + final Validator val = lazyValidator.getValue().getValidator(); + containerSystemContext.unbind(validatoryName); + containerSystemContext.bind(validatoryName, val); + } catch (final Exception e) { + logger.error(e.getMessage(), e); + } + } catch (final NameAlreadyBoundException e) { + throw new OpenEJBException("ValidatorFactory already exists for module " + id, e); + } catch (final Exception e) { + throw new OpenEJBException(e); + } + } + } startEjbs(start, allDeployments); @@ -849,6 +879,7 @@ public class Assembler extends Assembler } // WebApp + final SystemInstance systemInstance = SystemInstance.get(); final WebAppBuilder webAppBuilder = systemInstance.getComponent(WebAppBuilder.class); if (webAppBuilder != null) { @@ -1245,7 +1276,7 @@ public class Assembler extends Assembler }else{ if(null == appContext.getWebBeansContext()){ appContext.setWebBeansContext(webBeansContext); - } + } return; } @@ -1272,9 +1303,9 @@ public class Assembler extends Assembler appContext.setCdiEnabled(false); OpenEJBTransactionService.class.cast(services.get(TransactionService.class)).setWebBeansContext(webBeansContext); - appContext.set(WebBeansContext.class, webBeansContext); - appContext.setWebBeansContext(webBeansContext); - } + appContext.set(WebBeansContext.class, webBeansContext); + appContext.setWebBeansContext(webBeansContext); + } } private TransactionPolicyFactory createTransactionPolicyFactory(final EjbJarInfo ejbJar, final ClassLoader classLoader) { @@ -1494,12 +1525,6 @@ public class Assembler extends Assembler } catch (final Exception e) { logger.debug("Not processing resource on destroy: " + className, e); } - } else if (DestroyableResource.class.isInstance(object)) { - try { - DestroyableResource.class.cast(object).destroyResource(); - } catch (final RuntimeException e) { - logger.error(e.getMessage(), e); - } } else if (logger.isDebugEnabled() && !DataSource.class.isInstance(object)) { logger.debug("Not processing resource on destroy: " + className); } @@ -1917,11 +1942,7 @@ public class Assembler extends Assembler jars.addAll(Arrays.asList(SystemInstance.get().getComponent(ClassLoaderEnricher.class).applicationEnrichment())); // Create the class loader - final ParentClassLoaderFinder parentFinder = SystemInstance.get().getComponent(ParentClassLoaderFinder.class); - ClassLoader parent = OpenEJB.class.getClassLoader(); - if (parentFinder != null) { - parent = parentFinder.getParentClassLoader(parent); - } + final ClassLoader parent = ParentClassLoaderFinder.Helper.get(); final String prefix; if (appInfo.webAppAlone) { @@ -1943,7 +1964,11 @@ public class Assembler extends Assembler // try to get the app BM from the AppClassLoader having stored it in a map). // since we don't really need to create a classloader here when starting from classpath just let skip this step if (skipLoaderIfPossible) { // TODO: maybe use a boolean to know if all urls comes from the classpath to avoid this validation - final Collection<File> urls = new ArrayList<File>(); + if ("classpath.ear".equals(appInfo.appId)) { + return parent; + } + + final Collection<File> urls = new HashSet<File>(); for (final URL url : ClassLoaders.findUrls(parent)) { // need to convert it to file since urls can be file:/xxx or jar:file:///xxx try { urls.add(URLs.toFile(url).getCanonicalFile()); @@ -1959,24 +1984,38 @@ public class Assembler extends Assembler try { if (!urls.contains(URLs.toFile(url).getCanonicalFile())) { allIsIntheClasspath = false; + if (logger.isDebugEnabled()) { + logger.debug(url.toExternalForm() + " (" + URLs.toFile(url) + + ") is not in the classloader so we'll create a dedicated classloader for this app"); + } break; } } catch (final Exception ignored) { allIsIntheClasspath = false; + if (logger.isDebugEnabled()) { + logger.debug(url.toExternalForm() + " (" + URLs.toFile(url) + ") is not in the classloader", ignored); + } break; } } if (allIsIntheClasspath) { + logger.info("Not creating another application classloader for " + appInfo.appId); return parent; } else if (logger.isDebugEnabled()) { logger.debug("Logging all urls from the app since we don't skip the app classloader creation:"); for (final URL url : filtered) { logger.debug(" -> " + url.toExternalForm()); } + logger.debug("Logging all urls from the classloader since we don't skip the app classloader creation:"); + for (final File url : urls) { + logger.debug(" -> " + url.getAbsolutePath()); + } } } + logger.info("Creating dedicated application classloader for " + appInfo.appId); + if (!appInfo.delegateFirst) { return ClassLoaderUtil.createClassLoader(appInfo.path, filtered, parent); } @@ -2048,7 +2087,7 @@ public class Assembler extends Assembler containerObjectNames.add(objectName); } catch (final Exception e) { // no-op - } catch (final NoClassDefFoundError ncdfe) { // OSGi + } catch (final NoClassDefFoundError ncdfe) { // no-op } } Added: tomee/tomee/branches/tomee-1.7.x/container/openejb-core/src/main/java/org/apache/openejb/assembler/classic/ComparableValidationConfig.java URL: http://svn.apache.org/viewvc/tomee/tomee/branches/tomee-1.7.x/container/openejb-core/src/main/java/org/apache/openejb/assembler/classic/ComparableValidationConfig.java?rev=1629582&view=auto ============================================================================== --- tomee/tomee/branches/tomee-1.7.x/container/openejb-core/src/main/java/org/apache/openejb/assembler/classic/ComparableValidationConfig.java (added) +++ tomee/tomee/branches/tomee-1.7.x/container/openejb-core/src/main/java/org/apache/openejb/assembler/classic/ComparableValidationConfig.java Mon Oct 6 07:26:04 2014 @@ -0,0 +1,81 @@ +/* + * 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 Properties propertyTypes; + private final List<String> constraintMappings; + + private final int hash; + + public ComparableValidationConfig(final String providerClassName, final String messageInterpolatorClass, + final String traversableResolverClass, final String constraintFactoryClass, + final Properties propertyTypes, final List<String> constraintMappings) { + this.providerClassName = providerClassName; + this.messageInterpolatorClass = messageInterpolatorClass; + this.traversableResolverClass = traversableResolverClass; + this.constraintFactoryClass = constraintFactoryClass; + this.propertyTypes = propertyTypes; + this.constraintMappings = constraintMappings; + + 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 + (propertyTypes != null ? propertyTypes.hashCode() : 0); + result = 31 * result + (constraintMappings != null ? constraintMappings.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 (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 (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; + return true; + } + + @Override + public int hashCode() { + return hash; + } +} Modified: tomee/tomee/branches/tomee-1.7.x/container/openejb-core/src/main/java/org/apache/openejb/assembler/classic/EntityManagerFactoryCallable.java URL: http://svn.apache.org/viewvc/tomee/tomee/branches/tomee-1.7.x/container/openejb-core/src/main/java/org/apache/openejb/assembler/classic/EntityManagerFactoryCallable.java?rev=1629582&r1=1629581&r2=1629582&view=diff ============================================================================== --- tomee/tomee/branches/tomee-1.7.x/container/openejb-core/src/main/java/org/apache/openejb/assembler/classic/EntityManagerFactoryCallable.java (original) +++ tomee/tomee/branches/tomee-1.7.x/container/openejb-core/src/main/java/org/apache/openejb/assembler/classic/EntityManagerFactoryCallable.java Mon Oct 6 07:26:04 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); @@ -60,8 +64,8 @@ public class EntityManagerFactoryCallabl final EntityManagerFactory emf = persistenceProvider.createContainerEntityManagerFactory(unitInfo, properties); if (unitInfo.getProperties() != null - && "true".equalsIgnoreCase(unitInfo.getProperties().getProperty(OPENEJB_JPA_INIT_ENTITYMANAGER)) - || SystemInstance.get().getOptions().get(OPENEJB_JPA_INIT_ENTITYMANAGER, false)) { + && "true".equalsIgnoreCase(unitInfo.getProperties().getProperty(OPENEJB_JPA_INIT_ENTITYMANAGER)) + || SystemInstance.get().getOptions().get(OPENEJB_JPA_INIT_ENTITYMANAGER, false)) { emf.createEntityManager().close(); } @@ -79,6 +83,7 @@ public class EntityManagerFactoryCallabl } } + // properties that have to be passed to properties parameters and not unit properties private void customizeProperties(final Map<String, Object> properties) { final String pool = SystemInstance.get().getProperty(OPENJPA_ENTITY_MANAGER_FACTORY_POOL); if (pool != null) { Modified: tomee/tomee/branches/tomee-1.7.x/container/openejb-core/src/main/java/org/apache/openejb/assembler/classic/LazyValidator.java URL: http://svn.apache.org/viewvc/tomee/tomee/branches/tomee-1.7.x/container/openejb-core/src/main/java/org/apache/openejb/assembler/classic/LazyValidator.java?rev=1629582&r1=1629581&r2=1629582&view=diff ============================================================================== --- tomee/tomee/branches/tomee-1.7.x/container/openejb-core/src/main/java/org/apache/openejb/assembler/classic/LazyValidator.java (original) +++ tomee/tomee/branches/tomee-1.7.x/container/openejb-core/src/main/java/org/apache/openejb/assembler/classic/LazyValidator.java Mon Oct 6 07:26:04 2014 @@ -20,6 +20,7 @@ package org.apache.openejb.assembler.cla import javax.validation.Validator; import javax.validation.ValidatorFactory; import java.lang.reflect.InvocationHandler; +import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; import java.util.concurrent.locks.ReentrantLock; @@ -35,7 +36,15 @@ public class LazyValidator implements In @Override public Object invoke(final Object proxy, final Method method, final Object[] args) throws Throwable { + ensureDelegate(); + try { + return method.invoke(validator, args); + } catch (final InvocationTargetException ite) { + throw ite.getCause(); + } + } + private void ensureDelegate() { if (validator == null) { final ReentrantLock l = lock; @@ -49,7 +58,10 @@ public class LazyValidator implements In l.unlock(); } } + } - return method.invoke(validator, args); + public Validator getValidator() { + ensureDelegate(); + return validator; } } Added: tomee/tomee/branches/tomee-1.7.x/container/openejb-core/src/main/java/org/apache/openejb/assembler/classic/LazyValidatorFactory.java URL: http://svn.apache.org/viewvc/tomee/tomee/branches/tomee-1.7.x/container/openejb-core/src/main/java/org/apache/openejb/assembler/classic/LazyValidatorFactory.java?rev=1629582&view=auto ============================================================================== --- tomee/tomee/branches/tomee-1.7.x/container/openejb-core/src/main/java/org/apache/openejb/assembler/classic/LazyValidatorFactory.java (added) +++ tomee/tomee/branches/tomee-1.7.x/container/openejb-core/src/main/java/org/apache/openejb/assembler/classic/LazyValidatorFactory.java Mon Oct 6 07:26:04 2014 @@ -0,0 +1,65 @@ +/* + * 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 javax.validation.ValidatorFactory; +import java.lang.reflect.InvocationHandler; +import java.lang.reflect.InvocationTargetException; +import java.lang.reflect.Method; +import java.util.concurrent.locks.ReentrantLock; + +// TODO: make it generic (LazyDelegate + Factory + refactor LazyValidator) +public class LazyValidatorFactory implements InvocationHandler { + private final ReentrantLock lock = new ReentrantLock(); + private final ClassLoader loader; + private final ValidationInfo info; + private volatile ValidatorFactory factory; + + public LazyValidatorFactory(final ClassLoader classLoader, final ValidationInfo validationInfo) { + this.loader = classLoader; + this.info = validationInfo; + } + + @Override + public Object invoke(final Object proxy, final Method method, final Object[] args) throws Throwable { + ensureDelegate(); + try { + return method.invoke(factory, args); + } catch (final InvocationTargetException ite) { + throw ite.getCause(); + } + } + + private void ensureDelegate() { + if (factory == null) { + final ReentrantLock l = lock; + l.lock(); + try { + if (factory == null) { + factory = ValidatorBuilder.buildFactory(loader, info); + } + } finally { + l.unlock(); + } + } + } + + public ValidatorFactory getFactory() { + ensureDelegate(); + return factory; + } +} Modified: tomee/tomee/branches/tomee-1.7.x/container/openejb-core/src/main/java/org/apache/openejb/assembler/classic/PersistenceBuilder.java URL: http://svn.apache.org/viewvc/tomee/tomee/branches/tomee-1.7.x/container/openejb-core/src/main/java/org/apache/openejb/assembler/classic/PersistenceBuilder.java?rev=1629582&r1=1629581&r2=1629582&view=diff ============================================================================== --- tomee/tomee/branches/tomee-1.7.x/container/openejb-core/src/main/java/org/apache/openejb/assembler/classic/PersistenceBuilder.java (original) +++ tomee/tomee/branches/tomee-1.7.x/container/openejb-core/src/main/java/org/apache/openejb/assembler/classic/PersistenceBuilder.java Mon Oct 6 07:26:04 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/branches/tomee-1.7.x/container/openejb-core/src/main/java/org/apache/openejb/assembler/classic/ValidatorFactoryWrapper.java URL: http://svn.apache.org/viewvc/tomee/tomee/branches/tomee-1.7.x/container/openejb-core/src/main/java/org/apache/openejb/assembler/classic/ValidatorFactoryWrapper.java?rev=1629582&r1=1629581&r2=1629582&view=diff ============================================================================== --- tomee/tomee/branches/tomee-1.7.x/container/openejb-core/src/main/java/org/apache/openejb/assembler/classic/ValidatorFactoryWrapper.java (original) +++ tomee/tomee/branches/tomee-1.7.x/container/openejb-core/src/main/java/org/apache/openejb/assembler/classic/ValidatorFactoryWrapper.java Mon Oct 6 07:26:04 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.TraversableResolver; @@ -28,12 +29,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/branches/tomee-1.7.x/container/openejb-core/src/main/java/org/apache/openejb/bval/ValidatorUtil.java URL: http://svn.apache.org/viewvc/tomee/tomee/branches/tomee-1.7.x/container/openejb-core/src/main/java/org/apache/openejb/bval/ValidatorUtil.java?rev=1629582&r1=1629581&r2=1629582&view=diff ============================================================================== --- tomee/tomee/branches/tomee-1.7.x/container/openejb-core/src/main/java/org/apache/openejb/bval/ValidatorUtil.java (original) +++ tomee/tomee/branches/tomee-1.7.x/container/openejb-core/src/main/java/org/apache/openejb/bval/ValidatorUtil.java Mon Oct 6 07:26:04 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();