From b0306567cab332f5e3e24e8797afefb1625c0151 Mon Sep 17 00:00:00 2001 From: Carlos Barragan Date: Fri, 6 Mar 2015 17:17:43 +0100 Subject: [PATCH] Closes #18 - References from EJB-Singletons are now supported --- .../extension/AnnotationInstances.java | 42 +++++++++++++++++++ .../beantest/extension/BeanTestExtension.java | 40 ++++++++++++++---- .../beantest/extension/InjectionHelper.java | 7 +--- .../beantest/demo/ejb/MyEjbSingleton.java | 42 +++++++++++++++++++ .../demo/ejb/TestSingletonInjection.java | 39 +++++++++++++++++ 5 files changed, 156 insertions(+), 14 deletions(-) create mode 100644 src/main/java/info/novatec/beantest/extension/AnnotationInstances.java create mode 100644 src/test/java/info/novatec/beantest/demo/ejb/MyEjbSingleton.java create mode 100644 src/test/java/info/novatec/beantest/demo/ejb/TestSingletonInjection.java diff --git a/src/main/java/info/novatec/beantest/extension/AnnotationInstances.java b/src/main/java/info/novatec/beantest/extension/AnnotationInstances.java new file mode 100644 index 0000000..c7a4139 --- /dev/null +++ b/src/main/java/info/novatec/beantest/extension/AnnotationInstances.java @@ -0,0 +1,42 @@ +/* + * Bean Testing. + * + * 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 info.novatec.beantest.extension; + +import info.novatec.beantest.transactions.Transactional; +import javax.ejb.Singleton; +import javax.enterprise.context.ApplicationScoped; +import javax.enterprise.context.RequestScoped; +import javax.inject.Inject; +import org.apache.deltaspike.core.util.metadata.AnnotationInstanceProvider; + +/** + * Class that contains constants of annotation instances. + * + * @author Carlos Barragan (carlos.barragan@novatec-gmbh.de) + */ +public final class AnnotationInstances { + + private AnnotationInstances() { + + } + + public static final Transactional TRANSACTIONAL = AnnotationInstanceProvider.of(Transactional.class); + public static final RequestScoped REQUEST_SCOPED = AnnotationInstanceProvider.of(RequestScoped.class); + public static final Inject INJECT = AnnotationInstanceProvider.of(Inject.class); + public static final Singleton SINGLETON = AnnotationInstanceProvider.of(Singleton.class); + public static final ApplicationScoped APPLICATION_SCOPED = AnnotationInstanceProvider.of(ApplicationScoped.class); + +} diff --git a/src/main/java/info/novatec/beantest/extension/BeanTestExtension.java b/src/main/java/info/novatec/beantest/extension/BeanTestExtension.java index 6b0c5f7..9a25ab6 100644 --- a/src/main/java/info/novatec/beantest/extension/BeanTestExtension.java +++ b/src/main/java/info/novatec/beantest/extension/BeanTestExtension.java @@ -18,15 +18,17 @@ import info.novatec.beantest.transactions.Transactional; import javax.ejb.EJB; import javax.ejb.MessageDriven; +import javax.ejb.Singleton; import javax.ejb.Stateless; +import javax.enterprise.context.ApplicationScoped; import javax.enterprise.context.RequestScoped; import javax.enterprise.event.Observes; import javax.enterprise.inject.spi.AnnotatedType; import javax.enterprise.inject.spi.Extension; import javax.enterprise.inject.spi.ProcessAnnotatedType; +import javax.enterprise.inject.spi.WithAnnotations; import javax.inject.Inject; import javax.interceptor.Interceptor; -import org.apache.deltaspike.core.util.metadata.AnnotationInstanceProvider; import org.apache.deltaspike.core.util.metadata.builder.AnnotatedTypeBuilder; /** @@ -39,6 +41,8 @@ * @author Carlos Barragan (carlos.barragan@novatec-gmbh.de) */ public class BeanTestExtension implements Extension { + + /** * Replaces the meta data of the {@link ProcessAnnotatedType}. @@ -48,19 +52,40 @@ public class BeanTestExtension implements Extension { * * * @param the type of the ProcessAnnotatedType * @param pat the annotated type representing the class being processed */ - public void processInjectionTarget(@Observes ProcessAnnotatedType pat) { + public void processInjectionTarget(@Observes @WithAnnotations({Stateless.class, MessageDriven.class, Interceptor.class, Singleton.class}) ProcessAnnotatedType pat) { if (pat.getAnnotatedType().isAnnotationPresent(Stateless.class) || pat.getAnnotatedType().isAnnotationPresent(MessageDriven.class)) { - modifyAnnotatedTypeMetaData(pat); + modifiyAnnotatedTypeMetadata(pat); } else if (pat.getAnnotatedType().isAnnotationPresent(Interceptor.class)) { processInterceptorDependencies(pat); + } else if(pat.getAnnotatedType().isAnnotationPresent(Singleton.class)) { + addApplicationScopedAndTransactionalToSingleton(pat); } } + + /** + * Adds {@link Transactional} and {@link ApplicationScoped} to the given annotated type and converts + * its EJB injection points into CDI injection points (i.e. it adds the {@link Inject}) + * @param the type of the annotated type. + * @param pat the process annotated type. + */ + private void addApplicationScopedAndTransactionalToSingleton(ProcessAnnotatedType pat) { + AnnotatedType at = pat.getAnnotatedType(); + + AnnotatedTypeBuilder builder = new AnnotatedTypeBuilder().readFromType(at); + + builder.addToClass(AnnotationInstances.APPLICATION_SCOPED).addToClass(AnnotationInstances.TRANSACTIONAL); + + InjectionHelper.addInjectAnnotation(at, builder); + + pat.setAnnotatedType(builder.create()); + } /** * Adds {@link Transactional} and {@link RequestScoped} to the given annotated type and converts @@ -68,14 +93,11 @@ public void processInjectionTarget(@Observes ProcessAnnotatedType pat) { * @param the type of the annotated type * @param pat the process annotated type. */ - private void modifyAnnotatedTypeMetaData(ProcessAnnotatedType pat) { - Transactional transactionalAnnotation = AnnotationInstanceProvider.of(Transactional.class); - RequestScoped requestScopedAnnotation = AnnotationInstanceProvider.of(RequestScoped.class); - + private void modifiyAnnotatedTypeMetadata(ProcessAnnotatedType pat) { AnnotatedType at = pat.getAnnotatedType(); AnnotatedTypeBuilder builder = new AnnotatedTypeBuilder().readFromType(at); - builder.addToClass(transactionalAnnotation).addToClass(requestScopedAnnotation); + builder.addToClass(AnnotationInstances.TRANSACTIONAL).addToClass(AnnotationInstances.REQUEST_SCOPED); InjectionHelper.addInjectAnnotation(at, builder); //Set the wrapper instead the actual annotated type diff --git a/src/main/java/info/novatec/beantest/extension/InjectionHelper.java b/src/main/java/info/novatec/beantest/extension/InjectionHelper.java index 1b9fa26..9243738 100644 --- a/src/main/java/info/novatec/beantest/extension/InjectionHelper.java +++ b/src/main/java/info/novatec/beantest/extension/InjectionHelper.java @@ -27,7 +27,6 @@ import javax.enterprise.inject.spi.AnnotatedType; import javax.inject.Inject; import javax.persistence.PersistenceContext; -import org.apache.deltaspike.core.util.metadata.AnnotationInstanceProvider; import org.apache.deltaspike.core.util.metadata.builder.AnnotatedTypeBuilder; /** @@ -37,8 +36,6 @@ */ public final class InjectionHelper { - private static final Inject INJECT_ANNOTATION = AnnotationInstanceProvider.of(Inject.class); - private static final Set> JAVA_EE_ANNOTATIONS = createJavaEEAnnotationSet(); private static Set> createJavaEEAnnotationSet() { @@ -108,12 +105,12 @@ private static boolean hasJavaEEAnnotations(AnnotatedMember membe public static void addInjectAnnotation(final AnnotatedType annotatedType, AnnotatedTypeBuilder builder) { for (AnnotatedField field : annotatedType.getFields()) { if (shouldInjectionAnnotationBeAddedToMember(field)) { - builder.addToField(field, INJECT_ANNOTATION); + builder.addToField(field, AnnotationInstances.INJECT); } } for (AnnotatedMethod method : annotatedType.getMethods()) { if (shouldInjectionAnnotationBeAddedToMember(method)) { - builder.addToMethod(method, INJECT_ANNOTATION); + builder.addToMethod(method, AnnotationInstances.INJECT); } } } diff --git a/src/test/java/info/novatec/beantest/demo/ejb/MyEjbSingleton.java b/src/test/java/info/novatec/beantest/demo/ejb/MyEjbSingleton.java new file mode 100644 index 0000000..dac253e --- /dev/null +++ b/src/test/java/info/novatec/beantest/demo/ejb/MyEjbSingleton.java @@ -0,0 +1,42 @@ +/* + * Bean Testing. + * + * 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 info.novatec.beantest.demo.ejb; + +import javax.ejb.EJB; +import javax.ejb.Singleton; + +/** + * Demo EJB Singleton. + * @author Carlos Barragan (carlos.barragan@novatec-gmbh.de) + */ +@Singleton +public class MyEjbSingleton { + + @EJB + MyOtherEJBService ejbService; + + private boolean wasEjbCalled=false; + + public void callAnEjb() { + ejbService.doSomething(); + wasEjbCalled = true; + } + + public boolean wasEjbCalled() { + return this.wasEjbCalled; + } + +} diff --git a/src/test/java/info/novatec/beantest/demo/ejb/TestSingletonInjection.java b/src/test/java/info/novatec/beantest/demo/ejb/TestSingletonInjection.java new file mode 100644 index 0000000..e534eac --- /dev/null +++ b/src/test/java/info/novatec/beantest/demo/ejb/TestSingletonInjection.java @@ -0,0 +1,39 @@ +/* + * Bean Testing. + * + * 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 info.novatec.beantest.demo.ejb; + +import info.novatec.beantest.api.BaseBeanTest; +import static org.hamcrest.Matchers.is; +import static org.junit.Assert.assertThat; +import org.junit.Test; + +/** + * This test verifies that an EJB Singleton is instantiated just once and is able to call other EJBs. + * + * @author Carlos Barragan (carlos.barragan@novatec-gmbh.de) + */ +public class TestSingletonInjection extends BaseBeanTest { + + @Test + public void shouldBeInstantiatedOnce() { + MyEjbSingleton singleton= getBean(MyEjbSingleton.class); + assertThat(singleton.wasEjbCalled(), is(false)); + singleton.callAnEjb(); + assertThat(singleton.wasEjbCalled(), is(true)); + } + + +}