Search code examples
javajax-rscdijpa-2.0java-ee-7

Java EE CDI Deployment Exception - WELD-001408: Unsatisfied dependencies for type EntityManager with qualifiers @Default


I'm fairly new to Java EE. I've searched long and hard but can't find a resolution to a problem that others have had. I've looked at other related posts on SO, and I've looked at JBoss and Oracle documentation as suggested by other posts, but I'm still not able to resolve my issue. I'm using Eclipse to develop a JAX-RS application that uses JPA to interact with MariaDB. I used the Maven webapp-jee7-liberty archetype to create the project, so I'm running it on a Liberty runtime. Here are my project facets:

enter image description here

Here's my project structure:

enter image description here

beans.xml file:

<?xml version="1.0" encoding="UTF-8"?>
<beans bean-discovery-mode="annotated"
  xmlns="http://xmlns.jcp.org/xml/ns/javaee"
  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/beans_1_1.xsd"/>

web.xml file:

<?xml version="1.0" encoding="UTF-8"?>
<web-app id="WebApp_ID" version="3.1" xmlns="http://xmlns.jcp.org/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd">
    <display-name>journal-task-mgr</display-name>
    <welcome-file-list>
        <welcome-file>index.html</welcome-file>
        <welcome-file>index.htm</welcome-file>
        <welcome-file>index.jsp</welcome-file>
        <welcome-file>default.html</welcome-file>
        <welcome-file>default.htm</welcome-file>
        <welcome-file>default.jsp</welcome-file>
    </welcome-file-list>
</web-app>

Here's my repository class:

package me.org.jtm.repository;

import java.util.List;

import javax.enterprise.context.RequestScoped;
import javax.inject.Inject;
import javax.persistence.EntityManager;
import javax.persistence.EntityTransaction;
import javax.persistence.TypedQuery;

import me.org.jtm.repository.bean.Task;

@RequestScoped
public class TaskRepositoryImpl implements TaskRepository {

    private EntityManager em;
    private EntityTransaction tx;

    @Inject
    public TaskRepositoryImpl(EntityManager em) {
        this.em = em;
        this.tx = em.getTransaction();
    }

    @Override
    public List<Task> get() {
        tx.begin();
        List<Task> resultList = em.createNamedQuery("AllTaskEntries", Task.class).getResultList();
        tx.commit();
        return resultList;
    }

    ...

}

I've created a producer to be able to use the @Inject annotation for EntityManager:

package me.org.jtm.repository;

import javax.enterprise.context.RequestScoped;
import javax.enterprise.inject.Produces;
import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;

public class EntityManagerProducer {
    @PersistenceContext
    private EntityManager em;

    @Produces
    @RequestScoped
    public EntityManager entityManager() {
        return em;
    }
}

Here's my persistence.xml:

<?xml version="1.0" encoding="UTF-8"?>
<persistence version="1.0" xmlns="http://java.sun.com/xml/ns/persistence" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/persistence http://java.sun.com/xml/ns/persistence/persistence_1_0.xsd">
    <persistence-unit name="journal-task-mgr" transaction-type="JTA">
        <jta-data-source>jdbc/JournalTaskMgrMariaDb</jta-data-source>
        <class>me.org.jtm.repository.bean.Journal</class>
        <class>me.org.jtm.repository.bean.Task</class>
        <class>me.org.jtm.repository.bean.User</class>
    </persistence-unit>
</persistence>

Yet I get this error on startup:

org.jboss.weld.exceptions.DeploymentException: WELD-001408: Unsatisfied dependencies for type EntityManager with qualifiers @Default at injection point [BackedAnnotatedParameter] Parameter 1 of [BackedAnnotatedConstructor] @Inject public me.org.jtm.repository.TaskRepositoryImpl(EntityManager) at me.org.jtm.repository.TaskRepositoryImpl.(TaskRepositoryImpl.java:0)

at org.jboss.weld.bootstrap.Validator.validateInjectionPointForDeploymentProblems(Validator.java:378) at org.jboss.weld.bootstrap.Validator.validateInjectionPoint(Validator.java:290) at org.jboss.weld.bootstrap.Validator.validateGeneralBean(Validator.java:143) at org.jboss.weld.bootstrap.Validator.validateRIBean(Validator.java:164) at org.jboss.weld.bootstrap.Validator.validateBean(Validator.java:526) at org.jboss.weld.bootstrap.ConcurrentValidator$1.doWork(ConcurrentValidator.java:64) at org.jboss.weld.bootstrap.ConcurrentValidator$1.doWork(ConcurrentValidator.java:62) at org.jboss.weld.executor.IterativeWorkerTaskFactory$1.call(IterativeWorkerTaskFactory.java:62) at org.jboss.weld.executor.IterativeWorkerTaskFactory$1.call(IterativeWorkerTaskFactory.java:55) at java.util.concurrent.FutureTask.run(Unknown Source) at java.util.concurrent.ThreadPoolExecutor.runWorker(Unknown Source) at java.util.concurrent.ThreadPoolExecutor$Worker.run(Unknown Source) at java.lang.Thread.run(Unknown Source)

Dependency injection seems to be working fine in my resource and service classes:

package me.org.jtm.resources;

import java.util.List;

import javax.enterprise.context.RequestScoped;
import javax.inject.Inject;
import javax.ws.rs.core.Response;
import javax.ws.rs.core.UriBuilder;
import javax.ws.rs.core.UriInfo;

import me.org.jtm.domain.TaskService;
import me.org.jtm.repository.bean.Task;

@RequestScoped
public class TaskResourceImpl implements TaskResource {
    private TaskService taskService;

    @Inject
    public TaskResourceImpl(TaskService taskService) {
        this.taskService = taskService;
    }

    @Override
    public Response get() {
        List<Task> tasks = taskService.getAll();    
        return Response.ok(tasks).build();
    }

    ...

}

From what I've seen in other posts and elsewhere it seems that I have what I need in place for this to work, but I keep getting this exception. What am I missing?


Solution

  • Since the bean-discovery-mode is set to "annotated" in beans.xml, CDI will not consider the EntityManagerProducer to be a Bean and will not activate the producer method.

    Add a scope on the EntityManagerProducer. @ApplicationScoped is probably good for this case.