diff --git a/ext/bean-validation/pom.xml b/ext/bean-validation/pom.xml index d490857a6b..15f55bd073 100644 --- a/ext/bean-validation/pom.xml +++ b/ext/bean-validation/pom.xml @@ -2,6 +2,7 @@ diff --git a/ext/bean-validation/src/main/java/org/glassfish/jersey/server/validation/internal/CompositeInjectingConstraintValidatorFactory.java b/ext/bean-validation/src/main/java/org/glassfish/jersey/server/validation/internal/CompositeInjectingConstraintValidatorFactory.java new file mode 100644 index 0000000000..271015dbd9 --- /dev/null +++ b/ext/bean-validation/src/main/java/org/glassfish/jersey/server/validation/internal/CompositeInjectingConstraintValidatorFactory.java @@ -0,0 +1,58 @@ +/* + * Copyright (c) 2018 Payara Foundation and/or its affiliates. All rights reserved. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v. 2.0, which is available at + * http://www.eclipse.org/legal/epl-2.0. + * + * This Source Code may also be made available under the following Secondary + * Licenses when the conditions for such availability set forth in the + * Eclipse Public License v. 2.0 are satisfied: GNU General Public License, + * version 2 with the GNU Classpath Exception, which is available at + * https://www.gnu.org/software/classpath/license.html. + * + * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0 + */ +package org.glassfish.jersey.server.validation.internal; + +import javax.annotation.PostConstruct; +import javax.validation.ConstraintValidator; +import javax.validation.ConstraintValidatorFactory; +import javax.ws.rs.container.ResourceContext; +import javax.ws.rs.core.Context; + +/** + * {@link ConstraintValidatorFactory} implementation that uses {@link InjectingConstraintValidatorFactory} + * by default and fallbacks to {@link HibernateInjectingConstraintValidatorFactory} when the resource + * cannot be found in resource context of Jersey. + * + * @author Mert Caliskan + */ +public class CompositeInjectingConstraintValidatorFactory implements ConstraintValidatorFactory { + + @Context + private ResourceContext resourceContext; + + private InjectingConstraintValidatorFactory jerseyVF; + private HibernateInjectingConstraintValidatorFactory hibernateVF; + + @PostConstruct + void postConstruct() { + jerseyVF = resourceContext.getResource(InjectingConstraintValidatorFactory.class); + hibernateVF = resourceContext.getResource(HibernateInjectingConstraintValidatorFactory.class); + } + + @Override + public > T getInstance(final Class key) { + T jerseyInstance = jerseyVF.getInstance(key); + if (jerseyInstance == null) { + return hibernateVF.getInstance(key); + } + return jerseyInstance; + } + + @Override + public void releaseInstance(final ConstraintValidator instance) { + // NOOP + } +} \ No newline at end of file diff --git a/ext/bean-validation/src/main/java/org/glassfish/jersey/server/validation/internal/DestructibleBeanInstance.java b/ext/bean-validation/src/main/java/org/glassfish/jersey/server/validation/internal/DestructibleBeanInstance.java new file mode 100644 index 0000000000..136a007609 --- /dev/null +++ b/ext/bean-validation/src/main/java/org/glassfish/jersey/server/validation/internal/DestructibleBeanInstance.java @@ -0,0 +1,63 @@ +/* + * Hibernate Validator, declare and validate application constraints + * + * License: Apache License, Version 2.0 + * See the license.txt file in the root directory or . + */ +// Portions Copyright [2018] [Payara Foundation and/or its affiliates] + +package org.glassfish.jersey.server.validation.internal; + +import javax.enterprise.context.spi.CreationalContext; +import javax.enterprise.inject.spi.AnnotatedType; +import javax.enterprise.inject.spi.BeanManager; +import javax.enterprise.inject.spi.InjectionTarget; + +/** + * @author Hardy Ferentschik + */ +public class DestructibleBeanInstance { + private final T instance; + private final InjectionTarget injectionTarget; + + public DestructibleBeanInstance(BeanManager beanManager, Class key) { + this.injectionTarget = createInjectionTarget(beanManager, key); + this.instance = createAndInjectBeans(beanManager, injectionTarget); + } + + @SuppressWarnings("unchecked") + public DestructibleBeanInstance(BeanManager beanManager, T instance) { + this.injectionTarget = createInjectionTarget(beanManager, (Class) instance.getClass()); + injectBeans(beanManager, beanManager.createCreationalContext(null), injectionTarget, instance); + this.instance = instance; + } + + public T getInstance() { + return instance; + } + + public void destroy() { + injectionTarget.preDestroy(instance); + injectionTarget.dispose(instance); + } + + private InjectionTarget createInjectionTarget(BeanManager beanManager, Class type) { + AnnotatedType annotatedType = beanManager.createAnnotatedType(type); + return beanManager.createInjectionTarget(annotatedType); + } + + private static T createAndInjectBeans(BeanManager beanManager, InjectionTarget injectionTarget) { + CreationalContext creationalContext = beanManager.createCreationalContext(null); + + T instance = injectionTarget.produce(creationalContext); + injectBeans(beanManager, creationalContext, injectionTarget, instance); + + return instance; + } + + private static void injectBeans(BeanManager beanManager, CreationalContext creationalContext, + InjectionTarget injectionTarget, T instance) { + injectionTarget.inject(instance, creationalContext); + injectionTarget.postConstruct(instance); + } +} \ No newline at end of file diff --git a/ext/bean-validation/src/main/java/org/glassfish/jersey/server/validation/internal/HibernateInjectingConstraintValidatorFactory.java b/ext/bean-validation/src/main/java/org/glassfish/jersey/server/validation/internal/HibernateInjectingConstraintValidatorFactory.java new file mode 100644 index 0000000000..d0ad811a95 --- /dev/null +++ b/ext/bean-validation/src/main/java/org/glassfish/jersey/server/validation/internal/HibernateInjectingConstraintValidatorFactory.java @@ -0,0 +1,52 @@ +/* + * Hibernate Validator, declare and validate application constraints + * + * License: Apache License, Version 2.0 + * See the license.txt file in the root directory or . + */ +// Portions Copyright [2018] [Payara Foundation and/or its affiliates] + +package org.glassfish.jersey.server.validation.internal; + +import org.glassfish.jersey.ext.cdi1x.internal.CdiUtil; + +import javax.annotation.PostConstruct; +import javax.enterprise.inject.spi.BeanManager; +import javax.validation.ConstraintValidator; +import javax.validation.ConstraintValidatorFactory; +import java.util.Collections; +import java.util.IdentityHashMap; +import java.util.Map; + +public class HibernateInjectingConstraintValidatorFactory implements ConstraintValidatorFactory { + // TODO look for something with better performance (HF) + private final Map> constraintValidatorMap = + Collections.synchronizedMap(new IdentityHashMap>()); + + private BeanManager beanManager; + + @PostConstruct + void postConstruct() { + this.beanManager = CdiUtil.getBeanManager(); + } + + @Override + public > T getInstance(Class key) { + DestructibleBeanInstance destructibleBeanInstance = new DestructibleBeanInstance(beanManager, key); + constraintValidatorMap.put(destructibleBeanInstance.getInstance(), destructibleBeanInstance); + return destructibleBeanInstance.getInstance(); + } + + @Override + public void releaseInstance(ConstraintValidator instance) { + DestructibleBeanInstance destructibleBeanInstance = constraintValidatorMap.remove(instance); + // HV-865 (Cleanup is multi threaded and instances can be removed by multiple threads. + // Explicit null check is needed) + if (destructibleBeanInstance != null) { + destructibleBeanInstance.destroy(); + } + } +} + + + diff --git a/ext/bean-validation/src/main/java/org/glassfish/jersey/server/validation/internal/ValidationBinder.java b/ext/bean-validation/src/main/java/org/glassfish/jersey/server/validation/internal/ValidationBinder.java index 050f920842..a5b5d06cd9 100644 --- a/ext/bean-validation/src/main/java/org/glassfish/jersey/server/validation/internal/ValidationBinder.java +++ b/ext/bean-validation/src/main/java/org/glassfish/jersey/server/validation/internal/ValidationBinder.java @@ -1,5 +1,6 @@ /* * Copyright (c) 2012, 2018 Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2018, 2019 Payara Foundation and/or its affiliates. All rights reserved. * * This program and the accompanying materials are made available under the * terms of the Eclipse Public License v. 2.0, which is available at @@ -256,8 +257,9 @@ private ConfiguredValidator getDefaultValidator() { private ValidatorContext getDefaultValidatorContext(final ValidateOnExecutionHandler handler) { final ValidatorContext context = factory.usingContext(); - // Default Configuration. - context.constraintValidatorFactory(resourceContext.getResource(InjectingConstraintValidatorFactory.class)); + // Composite Configuration - due to PAYARA-2491 + // https://github.com/payara/Payara/issues/2245 + context.constraintValidatorFactory(resourceContext.getResource(CompositeInjectingConstraintValidatorFactory.class)); // Traversable Resolver. context.traversableResolver(getTraversableResolver(factory.getTraversableResolver(), handler));