diff --git a/tck/src/main/java/ee/jakarta/tck/data/common/cdi/AddressRepository.java b/tck/src/main/java/ee/jakarta/tck/data/common/cdi/AddressRepository.java index ea4137b46..f10122807 100644 --- a/tck/src/main/java/ee/jakarta/tck/data/common/cdi/AddressRepository.java +++ b/tck/src/main/java/ee/jakarta/tck/data/common/cdi/AddressRepository.java @@ -15,6 +15,8 @@ */ package ee.jakarta.tck.data.common.cdi; +import jakarta.enterprise.context.Dependent; + import java.util.HashMap; import java.util.List; import java.util.Map; @@ -25,6 +27,7 @@ * An implementation of the AddressBook repository interface. * Implementation is backed by an in-memory HashMap. */ +@Dependent public class AddressRepository implements AddressBook { private Map<UUID, AddressRecord> data = new HashMap<UUID, AddressRecord>(); diff --git a/tck/src/main/java/ee/jakarta/tck/data/common/cdi/DirectoryRepository.java b/tck/src/main/java/ee/jakarta/tck/data/common/cdi/DirectoryRepository.java index 1851dc555..b589d5420 100644 --- a/tck/src/main/java/ee/jakarta/tck/data/common/cdi/DirectoryRepository.java +++ b/tck/src/main/java/ee/jakarta/tck/data/common/cdi/DirectoryRepository.java @@ -15,6 +15,8 @@ */ package ee.jakarta.tck.data.common.cdi; +import jakarta.enterprise.context.Dependent; + import java.util.Comparator; import java.util.HashMap; import java.util.List; @@ -25,6 +27,7 @@ * An implementation of the Directory repository interface. * Implementation is backed by an in-memory HashMap and has one function. */ +@Dependent public class DirectoryRepository implements Directory { private Map<Long, Person> data = new HashMap<Long, Person>(); diff --git a/tck/src/main/java/ee/jakarta/tck/data/core/cdi/ExtensionTests.java b/tck/src/main/java/ee/jakarta/tck/data/core/cdi/ExtensionTests.java index 82d343457..26562337c 100644 --- a/tck/src/main/java/ee/jakarta/tck/data/core/cdi/ExtensionTests.java +++ b/tck/src/main/java/ee/jakarta/tck/data/core/cdi/ExtensionTests.java @@ -23,19 +23,16 @@ import org.jboss.arquillian.container.test.api.Deployment; import org.jboss.shrinkwrap.api.ShrinkWrap; -import org.jboss.shrinkwrap.api.spec.JavaArchive; import org.jboss.shrinkwrap.api.spec.WebArchive; import ee.jakarta.tck.data.common.cdi.AddressBook; import ee.jakarta.tck.data.common.cdi.AddressRecord; import ee.jakarta.tck.data.common.cdi.Directory; import ee.jakarta.tck.data.common.cdi.Person; -import ee.jakarta.tck.data.core.cdi.provider.BuildCompatibleExtensionImpl; import ee.jakarta.tck.data.framework.junit.anno.AnyEntity; import ee.jakarta.tck.data.framework.junit.anno.Assertion; import ee.jakarta.tck.data.framework.junit.anno.CDI; import ee.jakarta.tck.data.framework.junit.anno.Core; -import jakarta.enterprise.inject.build.compatible.spi.BuildCompatibleExtension; import jakarta.inject.Inject; @Core @@ -44,16 +41,9 @@ public class ExtensionTests { @Deployment public static WebArchive createDeployment() { - JavaArchive provider = ShrinkWrap.create(JavaArchive.class) - .addPackage(BuildCompatibleExtensionImpl.class.getPackage()) - .addAsServiceProvider(BuildCompatibleExtension.class, BuildCompatibleExtensionImpl.class); - - return ShrinkWrap.create(WebArchive.class) .addPackage(ExtensionTests.class.getPackage()) - .addPackage(Person.class.getPackage()) - .addAsLibraries(provider); - + .addPackage(Person.class.getPackage()); } @Inject diff --git a/tck/src/main/java/ee/jakarta/tck/data/core/cdi/provider/BeanCreator.java b/tck/src/main/java/ee/jakarta/tck/data/core/cdi/provider/BeanCreator.java deleted file mode 100644 index ccc70961d..000000000 --- a/tck/src/main/java/ee/jakarta/tck/data/core/cdi/provider/BeanCreator.java +++ /dev/null @@ -1,42 +0,0 @@ -/* - * Copyright (c) 2023, 2024 Contributors to the Eclipse Foundation - * - * 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 ee.jakarta.tck.data.core.cdi.provider; - -import java.util.logging.Logger; - -import jakarta.enterprise.inject.Instance; -import jakarta.enterprise.inject.build.compatible.spi.Parameters; -import jakarta.enterprise.inject.build.compatible.spi.SyntheticBeanCreator; - -/** - * Creates beans for repositories for which the entity class has the PersonEntity annotation. - */ -public class BeanCreator implements SyntheticBeanCreator<Object> { - - private static final Logger log = Logger.getLogger(BeanCreator.class.getCanonicalName()); - - @Override - public Object create(Instance<Object> instance, Parameters parameters) { - Class<?> provider = parameters.get("impl", Class.class); - - try { - return provider.getConstructor().newInstance(); - } catch (Exception e) { - log.warning("Error while constructing implementation of repository: " + e.getMessage()); - return null; - } - } -} diff --git a/tck/src/main/java/ee/jakarta/tck/data/core/cdi/provider/BuildCompatibleExtensionImpl.java b/tck/src/main/java/ee/jakarta/tck/data/core/cdi/provider/BuildCompatibleExtensionImpl.java deleted file mode 100644 index 3d406ab9f..000000000 --- a/tck/src/main/java/ee/jakarta/tck/data/core/cdi/provider/BuildCompatibleExtensionImpl.java +++ /dev/null @@ -1,127 +0,0 @@ -/* - * Copyright (c) 2023, 2024 Contributors to the Eclipse Foundation - * - * 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 ee.jakarta.tck.data.core.cdi.provider; - -import java.lang.reflect.ParameterizedType; -import java.lang.reflect.Type; -import java.util.ArrayList; -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import java.util.logging.Logger; - -import ee.jakarta.tck.data.common.cdi.AddressBook; -import ee.jakarta.tck.data.common.cdi.AddressRepository; -import ee.jakarta.tck.data.common.cdi.Directory; -import ee.jakarta.tck.data.common.cdi.DirectoryRepository; -import ee.jakarta.tck.data.common.cdi.TCKEntity; -import jakarta.data.repository.DataRepository; -import jakarta.data.repository.Repository; -import jakarta.enterprise.context.ApplicationScoped; -import jakarta.enterprise.inject.build.compatible.spi.BuildCompatibleExtension; -import jakarta.enterprise.inject.build.compatible.spi.Enhancement; -import jakarta.enterprise.inject.build.compatible.spi.Synthesis; -import jakarta.enterprise.inject.build.compatible.spi.SyntheticBeanBuilder; -import jakarta.enterprise.inject.build.compatible.spi.SyntheticComponents; -import jakarta.enterprise.inject.build.compatible.spi.Types; -import jakarta.enterprise.lang.model.AnnotationMember; -import jakarta.enterprise.lang.model.declarations.ClassInfo; - -/** - * A fake Jakarta Data provider extension that only produces a single repository class, - * which is because it doesn't have a real implementation and is only for tests - * that register a Jakarta Data provider as a CDI extension. - */ -public class BuildCompatibleExtensionImpl implements BuildCompatibleExtension { - - private static final Logger log = Logger.getLogger(BuildCompatibleExtensionImpl.class.getCanonicalName()); - - // Static relation between Repository and Implementation - private static final Map<Class<?>, Class<?>> staticImplMap = new HashMap<>(); - static { - staticImplMap.put(AddressBook.class, AddressRepository.class); - staticImplMap.put(Directory.class, DirectoryRepository.class); - } - - // List of repository class names - private final List<String> repositoryClassNames = new ArrayList<>(); - - /** - * Identify classes that are annotated with Repository - * and determine which apply to this provider. - */ - @Enhancement(withAnnotations = Repository.class, types = Object.class, withSubtypes = true) - public void enhancement(ClassInfo repositoryClassInfo) throws Exception{ - - // First determine if we support the repository based on entity - Class<?> entityClass = getEntityClassFromRepository(Class.forName(repositoryClassInfo.name())); - if(entityClass != null && entityClass.isAnnotationPresent(TCKEntity.class)) { - log.info("This extension provides for the repository: " + repositoryClassInfo.name()); - log.info("Based on Entity with @TCKEntity annotation: " + entityClass.getCanonicalName()); - repositoryClassNames.add(repositoryClassInfo.name()); - return; - } - - // Second determine if we support the repository based on provider attribute - AnnotationMember providerMember = repositoryClassInfo.annotation(Repository.class).member("provider"); - String provider = providerMember.asString(); - if(Directory.PERSON_PROVIDER.equals(provider) || AddressBook.ADDRESS_PROVIDER.equals(provider)) { - log.info("This extension provides for the repository: " + repositoryClassInfo.name()); - log.info("Based on the Repository provider: " + provider); - repositoryClassNames.add(repositoryClassInfo.name()); - return; - } - - //Otherwise, do not support - log.info("This extension does not provides for the repository: " + repositoryClassInfo.name()); - } - - /** - * Register beans for repositories. - */ - @Synthesis - public void synthesis(Types types, SyntheticComponents synth) throws ClassNotFoundException { - for (String repoClassName : repositoryClassNames) { - @SuppressWarnings("unchecked") - Class<Object> repoClass = (Class<Object>) Class.forName(repoClassName); - SyntheticBeanBuilder<Object> builder = synth - .addBean(repoClass) - .name(repoClassName) - .type(types.ofClass(repoClassName)) - .scope(ApplicationScoped.class) - .withParam("impl", staticImplMap.get(repoClass)) - .createWith(BeanCreator.class); - - log.info("Registered " + repoClassName + " bean with " + builder); - } - } - - private Class<?> getEntityClassFromRepository(Class<?> repositoryInterface) { - for (Type interfaceType : repositoryInterface.getGenericInterfaces()) { - if (interfaceType instanceof ParameterizedType) { - ParameterizedType parameterizedType = (ParameterizedType) interfaceType; - if (parameterizedType.getRawType().getTypeName().startsWith(DataRepository.class.getPackageName())) { - Type typeParams[] = parameterizedType.getActualTypeArguments(); - if (typeParams.length == 2 && typeParams[0] instanceof Class) { - return (Class<?>) typeParams[0]; - } - } - } - } - - return null; - } -} diff --git a/tck/src/main/java/ee/jakarta/tck/data/web/cdi/ExtensionTests.java b/tck/src/main/java/ee/jakarta/tck/data/web/cdi/ExtensionTests.java index a2110497c..8e84313da 100644 --- a/tck/src/main/java/ee/jakarta/tck/data/web/cdi/ExtensionTests.java +++ b/tck/src/main/java/ee/jakarta/tck/data/web/cdi/ExtensionTests.java @@ -23,7 +23,6 @@ import org.jboss.arquillian.container.test.api.Deployment; import org.jboss.shrinkwrap.api.ShrinkWrap; -import org.jboss.shrinkwrap.api.spec.JavaArchive; import org.jboss.shrinkwrap.api.spec.WebArchive; import ee.jakarta.tck.data.common.cdi.AddressBook; @@ -34,8 +33,6 @@ import ee.jakarta.tck.data.framework.junit.anno.Assertion; import ee.jakarta.tck.data.framework.junit.anno.CDI; import ee.jakarta.tck.data.framework.junit.anno.Web; -import ee.jakarta.tck.data.web.cdi.provider.ExtensionImpl; -import jakarta.enterprise.inject.spi.Extension; import jakarta.inject.Inject; @Web @@ -44,15 +41,9 @@ public class ExtensionTests { @Deployment public static WebArchive createDeployment() { - JavaArchive provider = ShrinkWrap.create(JavaArchive.class) - .addPackage(ExtensionImpl.class.getPackage()) - .addAsServiceProvider(Extension.class, ExtensionImpl.class); - - return ShrinkWrap.create(WebArchive.class) .addPackage(ExtensionTests.class.getPackage()) - .addPackage(Person.class.getPackage()) - .addAsLibraries(provider); + .addPackage(Person.class.getPackage()); } diff --git a/tck/src/main/java/ee/jakarta/tck/data/web/cdi/provider/AddressRepositoryProducer.java b/tck/src/main/java/ee/jakarta/tck/data/web/cdi/provider/AddressRepositoryProducer.java deleted file mode 100644 index e631f1812..000000000 --- a/tck/src/main/java/ee/jakarta/tck/data/web/cdi/provider/AddressRepositoryProducer.java +++ /dev/null @@ -1,68 +0,0 @@ -/* - * Copyright (c) 2024 Contributors to the Eclipse Foundation - * - * 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 ee.jakarta.tck.data.web.cdi.provider; - -import java.util.Collections; -import java.util.Set; -import java.util.logging.Logger; - -import ee.jakarta.tck.data.common.cdi.AddressRepository; -import jakarta.enterprise.context.spi.CreationalContext; -import jakarta.enterprise.inject.spi.Bean; -import jakarta.enterprise.inject.spi.InjectionPoint; -import jakarta.enterprise.inject.spi.Producer; -import jakarta.enterprise.inject.spi.ProducerFactory; - -/** - * A CDI producer for the AddressRepository - * - * @param <R> The repository producer (i.e. this) - * @param <P> The type of the bean containing the producer - */ -public class AddressRepositoryProducer<R, P> implements Producer<AddressRepository> { - - private static final Logger log = Logger.getLogger(AddressRepositoryProducer.class.getCanonicalName()); - - /** - * Factory class for this repository producer. - */ - static class Factory<P> implements ProducerFactory<P> { - @Override - @SuppressWarnings({ "rawtypes", "unchecked" }) - public <R> Producer<R> createProducer(Bean<R> bean) { - return new AddressRepositoryProducer(); - } - } - - @Override - public void dispose(AddressRepository instance) { - log.info("Directory CDI extension has been disposed: " + instance); - } - - @Override - public Set<InjectionPoint> getInjectionPoints() { - return Collections.emptySet(); - } - - @Override - public AddressRepository produce(CreationalContext<AddressRepository> cc) { - AddressRepository instance = new AddressRepository(); - - log.info("Address CDI extension has been produced: " + instance); - - return instance; - } -} diff --git a/tck/src/main/java/ee/jakarta/tck/data/web/cdi/provider/DirectoryRepositoryProducer.java b/tck/src/main/java/ee/jakarta/tck/data/web/cdi/provider/DirectoryRepositoryProducer.java deleted file mode 100644 index 52d17a200..000000000 --- a/tck/src/main/java/ee/jakarta/tck/data/web/cdi/provider/DirectoryRepositoryProducer.java +++ /dev/null @@ -1,68 +0,0 @@ -/* - * Copyright (c) 2023 Contributors to the Eclipse Foundation - * - * 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 ee.jakarta.tck.data.web.cdi.provider; - -import java.util.Collections; -import java.util.Set; -import java.util.logging.Logger; - -import ee.jakarta.tck.data.common.cdi.DirectoryRepository; -import jakarta.enterprise.context.spi.CreationalContext; -import jakarta.enterprise.inject.spi.Bean; -import jakarta.enterprise.inject.spi.InjectionPoint; -import jakarta.enterprise.inject.spi.Producer; -import jakarta.enterprise.inject.spi.ProducerFactory; - -/** - * A CDI producer for the DirectoryRepository - * - * @param <R> The repository producer (i.e. this) - * @param <P> The type of the bean containing the producer - */ -public class DirectoryRepositoryProducer<R, P> implements Producer<DirectoryRepository> { - - private static final Logger log = Logger.getLogger(DirectoryRepositoryProducer.class.getCanonicalName()); - - /** - * Factory class for this repository producer. - */ - static class Factory<P> implements ProducerFactory<P> { - @Override - @SuppressWarnings({ "rawtypes", "unchecked" }) - public <R> Producer<R> createProducer(Bean<R> bean) { - return new DirectoryRepositoryProducer(); - } - } - - @Override - public void dispose(DirectoryRepository instance) { - log.info("Directory CDI extension has been disposed: " + instance); - } - - @Override - public Set<InjectionPoint> getInjectionPoints() { - return Collections.emptySet(); - } - - @Override - public DirectoryRepository produce(CreationalContext<DirectoryRepository> cc) { - DirectoryRepository instance = new DirectoryRepository(); - - log.info("Directory CDI extension has been produced: " + instance); - - return instance; - } -} diff --git a/tck/src/main/java/ee/jakarta/tck/data/web/cdi/provider/ExtensionImpl.java b/tck/src/main/java/ee/jakarta/tck/data/web/cdi/provider/ExtensionImpl.java deleted file mode 100644 index d08e183c0..000000000 --- a/tck/src/main/java/ee/jakarta/tck/data/web/cdi/provider/ExtensionImpl.java +++ /dev/null @@ -1,133 +0,0 @@ -/* - * Copyright (c) 2023, 2024 Contributors to the Eclipse Foundation - * - * 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 ee.jakarta.tck.data.web.cdi.provider; - -import java.lang.reflect.ParameterizedType; -import java.lang.reflect.Type; -import java.util.ArrayList; -import java.util.HashMap; -import java.util.HashSet; -import java.util.Map; -import java.util.logging.Logger; - -import ee.jakarta.tck.data.common.cdi.AddressBook; -import ee.jakarta.tck.data.common.cdi.Directory; -import ee.jakarta.tck.data.common.cdi.TCKEntity; -import jakarta.data.exceptions.MappingException; -import jakarta.data.repository.DataRepository; -import jakarta.data.repository.Repository; -import jakarta.enterprise.event.Observes; -import jakarta.enterprise.inject.spi.AfterBeanDiscovery; -import jakarta.enterprise.inject.spi.AfterTypeDiscovery; -import jakarta.enterprise.inject.spi.AnnotatedType; -import jakarta.enterprise.inject.spi.Bean; -import jakarta.enterprise.inject.spi.BeanAttributes; -import jakarta.enterprise.inject.spi.BeanManager; -import jakarta.enterprise.inject.spi.Extension; -import jakarta.enterprise.inject.spi.ProcessAnnotatedType; -import jakarta.enterprise.inject.spi.ProducerFactory; -import jakarta.enterprise.inject.spi.WithAnnotations; - -/** - * A Jakarta Data provider extension that produces the Directory and Address repositories - * class. This provider is only for testing and is not a real implementation. - * This extension verifies how a Jakarta Data provider is registered as a CDI - * extension. - */ -public class ExtensionImpl implements Extension { - - private static final Logger log = Logger.getLogger(ExtensionImpl.class.getCanonicalName()); - - // Static relation between Repository and Producer - private static final Map<Class<?>, ProducerFactory<?>> staticProducerMap = new HashMap<>(); - static { - staticProducerMap.put(AddressBook.class, new AddressRepositoryProducer.Factory<>() ); - staticProducerMap.put(Directory.class, new DirectoryRepositoryProducer.Factory<>()); - } - - private final ArrayList<Bean<?>> repositoryBeans = new ArrayList<>(); - - private final HashSet<AnnotatedType<?>> repositoryTypes = new HashSet<>(); - - public <T> void annotatedRepository(@Observes @WithAnnotations(Repository.class) ProcessAnnotatedType<T> event) { - AnnotatedType<T> type = event.getAnnotatedType(); - Class<?> repositoryClass = type.getJavaClass(); - - // First determine if we support the repository based on entity - Class<?> entityClass = getEntityClassFromRepository(repositoryClass); - if (entityClass != null && entityClass.isAnnotationPresent(TCKEntity.class)) { - log.info("This extension provides for the repository: " + repositoryClass.getCanonicalName()); - log.info("Based on Entity with @TCKEntity annotation: " + entityClass.getCanonicalName()); - repositoryTypes.add(type); - return; - } - - // Second determine if we support the repository based on provider attribute - String provider = type.getAnnotation(Repository.class).provider(); - if (Directory.PERSON_PROVIDER.equals(provider) || AddressBook.ADDRESS_PROVIDER.equals(provider)) { - log.info("This extension provides for the repository: " + repositoryClass.getCanonicalName()); - log.info("Based on the Repository provider: " + provider); - repositoryTypes.add(type); - return; - } - - // Otherwise, do not support - log.info("This extension does not provides for the repository: " + repositoryClass.getCanonicalName()); - - } - - @SuppressWarnings({ "rawtypes", "unchecked" }) - public void afterTypeDiscovery(@Observes AfterTypeDiscovery event, BeanManager beanMgr) { - for (AnnotatedType<?> repositoryType : repositoryTypes) { - - Class<?> repositoryInterface = repositoryType.getJavaClass(); - ProducerFactory repositoryProducer = staticProducerMap.get(repositoryInterface); - - if(repositoryProducer != null) { - BeanAttributes<?> attrs = beanMgr.createBeanAttributes(repositoryType); - Bean<?> bean = beanMgr.createBean(attrs, repositoryInterface, repositoryProducer); - repositoryBeans.add(bean); - continue; - } - - String message = "The Jakarta Data provider cannot provide the " + repositoryType.getJavaClass().getName() - + " repository because there is no producer that supports this repository"; - throw new MappingException(message); - } - } - - public void afterBeanDiscovery(@Observes AfterBeanDiscovery event, BeanManager beanMgr) { - for (Bean<?> bean : repositoryBeans) { - event.addBean(bean); - } - } - - private Class<?> getEntityClassFromRepository(Class<?> repositoryInterface) { - for (Type interfaceType : repositoryInterface.getGenericInterfaces()) { - if (interfaceType instanceof ParameterizedType) { - ParameterizedType parameterizedType = (ParameterizedType) interfaceType; - if (parameterizedType.getRawType().getTypeName().startsWith(DataRepository.class.getPackageName())) { - Type typeParams[] = parameterizedType.getActualTypeArguments(); - if (typeParams.length == 2 && typeParams[0] instanceof Class) { - return (Class<?>) typeParams[0]; - } - } - } - } - - return null; - } -}