WELD-001408: Ketergantungan tidak terpenuhi untuk tipe Logger dengan kualifikasi @Default pada titik injeksi [BackedAnnotatedField] @Inject

Aug 19 2020

Saya mengalami masalah ini saat menguji aplikasi JavaEE8 dengan Arquillian: WELD-001408: Dependensi yang tidak terpenuhi untuk tipe Logger dengan kualifikasi @Default pada titik injeksi [BackedAnnotatedField] @Inject private academy.learnprogramming.services.TodoService.LOG

Saya memiliki kesalahan yang sama untuk EntityManager yang diinjeksi

Ini adalah kelas saya:

TodoService.class (kelas yang harus saya uji)

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 (Kelas yang digunakan untuk pengujian)

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 (Kelas yang digunakan untuk menambahkan perpustakaan pihak ketiga ke 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;
    }
}

Mencari-cari, saya mengerti bahwa kemungkinan masalah bisa jadi:

  1. beans.xml dapat memberikan masalah jika Anda tidak meletakkan bean-discovery-mode = "all", karena tidak akan memindai kacang yang tidak dianotasi, tetapi file beans.xml saya memiliki bean-discovery-mode = "all"
  2. Logger dan EntityManager yang dimasukkan ke dalam kelas TodoService tidak dapat memiliki Produser, tetapi saya memiliki kelas Produser
  3. Orang dapat membuat kesalahan selama pengimporan kelas Logger untuk kelas TodoService, TodoServiceTest dan Producers, misalnya dengan mengimpor org.apache.log4j.Logger dalam satu kelas, dan java util.logging.Logger untuk kelas lainnya, tetapi saya memiliki semua kelas dengan impor org.apache.log4j.Logger

Jika saya menghapus anotasi @Inject dan saya menggunakan logger dari kelas, itu berhasil.

Apa lagi yang bisa saya coba? Terima kasih banyak atas waktunya.

Jawaban

LuisGalaz Aug 19 2020 at 19:21

Coba gunakan WebArchive jika Anda menggunakan file WAR

 @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");
}

hapus Logger.getLogger(TodoService.class);produser yang akan digunakan untuk membuat 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();
    }