2017-06-01 30 views
1

我使用Arquillian和TomEE嵌入来测试一个SpringLoggerBeanProducer,它使用CDI构建一个记录器对象,而该对象又可以使用一个bean生成注入Spring容器方法。我遇到的问题是可以生产5种类型的记录器。当我运行测试(每个产生一种类型的记录器)时,只有首先执行的测试成功,而由于javax.naming.ConfigurationException所有后续测试失败。 看起来好像只有第一个测试在JEE服务器环境中执行,而其他测试不是。Arquillian TomEE在第一次测试后嵌入了javax.naming.ConfigurationException

为生产者的代码如下:

package mypackage.monitoring.spring.logger.producer; 

import java.lang.annotation.Annotation; 
import java.lang.reflect.Field; 
import java.lang.reflect.Member; 
import java.lang.reflect.Modifier; 
import java.lang.reflect.Type; 
import java.util.HashSet; 
import java.util.Set; 

import javax.enterprise.context.spi.CreationalContext; 
import javax.enterprise.inject.spi.Annotated; 
import javax.enterprise.inject.spi.Bean; 
import javax.enterprise.inject.spi.BeanManager; 
import javax.enterprise.inject.spi.InjectionPoint; 
import javax.naming.InitialContext; 
import javax.naming.NamingException; 

import org.springframework.beans.factory.config.ConfigurableBeanFactory; 
import org.springframework.context.annotation.Configuration; 
import org.springframework.context.annotation.Scope; 

import mypackage.monitoring.shared.logger.Logger; 
import mypackage.monitoring.shared.qualifier.Application; 
import mypackage.monitoring.shared.qualifier.Business; 
import mypackage.monitoring.shared.qualifier.Security; 
import mypackage.monitoring.shared.qualifier.Technical; 

@Configuration 
public class SpringLoggerBeanProducer { 

private BeanManager beanManager; 

@org.springframework.context.annotation.Bean 
@Scope(ConfigurableBeanFactory.SCOPE_PROTOTYPE) 
@Application 
public Logger applicationLogger(org.springframework.beans.factory.InjectionPoint springIp) { 
    return logger(springIp); 
} 

@org.springframework.context.annotation.Bean 
@Scope(ConfigurableBeanFactory.SCOPE_PROTOTYPE) 
@Business 
public Logger businessLogger(org.springframework.beans.factory.InjectionPoint springIp) { 
    return logger(springIp); 
} 

@org.springframework.context.annotation.Bean 
@Scope(ConfigurableBeanFactory.SCOPE_PROTOTYPE) 
@Security 
public Logger securityLogger(org.springframework.beans.factory.InjectionPoint springIp) { 
    return logger(springIp); 
} 

@org.springframework.context.annotation.Bean 
@Scope(ConfigurableBeanFactory.SCOPE_PROTOTYPE) 
@Technical 
public Logger technicalLogger(org.springframework.beans.factory.InjectionPoint springIp) { 
    return logger(springIp); 
} 

private Logger logger(org.springframework.beans.factory.InjectionPoint springIp) { 
    setBeanManager(); 
    Field field = springIp.getField(); 
    Annotation[] qualifiers = getFieldQualifiers(field); 
    Bean<? extends Object> bean = getLoggerBean(qualifiers); 
    return getInjectableLoggerReference(field, bean); 
} 

private Logger getInjectableLoggerReference(Field field, Bean<?> bean) { 
    CreationalContext<?> creationalContext = beanManager.createCreationalContext(bean); 
    return (Logger) beanManager.getInjectableReference(getInjectionPoint(field), creationalContext); 
} 

private Bean<? extends Object> getLoggerBean(Annotation[] qualifiers) { 
    Set<Bean<?>> beans = beanManager.getBeans(Logger.class, qualifiers); 
    return beanManager.resolve(beans); 
} 

private Annotation[] getFieldQualifiers(Field field) { 
    Annotation[] annotations = field.getAnnotations(); 

    Set<Annotation> qualifierSet = getQualifierSet(annotations); 
    annotations = qualifierSet.toArray(new Annotation[0]); 
    return annotations; 
} 

private void setBeanManager() { 
    try { 
     if (beanManager == null) { 
      beanManager = InitialContext.doLookup("java:comp/BeanManager"); 
     } 
    } catch (NamingException e) { 
     throw new LoggerProducerException("BeanManager not found.", e); 
    } 
} 

private Set<Annotation> getQualifierSet(Annotation[] annotations) { 
    Set<Annotation> qualifierSet = new HashSet<Annotation>(); 
    for (Annotation annotation : annotations) { 
     if (annotation.annotationType().isAnnotationPresent(javax.inject.Qualifier.class)) { 
      qualifierSet.add(annotation); 
     } 
    } 
    return qualifierSet; 
} 

private InjectionPoint getInjectionPoint(final Field member) { 
    class GeneratedInjectionPoint implements InjectionPoint { 

     @Override 
     public boolean isTransient() { 
      return Modifier.isTransient(member.getModifiers()); 
     } 

     @Override 
     public boolean isDelegate() { 
      return false; 
     } 

     @Override 
     public Type getType() { 
      return member.getType(); 
     } 

     @Override 
     public Set<Annotation> getQualifiers() { 
      Annotation[] annotations = member.getAnnotations(); 
      return getQualifierSet(annotations); 
     } 

     @Override 
     public Member getMember() { 
      return member; 
     } 

     @Override 
     public Bean<?> getBean() { 
      return null; 
     } 

     @Override 
     public Annotated getAnnotated() { 
      throw new UnsupportedOperationException("Method not implemented for " + this.getClass().getSimpleName() + ".class"); 
     } 
    } 

    return new GeneratedInjectionPoint(); 
} 
} 

发生在线路beanManager = InitialContext.doLookup("java:comp/BeanManager");

用于测试的代码中的例外:

package mypackage.monitoring.spring.logger.producer; 

import static org.junit.Assert.assertThat; 

import java.lang.reflect.Field; 

import javax.inject.Inject; 

import org.hamcrest.Matchers; 
import org.jboss.arquillian.container.test.api.Deployment; 
import org.jboss.arquillian.junit.Arquillian; 
import org.jboss.shrinkwrap.api.ShrinkWrap; 
import org.jboss.shrinkwrap.api.asset.EmptyAsset; 
import org.jboss.shrinkwrap.api.spec.JavaArchive; 
import org.junit.Test; 
import org.junit.runner.RunWith; 
import org.springframework.beans.factory.InjectionPoint; 

import mypackage.monitoring.shared.event.MonitorEventType; 
import mypackage.monitoring.shared.logger.Logger; 
import mypackage.monitoring.shared.qualifier.Application; 
import mypackage.monitoring.shared.qualifier.Business; 
import mypackage.monitoring.shared.qualifier.Security; 
import mypackage.monitoring.shared.qualifier.Technical; 

@RunWith(Arquillian.class) 
public class SpringLoggerBeanProducerIT<X> { 

@Inject 
private SpringLoggerBeanProducer producer; 

private Logger defaultLogger; 
@Application 
private Logger applicationLogger; 
@Business 
private Logger businessLogger; 
@Security 
private Logger securityLogger; 
@Technical 
private Logger technicalLogger; 

@Deployment 
public static JavaArchive createDeployment() { 
    return ShrinkWrap.create(JavaArchive.class).addPackages(true, "mypackage") 
      .addAsManifestResource(EmptyAsset.INSTANCE, "beans.xml"); 
} 

@Test 
public void alsDefaultLoggerDanMonitorEventTypeTechnical() throws Exception { 
    System.out.println("Default Logger"); 
    Logger logger = producer.applicationLogger(new InjectionPoint(this.getClass().getDeclaredField("defaultLogger"))); 

    assertThat(logger, Matchers.notNullValue()); 

    Field typeField = logger.getClass().getSuperclass().getDeclaredField("type"); 
    typeField.setAccessible(true); 
    MonitorEventType type = (MonitorEventType) typeField.get(logger); 

    assertThat(type, Matchers.is(MonitorEventType.TECHNICAL)); 
} 

@Test 
public void alsApplicationLoggerDanMonitorEventTypeApplication() throws Exception { 
    System.out.println("Application Logger"); 
    Logger logger = producer.applicationLogger(new InjectionPoint(this.getClass().getDeclaredField("applicationLogger"))); 

    assertThat(logger, Matchers.notNullValue()); 

    Field typeField = logger.getClass().getSuperclass().getDeclaredField("type"); 
    typeField.setAccessible(true); 
    MonitorEventType type = (MonitorEventType) typeField.get(logger); 

    assertThat(type, Matchers.is(MonitorEventType.APPLICATION)); 
} 

@Test 
public void alsBusinessLoggerDanMonitorEventTypeBusiness() throws Exception { 
    System.out.println("Business Logger"); 
    Logger logger = producer.applicationLogger(new InjectionPoint(this.getClass().getDeclaredField("businessLogger"))); 

    assertThat(logger, Matchers.notNullValue()); 

    Field typeField = logger.getClass().getSuperclass().getDeclaredField("type"); 
    typeField.setAccessible(true); 
    MonitorEventType type = (MonitorEventType) typeField.get(logger); 

    assertThat(type, Matchers.is(MonitorEventType.BUSINESS)); 
} 

@Test 
public void alsSecurityLoggerDanMonitorEventTypeSecurity() throws Exception { 
    System.out.println("Security Logger"); 
    Logger logger = producer.applicationLogger(new InjectionPoint(this.getClass().getDeclaredField("securityLogger"))); 

    assertThat(logger, Matchers.notNullValue()); 

    Field typeField = logger.getClass().getSuperclass().getDeclaredField("type"); 
    typeField.setAccessible(true); 
    MonitorEventType type = (MonitorEventType) typeField.get(logger); 

    assertThat(type, Matchers.is(MonitorEventType.SECURITY)); 
} 

@Test 
public void alsTechnicalLoggerDanMonitorEventTypeTechnical() throws Exception { 
    System.out.println("Technical Logger"); 
    Logger logger = producer.applicationLogger(new InjectionPoint(this.getClass().getDeclaredField("technicalLogger"))); 

    assertThat(logger, Matchers.notNullValue()); 

    Field typeField = logger.getClass().getSuperclass().getDeclaredField("type"); 
    typeField.setAccessible(true); 
    MonitorEventType type = (MonitorEventType) typeField.get(logger); 

    assertThat(type, Matchers.is(MonitorEventType.TECHNICAL)); 
} 

} 

我已经加入以下Maven依赖项目:

<!-- Arquillian junit testen --> 
    <dependency> 
     <groupId>org.jboss.arquillian.junit</groupId> 
     <artifactId>arquillian-junit-container</artifactId> 
     <version>1.1.9.FINAL</version> 
     <scope>test</scope> 
    </dependency> 

    <!-- Arquillian adapter voor TomEE --> 
    <dependency> 
     <groupId>org.apache.openejb</groupId> 
     <artifactId>arquillian-tomee-embedded</artifactId> 
     <version>1.7.4</version> 
     <scope>test</scope> 
    </dependency> 

    <!-- Embedded container TomEE --> 
    <dependency> 
     <groupId>org.apache.openejb</groupId> 
     <artifactId>tomee-embedded</artifactId> 
     <version>1.7.4</version> 
     <scope>test</scope> 
    </dependency> 

Test results

Stacktrace

回答

0

看来应用程序的某些部分弄乱tomee JNDI空间(IBM客户端罐子?)。您可以尝试强制上下文工厂:org.apache.openejb.core.OpenEJBInitialContextFactory

注意:也许还升级到tomee 7.0.3?

+0

它确实似乎是JNDI空间中的一个冲突,因为它在执行第一个测试后发生了变化。至于为什么会发生这种情况,我仍然有点模糊,但现在我有办法解决这个问题。 –