jpacdihelidon

Helidon MP EntityManager always return NULL


I am facing a NullPointerException when trying to use EntityManager in my Helidon MicroProfile project. The exception occurs because the EntityManager is null when I attempt to create a query. The error message is:

java.lang.NullPointerException: Cannot invoke "jakarta.persistence.EntityManager.createQuery(String, java.lang.Class)" because "this.entityManager" is null

This happens in the method getDataBaseData() of my DataBaseService class. I am using the @PersistenceContext annotation to inject the EntityManager, but it seems that the injection is not working as expected.

I am using Helidon MP, and I have configured the persistence.xml for Derby as the database.

here is ressources/META-INF/beans.xml:

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="https://jakarta.ee/xml/ns/jakartaee"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xsi:schemaLocation="https://jakarta.ee/xml/ns/jakartaee https://jakarta.ee/xml/ns/jakartaee/beans_4_0.xsd"
       version="4.0"
       bean-discovery-mode="annotated">
</beans>

ressources/META-INF/persistence.xml :

<persistence xmlns="https://jakarta.ee/xml/ns/persistence"
             xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
             xsi:schemaLocation="https://jakarta.ee/xml/ns/persistence
                                 https://jakarta.ee/xml/ns/persistence/persistence_3_1.xsd"
             version="3.1">
    <persistence-unit name="explanationsDbPU" transaction-type="JTA">
        <description> explanation database persistence unit </description>
        <jta-data-source>explanationsDS</jta-data-source>
        <class>fr.uge.xplain.Explanation</class>
        <properties>
            <property name="hibernate.dialect" value="org.hibernate.dialect.DerbyTenSevenDialect"/>
            <property name="hibernate.hbm2ddl.auto" value="update"/>
            <property name="hibernate.show_sql" value="true"/>
            <property name="hibernate.format_sql" value="true"/>
        </properties>
    </persistence-unit>
</persistence>

ressources/application.yaml :

javax:
  sql:
    DataSource:
      explanationsDS:
        driver: org.apache.derby.jdbc.EmbeddedDataSource
        url: jdbc:derby:memory:explanations;create=true
        user: admin
        password: admin

Explanation (the Entity) :

package fr.uge.xplain;

import jakarta.persistence.*;
import java.time.LocalDate;

@Entity
public class Explanation {

    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)  // Option pour une meilleure compatibilité
    private int id;

    @Column(name = "source_code", length = 255)
    private String sourceCode;

    @Column(name = "explanations", length = 255)
    private String explanations;

    @Column(name = "creation_date")
    private LocalDate creationDate;

    // Getters
    public int getId() {
        return id;
    }

    public String getSourceCode() {
        return sourceCode;
    }

    public String getExplanations() {
        return explanations;
    }

    public LocalDate getCreationDate() {
        return creationDate;
    }

    // Setters
    public void setSourceCode(String sourceCode) {
        this.sourceCode = sourceCode;
    }

    public void setId(int id) {
        this.id = id;
    }

    public void setExplanations(String explanations) {
        this.explanations = explanations;
    }

    public void setCreationDate(LocalDate creationDate) {
        this.creationDate = creationDate;
    }
}

DataBaseService.java :

package fr.uge.xplain;

import jakarta.annotation.PostConstruct;
import jakarta.enterprise.context.ApplicationScoped;
import jakarta.inject.Inject;
import jakarta.persistence.EntityManager;
import jakarta.persistence.PersistenceContext;
import jakarta.transaction.Transactional;
import java.util.List;

@ApplicationScoped
public class DataBaseService {

    @PersistenceContext(unitName = "explanationsDbPU")
    private EntityManager entityManager;

    public List<Explanation> getDataBaseData() {
        return entityManager.createQuery("SELECT e FROM Explanation e ORDER BY e.creationDate DESC", Explanation.class)
                .getResultList();
    }

    @Transactional
    public void setDataBaseData(Explanation explanation) {
        entityManager.persist(explanation);
    }
}

DataBaseResource (POST & GET for fornt-end) :

package fr.uge.xplain;

import jakarta.inject.Inject;
import jakarta.persistence.PersistenceContext;
import jakarta.ws.rs.GET;
import jakarta.ws.rs.POST;
import jakarta.ws.rs.Path;
import jakarta.ws.rs.Produces;
import jakarta.ws.rs.Consumes;
import jakarta.ws.rs.core.MediaType;
import jakarta.ws.rs.core.Response;
import java.util.List;
import java.util.Map;

@Path("/database")
public class DataBaseResource {

    @Inject
    private DataBaseService dataBaseService;

    @GET
    @Produces(MediaType.APPLICATION_JSON)
    public Response getDatabaseData() {
        List<Explanation> data = dataBaseService.getDataBaseData();
        if (data.isEmpty()) {
            return Response.status(Response.Status.NOT_FOUND)
                    .entity(Map.of("message", "No data found"))
                    .build();
        }
        return Response.ok(data).build();
    }

    @POST
    @Consumes(MediaType.APPLICATION_JSON)
    public Response addData(Explanation explanation) {
        dataBaseService.setDataBaseData(explanation);
        return Response.status(Response.Status.CREATED).build();
    }
}

Solution

  • Update : I juste forgot to include JPA dependency ! As specified in Helidon MP documentation : Helidon MP documentation

    <dependency>
         <groupId>io.helidon.integrations.cdi</groupId>
         <artifactId>helidon-integrations-cdi-jpa</artifactId>
    </dependency>