WELD-001408: Enjeksiyon noktasında @Default niteleyicileriyle Logger türü için tatmin edilmeyen bağımlılıklar [BackedAnnotatedField] @Inject

Aug 19 2020

Arquillian ile bir JavaEE8 uygulamasını test ederken bu sorunu yaşıyorum: WELD-001408: Enjeksiyon noktasında @ Default niteleyicileriyle Logger türü için tatminsiz bağımlılıklar [BackedAnnotatedField] @Inject private academy.learnprogramming.services.TodoService.LOG

Enjekte edilen EntityManager için aynı hatayı görüyorum

Bunlar benim derslerim:

TodoService.class (test etmem gereken sınıf)

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 (Test için kullanılan sınıf)

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'ya 3. taraf kitaplıkları eklemek için kullanılan sınıf)

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

Etrafı araştırırken, olası sorunların şunlar olabileceğini anladım:

  1. fasulye.xml, bean-discovery-mode = "all" koymazsanız sorun yaratabilir, çünkü açıklamalı olmayan çekirdekleri taramaz, ancak fasulye.xml dosyamda bean-discovery-mode = "all"
  2. TodoService sınıfına enjekte edilen Logger ve EntityManager bir Producer'a sahip olamazdı, ancak benim Producers sınıfım var
  3. TodoService, TodoServiceTest ve Producers sınıfları için Logger sınıfının içe aktarılması sırasında insanlar hata yapabilirler, örneğin bir sınıfta org.apache.log4j.Logger ve başka bir sınıfta java util.logging.Logger olabilir, ancak tüm sınıfları içe aktarım var org.apache.log4j.Logger

@Inject açıklamasını kaldırırsam ve günlükçüyü sınıflardan kullanırsam çalışır.

Başka ne deneyebilirim? Zaman ayırdığınız için çok teşekkür ederim.

Yanıtlar

LuisGalaz Aug 19 2020 at 19:21

WAR dosyası kullanıyorsanız WebArchive'ı kullanmayı deneyin

 @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);üreticiyi kaldırın, kaydediciyi somutlaştıracak.

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