OWB-1286 first JUnit 5 integration

git-svn-id: https://svn.apache.org/repos/asf/openwebbeans/trunk@1858345 13f79535-47bb-0310-9956-ffa450edef68
diff --git a/pom.xml b/pom.xml
index 18d02ac..051fed1 100644
--- a/pom.xml
+++ b/pom.xml
@@ -379,7 +379,7 @@
             <plugin>
                 <groupId>org.apache.maven.plugins</groupId>
                 <artifactId>maven-surefire-plugin</artifactId>
-                <version>2.19.1</version>
+                <version>3.0.0-M3</version>
                 <configuration>
                     <includes>
                         <include>**/*Test.java</include>
@@ -557,6 +557,7 @@
         <module>webbeans-maven</module>
         <module>webbeans-gradle</module>
         <module>webbeans-se</module>
+        <module>webbeans-junit5</module>
     </modules>
 
     <dependencyManagement>
diff --git a/webbeans-junit5/pom.xml b/webbeans-junit5/pom.xml
new file mode 100644
index 0000000..685f231
--- /dev/null
+++ b/webbeans-junit5/pom.xml
@@ -0,0 +1,108 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+    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.
+-->
+<project xmlns="http://maven.apache.org/POM/4.0.0"
+         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+    <modelVersion>4.0.0</modelVersion>
+
+    <parent>
+        <groupId>org.apache.openwebbeans</groupId>
+        <artifactId>openwebbeans</artifactId>
+        <version>2.0.11-SNAPSHOT</version>
+    </parent>
+
+    <artifactId>openwebbeans-junit5</artifactId>
+    <name>OpenWebBeans JUnit5</name>
+    <description>
+        Apache OpenWebBeans JUnit 5 integration
+    </description>
+
+    <dependencies>
+        <dependency>
+            <groupId>org.apache.geronimo.specs</groupId>
+            <artifactId>geronimo-annotation_1.3_spec</artifactId>
+            <scope>provided</scope>
+        </dependency>
+        <dependency>
+            <groupId>org.apache.geronimo.specs</groupId>
+            <artifactId>geronimo-jcdi_2.0_spec</artifactId>
+            <scope>provided</scope>
+        </dependency>
+        <dependency>
+            <groupId>org.apache.geronimo.specs</groupId>
+            <artifactId>geronimo-atinject_1.0_spec</artifactId>
+            <scope>provided</scope>
+        </dependency>
+        <dependency>
+            <groupId>org.apache.geronimo.specs</groupId>
+            <artifactId>geronimo-interceptor_1.2_spec</artifactId>
+            <scope>provided</scope>
+        </dependency>
+
+        <dependency>
+            <groupId>org.apache.openwebbeans</groupId>
+            <artifactId>openwebbeans-se</artifactId>
+            <version>${project.version}</version>
+        </dependency>
+        <dependency>
+            <groupId>org.junit.jupiter</groupId>
+            <artifactId>junit-jupiter</artifactId>
+            <version>5.4.2</version>
+            <scope>provided</scope>
+        </dependency>
+    </dependencies>
+
+    <build>
+        <plugins>
+            <plugin>
+                <groupId>org.apache.maven.plugins</groupId>
+                <artifactId>maven-surefire-plugin</artifactId>
+                <executions>
+                    <execution>
+                        <id>default-test</id>
+                        <configuration>
+                            <skip>true</skip>
+                        </configuration>
+                    </execution>
+                    <execution>
+                        <id>perclass</id>
+                        <phase>test</phase>
+                        <goals>
+                            <goal>test</goal>
+                        </goals>
+                        <configuration>
+                            <includes>**/perclass/*</includes>
+                        </configuration>
+                    </execution>
+                    <execution>
+                        <id>reusable</id>
+                        <phase>test</phase>
+                        <goals>
+                            <goal>test</goal>
+                        </goals>
+                        <configuration>
+                            <includes>**/reusable/*</includes>
+                        </configuration>
+                    </execution>
+                </executions>
+            </plugin>
+        </plugins>
+    </build>
+</project>
diff --git a/webbeans-junit5/src/main/java/org/apache/openwebbeans/junit5/Cdi.java b/webbeans-junit5/src/main/java/org/apache/openwebbeans/junit5/Cdi.java
new file mode 100644
index 0000000..f6c07a8
--- /dev/null
+++ b/webbeans-junit5/src/main/java/org/apache/openwebbeans/junit5/Cdi.java
@@ -0,0 +1,102 @@
+/*
+ * 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.openwebbeans.junit5;
+
+import org.apache.openwebbeans.junit5.internal.CdiExtension;
+import org.junit.jupiter.api.extension.ExtendWith;
+
+import java.io.Closeable;
+import java.lang.annotation.Annotation;
+import java.lang.annotation.Retention;
+import java.lang.annotation.Target;
+import java.util.function.Supplier;
+
+import static java.lang.annotation.ElementType.TYPE;
+import static java.lang.annotation.RetentionPolicy.RUNTIME;
+
+/**
+ * Activates CDI based on SE API for the decorated test.
+ *
+ * IMPORTANT: this is not thread safe - yet - so ensure to use a single fork in surefire/gradle/....
+ */
+@Target(TYPE)
+@Retention(RUNTIME)
+@ExtendWith(CdiExtension.class)
+public @interface Cdi
+{
+    /**
+     * @return classes to deploy.
+     */
+    Class<?>[] classes() default {};
+
+    /**
+     * @return decorators to activate.
+     */
+    Class<?>[] decorators() default {};
+
+    /**
+     * @return interceptors to activate.
+     */
+    Class<?>[] interceptors() default {};
+
+    /**
+     * @return alternatives to activate.
+     */
+    Class<?>[] alternatives() default {};
+
+    /**
+     * @return stereotypes to activate.
+     */
+    Class<? extends Annotation>[] alternativeStereotypes() default {};
+
+    /**
+     * @return packages to deploy.
+     */
+    Class<?>[] packages() default {};
+
+    /**
+     * @return packages to deploy recursively.
+     */
+    Class<?>[] recursivePackages() default {};
+
+    /**
+     * @return if the automatic scanning must be disabled.
+     */
+    boolean disableDiscovery() default false;
+
+    /**
+     * @return an array of callback to call before the container starts.
+     */
+    Class<? extends OnStart>[] onStarts() default {};
+
+    /**
+     * TIP: it is recommended to alias the configuration when this is true to avoid to have a not unified configuration.
+     * IMPORTANT: this is not thread safe so ensure to use a single fork when using it.
+     *
+     * @return true if the underlying container must stay up until the end of the tests.
+     */
+    boolean reusable() default false;
+
+    /**
+     * Will be execute before the container starts and can return a closeable called after the container stops.
+     */
+    interface OnStart extends Supplier<Closeable>
+    {
+    }
+}
diff --git a/webbeans-junit5/src/main/java/org/apache/openwebbeans/junit5/internal/CdiExtension.java b/webbeans-junit5/src/main/java/org/apache/openwebbeans/junit5/internal/CdiExtension.java
new file mode 100644
index 0000000..1c97389
--- /dev/null
+++ b/webbeans-junit5/src/main/java/org/apache/openwebbeans/junit5/internal/CdiExtension.java
@@ -0,0 +1,169 @@
+/*
+ * 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.openwebbeans.junit5.internal;
+
+import org.apache.openwebbeans.junit5.Cdi;
+import org.junit.jupiter.api.extension.AfterAllCallback;
+import org.junit.jupiter.api.extension.AfterEachCallback;
+import org.junit.jupiter.api.extension.BeforeAllCallback;
+import org.junit.jupiter.api.extension.BeforeEachCallback;
+import org.junit.jupiter.api.extension.ExtensionContext;
+import org.junit.platform.commons.util.AnnotationUtils;
+
+import javax.enterprise.context.spi.CreationalContext;
+import javax.enterprise.inject.se.SeContainer;
+import javax.enterprise.inject.se.SeContainerInitializer;
+import javax.enterprise.inject.spi.AnnotatedType;
+import javax.enterprise.inject.spi.BeanManager;
+import javax.enterprise.inject.spi.InjectionTarget;
+import java.io.Closeable;
+import java.io.IOException;
+import java.lang.reflect.InvocationTargetException;
+import java.util.Objects;
+import java.util.function.Supplier;
+import java.util.stream.Stream;
+
+// todo: enhance the setup to be thread safe? see Meecrowave ClassLoaderLock class and friends
+public class CdiExtension implements BeforeAllCallback, AfterAllCallback, BeforeEachCallback, AfterEachCallback
+{
+    private static SeContainer reusableContainer;
+
+    private SeContainer container;
+    private CreationalContext<Object> creationalContext;
+    private Closeable[] onStop;
+
+    @Override
+    public void beforeAll(final ExtensionContext extensionContext)
+    {
+        final Cdi config = AnnotationUtils.findAnnotation(extensionContext.getElement(), Cdi.class).orElse(null);
+        if (config == null)
+        {
+            return;
+        }
+
+        final boolean reusable = config.reusable();
+        if (reusable && reusableContainer != null)
+        {
+            return;
+        }
+        if (!reusable && reusableContainer != null)
+        {
+            throw new IllegalStateException(
+                    "You can't mix @Cdi(reusable=true) and @Cdi(reusable=false) in the same suite");
+        }
+
+        final SeContainerInitializer initializer = SeContainerInitializer.newInstance();
+        if (config.disableDiscovery())
+        {
+            initializer.disableDiscovery();
+        }
+        initializer.setClassLoader(Thread.currentThread().getContextClassLoader());
+        initializer.addBeanClasses(config.classes());
+        initializer.enableDecorators(config.decorators());
+        initializer.enableInterceptors(config.interceptors());
+        initializer.selectAlternatives(config.alternatives());
+        initializer.selectAlternativeStereotypes(config.alternativeStereotypes());
+        initializer.addPackages(
+                Stream.of(config.packages()).map(Class::getPackage).toArray(Package[]::new));
+        initializer.addPackages(true,
+                Stream.of(config.recursivePackages()).map(Class::getPackage).toArray(Package[]::new));
+        onStop = Stream.of(config.onStarts())
+                .map(it ->
+                {
+                    try
+                    {
+                        return it.getConstructor().newInstance();
+                    }
+                    catch (final InstantiationException | IllegalAccessException | NoSuchMethodException e)
+                    {
+                        throw new IllegalStateException(e);
+                    }
+                    catch (final InvocationTargetException e)
+                    {
+                        throw new IllegalStateException(e.getTargetException());
+                    }
+                })
+                .peek(Supplier::get)
+                .filter(Objects::nonNull)
+                .toArray(Closeable[]::new);
+        if (reusable)
+        {
+            reusableContainer = initializer.initialize();
+            Runtime.getRuntime().addShutdownHook(new Thread(
+                () -> doClose(reusableContainer), getClass().getName() + "-shutdown"));
+        }
+        else
+        {
+            container = initializer.initialize();
+        }
+    }
+
+    @Override
+    public void afterAll(final ExtensionContext extensionContext)
+    {
+        if (container != null)
+        {
+            doClose(container);
+            container = null;
+        }
+    }
+
+    @Override
+    public void beforeEach(final ExtensionContext extensionContext)
+    {
+        if (container == null && reusableContainer == null)
+        {
+            return;
+        }
+        extensionContext.getTestInstance().ifPresent(instance ->
+        {
+            final BeanManager manager = (container == null ? reusableContainer : container).getBeanManager();
+            final AnnotatedType<?> annotatedType = manager.createAnnotatedType(instance.getClass());
+            final InjectionTarget injectionTarget = manager.createInjectionTarget(annotatedType);
+            creationalContext = manager.createCreationalContext(null);
+            injectionTarget.inject(instance, creationalContext);
+        });
+    }
+
+    @Override
+    public void afterEach(final ExtensionContext extensionContext)
+    {
+        if (creationalContext != null)
+        {
+            creationalContext.release();
+            creationalContext = null;
+        }
+    }
+
+    private void doClose(final SeContainer container)
+    {
+        container.close();
+        Stream.of(onStop).forEach(it ->
+        {
+            try
+            {
+                it.close();
+            }
+            catch (final IOException e)
+            {
+                throw new IllegalStateException(e);
+            }
+        });
+    }
+}
diff --git a/webbeans-junit5/src/main/resources/META-INF/beans.xml b/webbeans-junit5/src/main/resources/META-INF/beans.xml
new file mode 100644
index 0000000..fd08856
--- /dev/null
+++ b/webbeans-junit5/src/main/resources/META-INF/beans.xml
@@ -0,0 +1,20 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+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.
+-->
+<beans version="2.0" bean-discovery-mode="none" />
diff --git a/webbeans-junit5/src/test/java/org/apache/openwebbeans/junit5/bean/MyService.java b/webbeans-junit5/src/test/java/org/apache/openwebbeans/junit5/bean/MyService.java
new file mode 100644
index 0000000..2fc35a1
--- /dev/null
+++ b/webbeans-junit5/src/test/java/org/apache/openwebbeans/junit5/bean/MyService.java
@@ -0,0 +1,28 @@
+/*
+ * 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.openwebbeans.junit5.bean;
+
+import javax.enterprise.context.ApplicationScoped;
+
+@ApplicationScoped
+public class MyService {
+    public String ok() {
+        return "ok";
+    }
+}
diff --git a/webbeans-junit5/src/test/java/org/apache/openwebbeans/junit5/perclass/CdiTest.java b/webbeans-junit5/src/test/java/org/apache/openwebbeans/junit5/perclass/CdiTest.java
new file mode 100644
index 0000000..07e2a0c
--- /dev/null
+++ b/webbeans-junit5/src/test/java/org/apache/openwebbeans/junit5/perclass/CdiTest.java
@@ -0,0 +1,51 @@
+/*
+ * 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.openwebbeans.junit5.perclass;
+
+import org.apache.openwebbeans.junit5.Cdi;
+import org.apache.openwebbeans.junit5.bean.MyService;
+import org.junit.jupiter.api.Test;
+
+import javax.inject.Inject;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+
+@Cdi(disableDiscovery = true, classes = MyService.class)
+class CdiTest
+{
+    @Inject
+    private MyService service;
+
+    @Test
+    void test1()
+    {
+        doTest();
+    }
+
+    @Test
+    void test2()
+    {
+        doTest();
+    }
+
+    private void doTest()
+    {
+        assertEquals("ok", service.ok());
+    }
+}
diff --git a/webbeans-junit5/src/test/java/org/apache/openwebbeans/junit5/reusable/Base.java b/webbeans-junit5/src/test/java/org/apache/openwebbeans/junit5/reusable/Base.java
new file mode 100644
index 0000000..1f2c384
--- /dev/null
+++ b/webbeans-junit5/src/test/java/org/apache/openwebbeans/junit5/reusable/Base.java
@@ -0,0 +1,59 @@
+/*
+ * 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.openwebbeans.junit5.reusable;
+
+import org.apache.openwebbeans.junit5.bean.MyService;
+import org.apache.webbeans.config.WebBeansContext;
+import org.junit.jupiter.api.Test;
+
+import javax.inject.Inject;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+
+abstract class Base {
+    private static WebBeansContext current;
+
+    @Inject
+    private MyService service;
+
+    @Test
+    void test1()
+    {
+        doTest();
+    }
+
+    @Test
+    void test2()
+    {
+        doTest();
+    }
+
+    private void doTest()
+    {
+        if (current == null)
+        {
+            current = WebBeansContext.currentInstance();
+        }
+        else
+        {
+            assertEquals(current, WebBeansContext.currentInstance());
+        }
+        assertEquals("ok", service.ok());
+    }
+}
diff --git a/webbeans-junit5/src/test/java/org/apache/openwebbeans/junit5/reusable/Cdi1Test.java b/webbeans-junit5/src/test/java/org/apache/openwebbeans/junit5/reusable/Cdi1Test.java
new file mode 100644
index 0000000..c57de40
--- /dev/null
+++ b/webbeans-junit5/src/test/java/org/apache/openwebbeans/junit5/reusable/Cdi1Test.java
@@ -0,0 +1,23 @@
+/*
+ * 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.openwebbeans.junit5.reusable;
+
+@Config
+class Cdi1Test extends Base {
+}
diff --git a/webbeans-junit5/src/test/java/org/apache/openwebbeans/junit5/reusable/Cdi2Test.java b/webbeans-junit5/src/test/java/org/apache/openwebbeans/junit5/reusable/Cdi2Test.java
new file mode 100644
index 0000000..1771a71
--- /dev/null
+++ b/webbeans-junit5/src/test/java/org/apache/openwebbeans/junit5/reusable/Cdi2Test.java
@@ -0,0 +1,23 @@
+/*
+ * 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.openwebbeans.junit5.reusable;
+
+@Config
+class Cdi2Test extends Base {
+}
diff --git a/webbeans-junit5/src/test/java/org/apache/openwebbeans/junit5/reusable/Config.java b/webbeans-junit5/src/test/java/org/apache/openwebbeans/junit5/reusable/Config.java
new file mode 100644
index 0000000..33d91e2
--- /dev/null
+++ b/webbeans-junit5/src/test/java/org/apache/openwebbeans/junit5/reusable/Config.java
@@ -0,0 +1,38 @@
+/*
+ * 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.openwebbeans.junit5.reusable;
+
+import org.apache.openwebbeans.junit5.Cdi;
+import org.apache.openwebbeans.junit5.bean.MyService;
+
+import java.lang.annotation.Retention;
+import java.lang.annotation.Target;
+
+import static java.lang.annotation.ElementType.TYPE;
+import static java.lang.annotation.RetentionPolicy.RUNTIME;
+
+/**
+ * This is a way to create an alias for a configuration with JUnit 5.
+ */
+@Target(TYPE)
+@Retention(RUNTIME)
+@Cdi(disableDiscovery = true, reusable = true, classes = MyService.class)
+public @interface Config
+{
+}