From 836e6bf723eb0074f393edabff4eafb1ca432b41 Mon Sep 17 00:00:00 2001 From: Dmitry Aleksandrov Date: Mon, 13 Nov 2023 22:19:29 +0200 Subject: [PATCH] Add Bean support Signed-off-by: Dmitry Aleksandrov --- .../testing/common/CommonAddBean.java | 53 ++++++++++++ .../testing/common/CommonAddBeans.java | 36 +++++++++ ...Extension.java => CommonCdiExtension.java} | 8 +- ...tensions.java => CommonCdiExtensions.java} | 8 +- .../testing/common/package-info.java | 20 +++++ .../microprofile/testing/jaxrs/AddJaxRs.java | 20 ++++- .../testing/jaxrs/package-info.java | 20 +++++ .../jaxrs/src/main/java/module-info.java | 1 + .../testing/junit5/HelidonJunitExtension.java | 81 +++++++++---------- 9 files changed, 195 insertions(+), 52 deletions(-) create mode 100644 microprofile/testing/common/src/main/java/io/helidon/microprofile/testing/common/CommonAddBean.java create mode 100644 microprofile/testing/common/src/main/java/io/helidon/microprofile/testing/common/CommonAddBeans.java rename microprofile/testing/common/src/main/java/io/helidon/microprofile/testing/common/{CdiExtension.java => CommonCdiExtension.java} (87%) rename microprofile/testing/common/src/main/java/io/helidon/microprofile/testing/common/{CdiExtensions.java => CommonCdiExtensions.java} (86%) create mode 100644 microprofile/testing/common/src/main/java/io/helidon/microprofile/testing/common/package-info.java create mode 100644 microprofile/testing/jaxrs/src/main/java/io/helidon/microprofile/testing/jaxrs/package-info.java diff --git a/microprofile/testing/common/src/main/java/io/helidon/microprofile/testing/common/CommonAddBean.java b/microprofile/testing/common/src/main/java/io/helidon/microprofile/testing/common/CommonAddBean.java new file mode 100644 index 00000000000..d0100d52c1d --- /dev/null +++ b/microprofile/testing/common/src/main/java/io/helidon/microprofile/testing/common/CommonAddBean.java @@ -0,0 +1,53 @@ +/* + * Copyright (c) 2023 Oracle and/or its affiliates. + * + * 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 io.helidon.microprofile.testing.common; + +import jakarta.enterprise.context.ApplicationScoped; + +import java.lang.annotation.Annotation; +import java.lang.annotation.ElementType; +import java.lang.annotation.Repeatable; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +/** + * Add a bean. + * This is intended for test sources where we do not want to add {@code beans.xml} as this would add + * all test classes as beans. + * The bean will be added by default with {@link ApplicationScoped}. + * The class will be instantiated using CDI and will be available for injection into test classes and other beans. + * This annotation can be repeated. + */ +@Retention(RetentionPolicy.RUNTIME) +@Target({ElementType.TYPE, ElementType.METHOD}) +@Repeatable(CommonAddBeans.class) +public @interface CommonAddBean { + /** + * Class of the bean. + * @return the class of a bean + */ + Class value(); + + /** + * Scope of the bean. + * Only {@link jakarta.inject.Singleton}, {@link ApplicationScoped} + * and {@link jakarta.enterprise.context.RequestScoped} scopes are supported. + * + * @return scope of the bean + */ + Class scope() default ApplicationScoped.class; +} diff --git a/microprofile/testing/common/src/main/java/io/helidon/microprofile/testing/common/CommonAddBeans.java b/microprofile/testing/common/src/main/java/io/helidon/microprofile/testing/common/CommonAddBeans.java new file mode 100644 index 00000000000..e413f0628a6 --- /dev/null +++ b/microprofile/testing/common/src/main/java/io/helidon/microprofile/testing/common/CommonAddBeans.java @@ -0,0 +1,36 @@ +/* + * Copyright (c) 2023 Oracle and/or its affiliates. + * + * 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 io.helidon.microprofile.testing.common; + +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +/** + * A repeatable container for {@link CommonAddBean}. + * No need to use this annotation, just repeat {@link CommonAddBean} annotation + * on test class. + */ +@Retention(RetentionPolicy.RUNTIME) +@Target({ElementType.TYPE}) +public @interface CommonAddBeans { + /** + * Beans to be added. + * @return add bean annotations + */ + CommonAddBean[] value(); +} diff --git a/microprofile/testing/common/src/main/java/io/helidon/microprofile/testing/common/CdiExtension.java b/microprofile/testing/common/src/main/java/io/helidon/microprofile/testing/common/CommonCdiExtension.java similarity index 87% rename from microprofile/testing/common/src/main/java/io/helidon/microprofile/testing/common/CdiExtension.java rename to microprofile/testing/common/src/main/java/io/helidon/microprofile/testing/common/CommonCdiExtension.java index 9461915f14c..71b641690f3 100644 --- a/microprofile/testing/common/src/main/java/io/helidon/microprofile/testing/common/CdiExtension.java +++ b/microprofile/testing/common/src/main/java/io/helidon/microprofile/testing/common/CommonCdiExtension.java @@ -16,6 +16,7 @@ package io.helidon.microprofile.testing.common; import java.lang.annotation.ElementType; +import java.lang.annotation.Inherited; import java.lang.annotation.Repeatable; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; @@ -28,9 +29,10 @@ * Common CDI Extension. */ @Retention(RetentionPolicy.RUNTIME) -@Target({ElementType.TYPE, ElementType.METHOD}) -@Repeatable(CdiExtensions.class) -public @interface CdiExtension { +@Target({ElementType.TYPE}) +@Repeatable(CommonCdiExtensions.class) +@Inherited +public @interface CommonCdiExtension { /** * CDI Extension. diff --git a/microprofile/testing/common/src/main/java/io/helidon/microprofile/testing/common/CdiExtensions.java b/microprofile/testing/common/src/main/java/io/helidon/microprofile/testing/common/CommonCdiExtensions.java similarity index 86% rename from microprofile/testing/common/src/main/java/io/helidon/microprofile/testing/common/CdiExtensions.java rename to microprofile/testing/common/src/main/java/io/helidon/microprofile/testing/common/CommonCdiExtensions.java index 87709219946..28890f40265 100644 --- a/microprofile/testing/common/src/main/java/io/helidon/microprofile/testing/common/CdiExtensions.java +++ b/microprofile/testing/common/src/main/java/io/helidon/microprofile/testing/common/CommonCdiExtensions.java @@ -16,6 +16,7 @@ package io.helidon.microprofile.testing.common; import java.lang.annotation.ElementType; +import java.lang.annotation.Inherited; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; @@ -25,13 +26,14 @@ * Common CDI Extensions for testing. */ @Retention(RetentionPolicy.RUNTIME) -@Target({ElementType.TYPE, ElementType.METHOD}) -public @interface CdiExtensions { +@Target({ElementType.TYPE}) +@Inherited +public @interface CommonCdiExtensions { /** * Return CDI Extension. * * @return CDIExtension[] */ - CdiExtension[] value(); + CommonCdiExtension[] value(); } diff --git a/microprofile/testing/common/src/main/java/io/helidon/microprofile/testing/common/package-info.java b/microprofile/testing/common/src/main/java/io/helidon/microprofile/testing/common/package-info.java new file mode 100644 index 00000000000..77f71b19fbe --- /dev/null +++ b/microprofile/testing/common/src/main/java/io/helidon/microprofile/testing/common/package-info.java @@ -0,0 +1,20 @@ +/* + * Copyright (c) 2023 Oracle and/or its affiliates. + * + * 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. + */ + +/** + * Common Testing Extensions. + */ +package io.helidon.microprofile.testing.common; diff --git a/microprofile/testing/jaxrs/src/main/java/io/helidon/microprofile/testing/jaxrs/AddJaxRs.java b/microprofile/testing/jaxrs/src/main/java/io/helidon/microprofile/testing/jaxrs/AddJaxRs.java index 76a57956102..a0f99f3d3d2 100644 --- a/microprofile/testing/jaxrs/src/main/java/io/helidon/microprofile/testing/jaxrs/AddJaxRs.java +++ b/microprofile/testing/jaxrs/src/main/java/io/helidon/microprofile/testing/jaxrs/AddJaxRs.java @@ -16,17 +16,29 @@ package io.helidon.microprofile.testing.jaxrs; +import java.lang.annotation.ElementType; +import java.lang.annotation.Inherited; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + import io.helidon.microprofile.server.JaxRsCdiExtension; import io.helidon.microprofile.server.ServerCdiExtension; -import io.helidon.microprofile.testing.common.CdiExtension; +import io.helidon.microprofile.testing.common.CommonAddBean; +import io.helidon.microprofile.testing.common.CommonCdiExtension; import org.glassfish.jersey.ext.cdi1x.internal.CdiComponentProvider; /** * JAX_RS Testing annotation. */ -@CdiExtension(ServerCdiExtension.class) -@CdiExtension(JaxRsCdiExtension.class) -@CdiExtension(CdiComponentProvider.class) +@Retention(RetentionPolicy.RUNTIME) +@Target({ElementType.TYPE, ElementType.METHOD}) +@Inherited +@CommonCdiExtension(ServerCdiExtension.class) +@CommonCdiExtension(JaxRsCdiExtension.class) +@CommonCdiExtension(CdiComponentProvider.class) +@CommonCdiExtension(org.glassfish.jersey.ext.cdi1x.internal.ProcessAllAnnotatedTypes.class) +@CommonAddBean(org.glassfish.jersey.weld.se.WeldRequestScope.class) public @interface AddJaxRs { } diff --git a/microprofile/testing/jaxrs/src/main/java/io/helidon/microprofile/testing/jaxrs/package-info.java b/microprofile/testing/jaxrs/src/main/java/io/helidon/microprofile/testing/jaxrs/package-info.java new file mode 100644 index 00000000000..3a80e8e726e --- /dev/null +++ b/microprofile/testing/jaxrs/src/main/java/io/helidon/microprofile/testing/jaxrs/package-info.java @@ -0,0 +1,20 @@ +/* + * Copyright (c) 2023 Oracle and/or its affiliates. + * + * 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. + */ + +/** + * JAX-RS Extension for Testing. + */ +package io.helidon.microprofile.testing.jaxrs; diff --git a/microprofile/testing/jaxrs/src/main/java/module-info.java b/microprofile/testing/jaxrs/src/main/java/module-info.java index cff2052441e..b4dadb03e5b 100644 --- a/microprofile/testing/jaxrs/src/main/java/module-info.java +++ b/microprofile/testing/jaxrs/src/main/java/module-info.java @@ -30,6 +30,7 @@ requires transitive jakarta.cdi; requires transitive jakarta.ws.rs; + requires jersey.weld2.se; exports io.helidon.microprofile.testing.jaxrs; diff --git a/microprofile/testing/junit5/src/main/java/io/helidon/microprofile/testing/junit5/HelidonJunitExtension.java b/microprofile/testing/junit5/src/main/java/io/helidon/microprofile/testing/junit5/HelidonJunitExtension.java index a271dbb5dc0..47d89503a32 100644 --- a/microprofile/testing/junit5/src/main/java/io/helidon/microprofile/testing/junit5/HelidonJunitExtension.java +++ b/microprofile/testing/junit5/src/main/java/io/helidon/microprofile/testing/junit5/HelidonJunitExtension.java @@ -16,7 +16,6 @@ package io.helidon.microprofile.testing.junit5; -import java.io.Serial; import java.lang.annotation.Annotation; import java.lang.reflect.AnnotatedElement; import java.lang.reflect.Array; @@ -31,10 +30,14 @@ import java.util.List; import java.util.Map; import java.util.Set; +import java.util.stream.Collectors; import io.helidon.config.mp.MpConfigSources; import io.helidon.config.yaml.mp.YamlMpConfigSource; -import io.helidon.microprofile.testing.common.CdiExtension; +import io.helidon.microprofile.testing.common.CommonAddBean; +import io.helidon.microprofile.testing.common.CommonAddBeans; +import io.helidon.microprofile.testing.common.CommonCdiExtension; +import io.helidon.microprofile.testing.common.CommonCdiExtensions; import jakarta.enterprise.context.ApplicationScoped; import jakarta.enterprise.context.Dependent; @@ -49,7 +52,6 @@ import jakarta.enterprise.inject.spi.InjectionPoint; import jakarta.enterprise.inject.spi.ProcessInjectionPoint; import jakarta.enterprise.inject.spi.configurator.AnnotatedTypeConfigurator; -import jakarta.enterprise.util.AnnotationLiteral; import jakarta.inject.Inject; import jakarta.inject.Singleton; import jakarta.ws.rs.client.Client; @@ -140,13 +142,6 @@ public void beforeAll(ExtensionContext context) { } validatePerClass(); - // add beans when using JaxRS -// AddJaxRs addJaxRsAnnotation = testClass.getAnnotation(AddJaxRs.class); -// if (addJaxRsAnnotation != null){ -// classLevelExtensions.add(AddProcessAnnotatedTypesLiteral.INSTANCE); -// classLevelBeans.add(AddWeldRequestScopeLiteral.INSTANCE); -// } - configure(classLevelConfigMeta); if (!classLevelConfigMeta.useExisting) { @@ -158,14 +153,33 @@ public void beforeAll(ExtensionContext context) { } @SuppressWarnings("unchecked") - private Class[] getFeatureExtensions(Class testClass) { + private List> getFeatureExtensions(Class testClass) { return Arrays.stream(testClass.getDeclaredAnnotations()) - .flatMap(a -> Arrays.stream(a.getClass().getDeclaredAnnotations())) - .filter(a -> a.annotationType() == CdiExtension.class) - .map(CdiExtension.class::cast) - .map(CdiExtension::value) - .toList() - .toArray(new Class[0]); + .flatMap(a -> Arrays.stream(a.annotationType().getDeclaredAnnotations())) + .filter(a -> a instanceof CommonCdiExtensions) + .map(CommonCdiExtensions.class::cast) + .flatMap(e -> Arrays.stream(e.value())) + .map(CommonCdiExtension::value) + .collect(Collectors.toList()); + } + + private List> getFeatureBeans(Class testClass) { + + ArrayList> result = new ArrayList<>(Arrays.stream(testClass.getDeclaredAnnotations()) + .flatMap(a -> Arrays.stream(a.annotationType().getDeclaredAnnotations())) + .filter(a -> a instanceof CommonAddBean) + .map(CommonAddBean.class::cast) + .map(CommonAddBean::value) + .collect(Collectors.toList())); + + result.addAll(Arrays.stream(testClass.getDeclaredAnnotations()) + .flatMap(a -> Arrays.stream(a.annotationType().getDeclaredAnnotations())) + .filter(a -> a instanceof CommonAddBeans) + .map(CommonAddBeans.class::cast) + .flatMap(e -> Arrays.stream(e.value())) + .map(CommonAddBean::value) + .collect(Collectors.toList())); + return result; } private T[] getAnnotations(Class testClass, Class annotClass) { @@ -254,29 +268,6 @@ private void validatePerClass() { } } } - -// AddJaxRs addJaxRsAnnotation = testClass.getAnnotation(AddJaxRs.class); -// if (addJaxRsAnnotation != null){ -// if (testClass.getAnnotation(DisableDiscovery.class) == null){ -// throw new RuntimeException("@AddJaxRs annotation should be used only with @DisableDiscovery annotation."); -// } -// -// List> beans = classLevelBeans.stream().map(AddBean::value).toList(); -// if (beans.contains(org.glassfish.jersey.weld.se.WeldRequestScope.class)) { -// throw new RuntimeException("@AddJaxRs annotation already includes `WeldRequestScope` bean"); -// } -// -// List> extensions = classLevelExtensions.stream().map(AddExtension::value).toList(); -// if (!extensions.isEmpty()) { -// if (extensions.contains(org.glassfish.jersey.ext.cdi1x.internal.ProcessAllAnnotatedTypes.class)) { -// throw new RuntimeException("@AddJaxRs annotation already includes `ProcessAllAnnotatedTypes` extension"); -// } -// if (extensions.contains(CdiExtension.class)) { -// throw new RuntimeException("@AddJaxRs annotation already includes `CDI` extension"); -// } -// } -// -// } } private boolean hasHelidonTestAnnotation(AnnotatedElement element) { @@ -370,7 +361,7 @@ private void startContainer(List beanAnnotations, initializer.disableDiscovery(); } - initializer.addExtensions(new AddBeansExtension(testClass, beanAnnotations)); + initializer.addExtensions(new AddBeansExtension(testClass, beanAnnotations, getFeatureBeans(testClass))); for (AddExtension addExtension : extensionAnnotations) { Class extensionClass = addExtension.value(); @@ -382,6 +373,8 @@ private void startContainer(List beanAnnotations, } } + getFeatureExtensions(testClass).forEach(initializer::addExtensions); + container = initializer.initialize(); } @@ -523,12 +516,14 @@ private void callAfterStop() { private static class AddBeansExtension implements Extension { private final Class testClass; private final List addBeans; + private final List> featureBeans; private final HashMap socketAnnotations = new HashMap<>(); - private AddBeansExtension(Class testClass, List addBeans) { + private AddBeansExtension(Class testClass, List addBeans, List> featureBeans) { this.testClass = testClass; this.addBeans = addBeans; + this.featureBeans = featureBeans; } @@ -603,6 +598,8 @@ void registerAddedBeans(@Observes BeforeBeanDiscovery event) { configurator.add(scope); } } + + featureBeans.forEach(e -> event.addAnnotatedType(e, e.getName())); } private boolean hasBda(Class value) {