首次测试后嵌入 Arquillian TomEE javax.naming.ConfigurationException
Arquillian TomEE embedded javax.naming.ConfigurationException after first test
我正在使用嵌入了 TomEE 的 Arquillian 来测试 SpringLoggerBeanProducer,它使用 CDI 构造一个记录器对象,然后可以使用 bean producing 将其注入到 Spring 容器中方法。我 运行 关注的问题是可以生产 5 种类型的记录器。当我 运行 测试(每个测试产生一种类型的记录器)时,只有首先执行的测试成功,而所有后续测试都因 javax.naming.ConfigurationException 而失败。
看起来好像只有第一个测试是在 JEE 服务器环境中执行的,而其他的则不是。
生产者代码如下:
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
似乎应用程序的某些部分弄乱了 tomee JNDI space(一个 ibm 客户端 jar?)。您可以尝试强制上下文工厂:org.apache.openejb.core.OpenEJBInitialContextFactory
旁注:也许还升级到 tomee 7.0.3?
我正在使用嵌入了 TomEE 的 Arquillian 来测试 SpringLoggerBeanProducer,它使用 CDI 构造一个记录器对象,然后可以使用 bean producing 将其注入到 Spring 容器中方法。我 运行 关注的问题是可以生产 5 种类型的记录器。当我 运行 测试(每个测试产生一种类型的记录器)时,只有首先执行的测试成功,而所有后续测试都因 javax.naming.ConfigurationException 而失败。 看起来好像只有第一个测试是在 JEE 服务器环境中执行的,而其他的则不是。
生产者代码如下:
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
似乎应用程序的某些部分弄乱了 tomee JNDI space(一个 ibm 客户端 jar?)。您可以尝试强制上下文工厂:org.apache.openejb.core.OpenEJBInitialContextFactory
旁注:也许还升级到 tomee 7.0.3?