WELD-001408 : 주입 지점 [BackedAnnotatedField] @Inject에서 @Default 한정자가있는 Logger 유형에 대한 종속성이 충족되지 않았습니다.

Aug 19 2020

Arquillian을 사용하여 JavaEE8 응용 프로그램을 테스트하는 동안이 문제가 발생합니다. WELD-001408 : 주입 지점 [BackedAnnotatedField] @Inject private academy.learnprogramming.services.TodoService.LOG 한정자가있는 Logger 유형에 대한 종속성이 충족되지 않습니다.

주입 된 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) {
        //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 (테스트에 사용되는 클래스)

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;

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

주변을 검색하면서 가능한 문제가 다음과 같을 수 있음을 이해했습니다.

  1. bean-discovery-mode = "all"을 넣지 않으면 bean-discovery-mode = "all"이 문제가 될 수 있습니다. 왜냐하면 주석이 붙지 않은 bean을 스캔하지 않을 것이기 때문입니다. 그러나 내 beans.xml 파일에는 bean-discovery-mode = "all"이 있습니다.
  2. TodoService 클래스에 삽입 된 Logger 및 EntityManager에는 Producer가있을 수 없지만 Producers 클래스가 있습니다.
  3. 사람들은 TodoService, TodoServiceTest 및 Producers 클래스에 대해 Logger 클래스를 가져 오는 동안 실수를 할 수 있습니다. 예를 들어 한 클래스에는 org.apache.log4j.Logger를 가져오고 다른 클래스에는 java util.logging.Logger를 사용하지만 모든 클래스에는 import가 있습니다. org.apache.log4j.Logger

@Inject 주석을 제거하고 클래스에서 로거를 사용하면 작동합니다.

또 무엇을 시도 할 수 있습니까? 시간 내 주셔서 감사합니다.

답변

LuisGalaz Aug 19 2020 at 19:21

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) {
        //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();
    }