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