package org.testfun.jee.runner.inject; import org.testfun.jee.runner.DependencyInjector; import org.testfun.jee.runner.EjbWithMockitoRunnerException; import javax.annotation.PostConstruct; import javax.ejb.EJB; import javax.ejb.Singleton; import javax.ejb.Stateless; import java.lang.annotation.Annotation; import java.lang.reflect.Field; import java.lang.reflect.Method; // Lookup and inject to @EJB annotated member variables public class EjbInjector extends BaseInjector { @Override public Class<? extends Annotation> getAnnotation() { return EJB.class; } @Override public <T> void doInject(T target, Field field) { Object ejb; // If the field's class is a singleton or a stateless-session, than it isn't expected to implement any interface // so the class itself is registered if (field.getType().getAnnotation(Singleton.class) != null || field.getType().getAnnotation(Stateless.class) != null) { Class<?> fieldClass = field.getType(); // Search for an instance of this interface or a mock ejb = findInstanceByClass(fieldClass); // If none was found, instantiate a new one and register the it in the various caches if (ejb == null) { ejb = instantiateSingletonAndCache(fieldClass); } } else { // Get class of the field and make sure it is an interface Class<?> fieldClass = InjectionUtils.getFieldInterface(target, field); // Search for an instance of this interface or a mock ejb = findInstanceByClass(fieldClass); // If none was found, instantiate a new one and register the it in the various caches if (ejb == null) { ejb = instantiateAndCache(fieldClass); } } // Assign the EJB to the field InjectionUtils.assignObjectToField(target, field, ejb); } private Object instantiateAndCache(Class<?> fieldClass) { // Try to instantiate an implementation of the field's class Object transactionLessEjb = EjbInstanceFactory.getInstance().newInstance(fieldClass); // Wrap the EJB with a transaction. Object ejb = TransactionUtils.wrapEjbWithTransaction(transactionLessEjb); registerByImplementedInterfaces(ejb); // Finally, inject dependencies into the new EJB DependencyInjector.getInstance().injectDependencies(transactionLessEjb); return ejb; } private Object instantiateSingletonAndCache(Class<?> fieldClass) { // Try to instantiate an implementation of the singleton Object singleton = EjbInstanceFactory.getInstance().newInstance(fieldClass); registerByClass(fieldClass, singleton); // Inject dependencies into the new EJB DependencyInjector.getInstance().injectDependencies(singleton); // Invoke any method annotated with @PostConstruct Method[] declaredMethods = fieldClass.getDeclaredMethods(); for (Method method : declaredMethods) { if (method.isAnnotationPresent(PostConstruct.class)) { try { method.invoke(singleton); } catch (Exception e) { throw new EjbWithMockitoRunnerException("Failed invoking '" + method.getName() + "'", e); } } } return singleton; } }