WELD-001408: Dépendances non satisfaites pour le type Logger avec des qualificatifs @Default au point d'injection [BackedAnnotatedField] @Inject

Aug 19 2020

Je rencontre ce problème lors du test d'une application JavaEE8 avec Arquillian: WELD-001408: Dépendances non satisfaites pour le type Logger avec des qualificatifs @Default au point d'injection [BackedAnnotatedField] @Inject private academy.learnprogramming.services.TodoService.LOG

J'ai la même erreur pour le EntityManager injecté

Ce sont mes cours:

TodoService.class (la classe que je dois tester)

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 (La classe utilisée pour les tests)

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 (Classe utilisée pour ajouter des bibliothèques tierces à 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;
    }
}

En cherchant, j'ai compris que les problèmes possibles pouvaient être:

  1. beans.xml pourrait poser des problèmes si vous ne mettez pas bean-discovery-mode = "all", car il ne recherchera pas les beans non annotés, mais mon fichier beans.xml a bean-discovery-mode = "all"
  2. Le Logger et l'EntityManager injectés dans la classe TodoService ne pouvaient pas avoir de Producer, mais j'ai la classe Producers
  3. Les gens peuvent faire des erreurs lors de l'importation de la classe Logger pour les classes TodoService, TodoServiceTest et Producers, ayant par exemple import org.apache.log4j.Logger dans une classe et java util.logging.Logger pour une autre, mais j'ai toutes les classes avec import org.apache.log4j.Logger

Si je supprime l'annotation @Inject et que j'utilise le logger des classes, cela fonctionne.

Que puis-je essayer d'autre? Merci beaucoup pour votre temps.

Réponses

LuisGalaz Aug 19 2020 at 19:21

Essayez d'utiliser WebArchive si vous utilisez un fichier 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");
}

supprimer le Logger.getLogger(TodoService.class);producteur qu'il va instancier de l'enregistreur.

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