英文:
WELD-001408: Unsatisfied dependencies for type Logger with qualifiers @Default at injection point [BackedAnnotatedField] @Inject
问题
我在测试一个使用 Arquillian 的 JavaEE8 应用程序时遇到了问题:WELD-001408:对于带有 @Default 限定符的 Logger 类型的不满足的依赖关系
在注入点 [BackedAnnotatedField] @Inject private academy.learnprogramming.services.TodoService.LOG 处
我对注入的 EntityManager 也有相同的错误
以下是我的类:
TodoService.class(我需要测试的类)
package academy.learnprogramming.services;
import academy.learnprogramming.entities.Todo;
import org.apache.log4j.Logger;
import javax.annotation.PostConstruct;
import javax.inject.Inject;
import javax.persistence.EntityManager;
import javax.transaction.Transactional;
import java.util.List;
@Transactional
public class TodoService {
    @Inject
    private Logger LOG = Logger.getLogger(TodoService.class);
    @Inject
    EntityManager entityManager;
    public Todo createTodo(Todo todo) {
        //将数据持久化到数据库
        entityManager.persist(todo);
        return todo;
    }
    public Todo updateTodo(Todo todo) {
        entityManager.merge(todo);
        return todo;
    }
    @PostConstruct
    private void init() {
        LOG.info("Bean TodoService created");
    }
    public Todo findTodoById(Long id) {
        return entityManager.find(Todo.class, id);
    }
    public List<Todo> getTodos(){
        return entityManager.createQuery("SELECT t from Todo t", Todo.class).getResultList();
    }
}
TodoServiceTest.class(用于测试的类)
package academy.learnprogramming.services;
import academy.learnprogramming.config.Producers;
import academy.learnprogramming.entities.Todo;
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.After;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import static org.junit.Assert.*;
@RunWith(Arquillian.class)
public class TodoServiceTest {
    @Deployment
    public static JavaArchive createDeployment() {
        return ShrinkWrap.create(JavaArchive.class)
                .addClasses(TodoService.class, Todo.class, Producers.class)
                .addAsResource("persistence.xml", "META-INF/persistence.xml")
                .addAsManifestResource(EmptyAsset.INSTANCE, "beans.xml");
    }
    @Before
    public void setUp() throws Exception {
    }
    @After
    public void tearDown() throws Exception {
    }
    @Test
    public void createTodo() {
    }
    @Test
    public void updateTodo() {
    }
    @Test
    public void findTodoById() {
    }
    @Test
    public void getTodos() {
    }
}
Producers.class(用于将第三方库添加到 CDI 的类)
package academy.learnprogramming.config;
import org.apache.log4j.Logger;
import org.dozer.DozerBeanMapper;
import javax.enterprise.context.RequestScoped;
import javax.enterprise.inject.Produces;
import javax.enterprise.inject.spi.InjectionPoint;
import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;
import java.util.ArrayList;
import java.util.List;
public class Producers {
    @Produces
    @PersistenceContext
    EntityManager entityManager;
    @Produces
    public Logger produceLogger(InjectionPoint injectionPoint) {
        return Logger.getLogger(injectionPoint.getMember().getDeclaringClass().getName());
    }
    @Produces
    public DozerBeanMapper produceDozerBeanMapper() {
        DozerBeanMapper mapper = new DozerBeanMapper();
        List<String> mappingFiles = new ArrayList<>();
        mappingFiles.add("dozerJdk8Converters.xml");
        mapper.setMappingFiles(mappingFiles);
        return mapper;
    }
}
在我搜索了一些信息后,我了解到可能的问题可能是:
- 如果你没有将 
bean-discovery-mode设置为"all",beans.xml可能会导致问题,因为它不会扫描未注释的 bean,但是我的beans.xml文件已经设置了bean-discovery-mode="all" - 注入到 
TodoService类中的 Logger 和 EntityManager 可能没有 Producer,但我已经有了Producers类 - 人们在为 
TodoService、TodoServiceTest和Producers类导入 Logger 类时可能会犯错,例如在一个类中导入org.apache.log4j.Logger,在另一个类中导入java.util.logging.Logger,但我所有的类都使用了import org.apache.log4j.Logger 
如果我移除 @Inject 注解并且直接从类中使用 logger,那么它可以正常工作。
还有什么其他尝试的方法吗?非常感谢您的时间。
英文:
I'm having this problem while testing a JavaEE8 application with Arquillian: WELD-001408: Unsatisfied dependencies for type Logger with qualifiers @Default
at injection point [BackedAnnotatedField] @Inject private academy.learnprogramming.services.TodoService.LOG
I have the same error for the injected EntityManager
These are my classes:
TodoService.class (the class that I have to test)
package academy.learnprogramming.services;
import academy.learnprogramming.entities.Todo;
import org.apache.log4j.Logger;
import javax.annotation.PostConstruct;
import javax.inject.Inject;
import javax.persistence.EntityManager;
import javax.transaction.Transactional;
import java.util.List;
@Transactional
public class TodoService {
    @Inject
    private Logger LOG = Logger.getLogger(TodoService.class);
    @Inject
    EntityManager entityManager;
    public Todo createTodo(Todo todo) {
        //Persist into db
        entityManager.persist(todo);
        return todo;
    }
    public Todo updateTodo(Todo todo) {
        entityManager.merge(todo);
        return todo;
    }
    @PostConstruct
    private void init() {
        LOG.info("Bean TodoService created");
    }
    public Todo findTodoById(Long id) {
        return entityManager.find(Todo.class, id);
    }
    public List<Todo> getTodos(){
        return entityManager.createQuery("SELECT t from Todo t", Todo.class).getResultList();
    }
}
TodoServiceTest.class (The class used for testing)
package academy.learnprogramming.services;
import academy.learnprogramming.config.Producers;
import academy.learnprogramming.entities.Todo;
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.After;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import static org.junit.Assert.*;
@RunWith(Arquillian.class)
public class TodoServiceTest {
    @Deployment
    public static JavaArchive createDeployment() {
        return ShrinkWrap.create(JavaArchive.class)
                .addClasses(TodoService.class, Todo.class, Producers.class)
                .addAsResource("persistence.xml", "META-INF/persistence.xml")
                .addAsManifestResource(EmptyAsset.INSTANCE, "beans.xml");
    }
    @Before
    public void setUp() throws Exception {
    }
    @After
    public void tearDown() throws Exception {
    }
    @Test
    public void createTodo() {
    }
    @Test
    public void updateTodo() {
    }
    @Test
    public void findTodoById() {
    }
    @Test
    public void getTodos() {
    }
}
Producers.class (Class used to add 3rd party libraries to CDI)
package academy.learnprogramming.config;
import org.apache.log4j.Logger;
import org.dozer.DozerBeanMapper;
import javax.enterprise.context.RequestScoped;
import javax.enterprise.inject.Produces;
import javax.enterprise.inject.spi.InjectionPoint;
import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;
import java.util.ArrayList;
import java.util.List;
//If producers becomes complitated, split it in many classes, each for a single producer
public class Producers {
    @Produces
    @PersistenceContext
    EntityManager entityManager;
    @Produces
    public Logger produceLogger(InjectionPoint injectionPoint) {
        return Logger.getLogger(injectionPoint.getMember().getDeclaringClass().getName());
    }
    //Auto mapper
    @Produces
    public DozerBeanMapper produceDozenBeanMapper() {
        DozerBeanMapper mapper = new DozerBeanMapper();
        List<String> mappingFiles = new ArrayList();
        mappingFiles.add("dozerJdk8Converters.xml");
        mapper.setMappingFiles(mappingFiles);
        return mapper;
    }
}
Searching around, I understood that possible problems could be:
- beans.xml could give problems if you don't put bean-discovery-mode="all", because it won't scan for not annotated beans, but my beans.xml file has bean-discovery-mode="all"
 - The Logger and the EntityManager injected into the TodoService class could not have a Producer, but I have the Producers class
 - People can make mistakes during the import of Logger class for TodoService, TodoServiceTest and Producers classes, having for example import org.apache.log4j.Logger in one class, and java util.logging.Logger for another, but I have all classes with import org.apache.log4j.Logger
 
If I remove the @Inject annotation and I use the logger from the classes, It works.
What else can I try?
Thank you a lot for your time.
答案1
得分: 0
尝试在使用WAR文件时使用WebArchive
 @Deployment
    public static WebArchive createDeployment() {
        return ShrinkWrap.create(WebArchive.class)
                .addClasses(TodoService.class, Todo.class, Producers.class)
                .addAsResource("persistence.xml", "META-INF/persistence.xml")
                .addAsManifestResource(EmptyAsset.INSTANCE, "beans.xml");
}
移除Logger.getLogger(TodoService.class);,生产者将会实例化日志记录器。
@RequestScoped
@Transactional
public class TodoService {
    @Inject
    private Logger log;
    @Inject
    EntityManager entityManager;
    public Todo createTodo(Todo todo) {
        //向数据库持久化
        entityManager.persist(todo);
        return todo;
    }
    public Todo updateTodo(Todo todo) {
        entityManager.merge(todo);
        return todo;
    }
    @PostConstruct
    private void init() {
        log.info("Bean TodoService已创建");
    }
    public Todo findTodoById(Long id) {
        return entityManager.find(Todo.class, id);
    }
    public List<Todo> getTodos(){
        return entityManager.createQuery("SELECT t from Todo t", Todo.class).getResultList();
    }
}
英文:
Try to use the WebArchive if you use a WAR file
 @Deployment
    public static WebArchive createDeployment() {
        return ShrinkWrap.create(WebArchive.class)
                .addClasses(TodoService.class, Todo.class, Producers.class)
                .addAsResource("persistence.xml", "META-INF/persistence.xml")
                .addAsManifestResource(EmptyAsset.INSTANCE, "beans.xml");
}
remove the Logger.getLogger(TodoService.class); the producer it's going to instantiate the logger.
@RequestScoped
@Transactional
public class TodoService {
    @Inject
    private Logger log;
    @Inject
    EntityManager entityManager;
    public Todo createTodo(Todo todo) {
        //Persist into db
        entityManager.persist(todo);
        return todo;
    }
    public Todo updateTodo(Todo todo) {
        entityManager.merge(todo);
        return todo;
    }
    @PostConstruct
    private void init() {
        log.info("Bean TodoService created");
    }
    public Todo findTodoById(Long id) {
        return entityManager.find(Todo.class, id);
    }
    public List<Todo> getTodos(){
        return entityManager.createQuery("SELECT t from Todo t", Todo.class).getResultList();
    }
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。


评论