0
votes

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?

1
Can you please try adding a scope (@ApplicationScoped would do) to your EntityManagerProducer? The reason I am suggesting this is because you have specified bean-discovery-mode="annotated".Nikos Paraskevopoulos
That did it! Took care of the DeploymentException error. Please provide it as an official answer so I can mark as answered. However, I came across another issue where the reference to the service object in the resource class was null. I moved the Inject annotation from the constructor to the field, added a no-argument constructor, and it resolved that problem. Interestingly enough I did not have to do that in the service class where I have the Inject annotation over the constructor that takes in a reference to the repository. Do you happen to know why this is the case?dotnetesse
Ohhh, I have had the same problem with JAX-RS (Resteasy on Thorntail), it does not understand constructor injection! I surrendered and now I am using field injection in my resources :) I will add the answer shortly...Nikos Paraskevopoulos

1 Answers

1
votes

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.