WELD-001408: Unsatisfied dependencies for type Logger with qualifiers @Default at injection point [BackedAnnotatedField] @Inject

huangapple go评论68阅读模式
英文:

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;
    }
}

在我搜索了一些信息后,我了解到可能的问题可能是:

  1. 如果你没有将 bean-discovery-mode 设置为 "all"beans.xml 可能会导致问题,因为它不会扫描未注释的 bean,但是我的 beans.xml 文件已经设置了 bean-discovery-mode="all"
  2. 注入到 TodoService 类中的 Logger 和 EntityManager 可能没有 Producer,但我已经有了 Producers
  3. 人们在为 TodoServiceTodoServiceTestProducers 类导入 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(&quot;Bean TodoService created&quot;);
    }

    public Todo findTodoById(Long id) {
        return entityManager.find(Todo.class, id);
    }

    public List&lt;Todo&gt; getTodos(){
        return entityManager.createQuery(&quot;SELECT t from Todo t&quot;, 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(&quot;persistence.xml&quot;, &quot;META-INF/persistence.xml&quot;)
                .addAsManifestResource(EmptyAsset.INSTANCE, &quot;beans.xml&quot;);
    }

    @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&lt;String&gt; mappingFiles = new ArrayList();
        mappingFiles.add(&quot;dozerJdk8Converters.xml&quot;);
        mapper.setMappingFiles(mappingFiles);
        return mapper;
    }
}

Searching around, I understood that possible problems could be:

  1. 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"
  2. The Logger and the EntityManager injected into the TodoService class could not have a Producer, but I have the Producers class
  3. 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(&quot;persistence.xml&quot;, &quot;META-INF/persistence.xml&quot;)
                .addAsManifestResource(EmptyAsset.INSTANCE, &quot;beans.xml&quot;);
}

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(&quot;Bean TodoService created&quot;);
    }

    public Todo findTodoById(Long id) {
        return entityManager.find(Todo.class, id);
    }

    public List&lt;Todo&gt; getTodos(){
        return entityManager.createQuery(&quot;SELECT t from Todo t&quot;, Todo.class).getResultList();
    }

huangapple
  • 本文由 发表于 2020年8月20日 01:14:53
  • 转载请务必保留本文链接:https://go.coder-hub.com/63491903.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定