Skip to content

Commit

Permalink
Closes #18 - References from EJB-Singletons are now supported
Browse files Browse the repository at this point in the history
  • Loading branch information
carlosbarragan committed Mar 23, 2015
1 parent 36f8463 commit b030656
Show file tree
Hide file tree
Showing 5 changed files with 156 additions and 14 deletions.
Original file line number Diff line number Diff line change
@@ -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);

}
Original file line number Diff line number Diff line change
Expand Up @@ -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;

/**
Expand All @@ -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}.
Expand All @@ -48,34 +52,52 @@ public class BeanTestExtension implements Extension {
* <ul>
* <li> {@link Stateless}
* <li> {@link MessageDriven}
* <li> {@link Interceptor}
* <li> {@link Interceptor}
* <li> {@link Singleton}
* </ul>
*
* @param <X> the type of the ProcessAnnotatedType
* @param pat the annotated type representing the class being processed
*/
public <X> void processInjectionTarget(@Observes ProcessAnnotatedType<X> pat) {
public <X> void processInjectionTarget(@Observes @WithAnnotations({Stateless.class, MessageDriven.class, Interceptor.class, Singleton.class}) ProcessAnnotatedType<X> 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 <X> the type of the annotated type.
* @param pat the process annotated type.
*/
private <X> void addApplicationScopedAndTransactionalToSingleton(ProcessAnnotatedType<X> pat) {
AnnotatedType at = pat.getAnnotatedType();

AnnotatedTypeBuilder<X> builder = new AnnotatedTypeBuilder<X>().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
* its EJB injection points into CDI injection points (i.e. it adds the {@link Inject})
* @param <X> the type of the annotated type
* @param pat the process annotated type.
*/
private <X> void modifyAnnotatedTypeMetaData(ProcessAnnotatedType<X> pat) {
Transactional transactionalAnnotation = AnnotationInstanceProvider.of(Transactional.class);
RequestScoped requestScopedAnnotation = AnnotationInstanceProvider.of(RequestScoped.class);

private <X> void modifiyAnnotatedTypeMetadata(ProcessAnnotatedType<X> pat) {
AnnotatedType at = pat.getAnnotatedType();

AnnotatedTypeBuilder<X> builder = new AnnotatedTypeBuilder<X>().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
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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;

/**
Expand All @@ -37,8 +36,6 @@
*/
public final class InjectionHelper {

private static final Inject INJECT_ANNOTATION = AnnotationInstanceProvider.of(Inject.class);

private static final Set<Class<? extends Annotation>> JAVA_EE_ANNOTATIONS = createJavaEEAnnotationSet();

private static Set<Class<? extends Annotation>> createJavaEEAnnotationSet() {
Expand Down Expand Up @@ -108,12 +105,12 @@ private static <X> boolean hasJavaEEAnnotations(AnnotatedMember<? super X> membe
public static <X> void addInjectAnnotation(final AnnotatedType<X> annotatedType, AnnotatedTypeBuilder<X> builder) {
for (AnnotatedField<? super X> field : annotatedType.getFields()) {
if (shouldInjectionAnnotationBeAddedToMember(field)) {
builder.addToField(field, INJECT_ANNOTATION);
builder.addToField(field, AnnotationInstances.INJECT);
}
}
for (AnnotatedMethod<? super X> method : annotatedType.getMethods()) {
if (shouldInjectionAnnotationBeAddedToMember(method)) {
builder.addToMethod(method, INJECT_ANNOTATION);
builder.addToMethod(method, AnnotationInstances.INJECT);
}
}
}
Expand Down
42 changes: 42 additions & 0 deletions src/test/java/info/novatec/beantest/demo/ejb/MyEjbSingleton.java
Original file line number Diff line number Diff line change
@@ -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;
}

}
Original file line number Diff line number Diff line change
@@ -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));
}


}

0 comments on commit b030656

Please sign in to comment.