I use payara5 (with EclipseLink). It looks like I can't use subclasses with a JPA converter. With wildfly (and Hibernate), it works fine.
The problem comes from this query :
#Override
public List<Employee> findByStatus(Employee.Status status) {
return em.createNamedQuery("Employee.findByStatus", Employee.class)
.setParameter("status", status)
.getResultList();
}
It looks like, if the converter is a subclass, EclipseLink is not able to convert the parameter "status" into a string.
Without the subclass, it works just fine. Is it a bug in EclipseLink ?
persistence.xml :
<?xml version="1.0" encoding="UTF-8"?>
<persistence version="2.2"
xmlns="http://xmlns.jcp.org/xml/ns/persistence"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/persistence
http://xmlns.jcp.org/xml/ns/persistence/persistence_2_2.xsd"
>
<persistence-unit name="primary" transaction-type="JTA">
<!--jta-data-source>java:/TestDS</jta-data-source-->
<jta-data-source>jdbc/TestDS</jta-data-source>
<class>fjp.converter.entity.Employee</class>
<class>fjp.converter.entity.converter.StatusConverter</class>
<class>fjp.converter.entity.converter.StatusConverterSubClass</class>
<exclude-unlisted-classes>true</exclude-unlisted-classes>
<shared-cache-mode>ENABLE_SELECTIVE</shared-cache-mode>
<properties>
<property name="javax.persistence.schema-generation.database.action" value="drop-and-create" />
<property name="eclipselink.logging.level.sql" value="FINE"/>
<property name="eclipselink.logging.parameters" value="true"/>
<property name="hibernate.show_sql" value="true"/>
</properties>
</persistence-unit>
</persistence>
Entity :
package fjp.converter.entity;
import java.io.Serializable;
import java.util.Map;
import java.util.function.Function;
import java.util.stream.Collectors;
import java.util.stream.Stream;
import javax.persistence.Convert;
import javax.persistence.Entity;
import javax.persistence.Id;
import javax.persistence.NamedQuery;
#NamedQuery(name="Employee.findByStatus", query="select e from Employee e where e.status=:status")
#Entity
public class Employee implements Serializable{
private static final long serialVersionUID = 1L;
public enum Status implements HasCode {
SENIOR("SENIOR"),
JUNIOR("JUNIOR");
private String code;
private Status(String s) {
this.code = s;
}
#Override
public String getCode() {
return this.code;
}
private static Map<String, Status> map = Stream.of(values()).collect(Collectors.toMap(Status::getCode, Function.identity()));
public static Status fromString(String code) {
return map.get(code);
}
}
#Id
private long id;
// #Convert(converter = fjp.converter.entity.converter.StatusConverter.class)
#Convert(converter = fjp.converter.entity.converter.StatusConverterSubClass.class)
private Status status;
public long getId() {
return id;
}
public void setId(long id) {
this.id = id;
}
public Status getStatus() {
return this.status;
}
public void setStatus(Status s) {
this.status = s;
}
#Override
public String toString() {
return String.format("id=%d, status=%s", id, status == null ? null : status.getCode());
}
#Override
public boolean equals(Object o) {
if(o == this) return true;
if(!(o instanceof Employee)) return false;
Employee e = (Employee) o;
return e.getId() == getId();
}
#Override
public int hashCode() {
return Long.hashCode(getId());
}
}
Interface HasCode :
package fjp.converter.entity;
public interface HasCode {
String getCode();
}
StatusConverter :
package fjp.converter.entity.converter;
import javax.persistence.Converter;
import javax.persistence.AttributeConverter;
import fjp.converter.entity.Employee.Status;
#Converter
public class StatusConverter implements AttributeConverter<Status, String> {
#Override
public String convertToDatabaseColumn(Status e) {
return e == null ? null : e.getCode();
}
#Override
public Status convertToEntityAttribute(String s) {
if(s == null) return null;
switch(s) {
case "SENIOR": return Status.SENIOR;
case "JUNIOR": return Status.JUNIOR;
default: return null;
}
}
}
StatusConverterSubClass :
package fjp.converter.entity.converter;
import javax.persistence.Converter;
import fjp.converter.entity.Employee.Status;
#Converter
public class StatusConverterSubClass extends EnumCodeConverter<Status> {
public StatusConverterSubClass() {
super(Status::fromString);
}
}
Converter base class :
package fjp.converter.entity.converter;
import java.util.function.Function;
import javax.persistence.AttributeConverter;
import fjp.converter.entity.HasCode;
public class EnumCodeConverter<T extends HasCode> implements AttributeConverter<T, String> {
private final Function<String, ? extends T> fromString;
protected EnumCodeConverter(Function<String, ? extends T> fromString) {
this.fromString = fromString;
}
#Override
public String convertToDatabaseColumn(T attribute) {
return attribute == null ? null : attribute.getCode();
}
#Override
public T convertToEntityAttribute(String code) {
if(code == null) return null;
T r = this.fromString.apply(code);
if(r == null) {
throw new IllegalArgumentException(String.format("unknow code: '%s', '%s'", code, this.getClass()));
}
return r;
}
}
dao :
package fjp.converter.dao;
import java.util.List;
import fjp.converter.entity.Employee;
public interface EmployeeDAO {
public List<Employee> findByStatus(Employee.Status status);
}
daoimpl :
package fjp.converter.dao;
import java.util.List;
import javax.ejb.Stateless;
import javax.ejb.Local;
import javax.persistence.PersistenceContext;
import javax.persistence.EntityManager;
import fjp.converter.entity.Employee;
#Local(EmployeeDAO.class)
#Stateless
public class EmployeeDAOImpl implements EmployeeDAO {
#PersistenceContext
private EntityManager em;
#Override
public List<Employee> findByStatus(Employee.Status status) {
return em.createNamedQuery("Employee.findByStatus", Employee.class)
.setParameter("status", status)
.getResultList();
}
}
Test servlet :
package fjp.converter.servlet;
import javax.inject.Inject;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import fjp.converter.dao.EmployeeDAO;
import fjp.converter.entity.Employee.Status;
#WebServlet("/test")
public class Test extends HttpServlet {
private static final long serialVersionUID = 1L;
#Inject
private EmployeeDAO dao;
#Override
protected void doGet(HttpServletRequest request, HttpServletResponse response) {
Status status = Status.SENIOR;
var list = dao.findByStatus(status);
System.out.println("FJP: " + list.size());
}
}
And payara logs :
[2021-11-11T11:42:56.565+0100] [Payara 5.2021.3] [CONFIG] [] [org.eclipse.persistence.default] [tid: _ThreadID=185 _ThreadName=admin-thread-pool::admin-listener(11)] [timeMillis: 1636627376565] [levelValue: 700] [[
The default table generator could not locate or convert a java type (class fjp.converter.entity.Employee$Status) into a database type for database field (EMPLOYEE.STATUS). The generator uses "java.lang.String" as default java type for the field.]]
[2021-11-11T11:43:21.771+0100] [Payara 5.2021.3] [AVERTISSEMENT] [AS-EJB-00056] [javax.enterprise.ejb.container] [tid: _ThreadID=76 _ThreadName=http-thread-pool::http-listener-1(5)] [timeMillis: 1636627401771] [levelValue: 900] [[
A system exception occurred during an invocation on EJB EmployeeDAOImpl, method: public java.util.List fjp.converter.dao.EmployeeDAOImpl.findByStatus(fjp.converter.entity.Employee$Status)]]
[2021-11-11T11:43:21.772+0100] [Payara 5.2021.3] [AVERTISSEMENT] [] [javax.enterprise.ejb.container] [tid: _ThreadID=76 _ThreadName=http-thread-pool::http-listener-1(5)] [timeMillis: 1636627401772] [levelValue: 900] [[
javax.ejb.EJBException: Exception [EclipseLink-3002] (Eclipse Persistence Services - 2.7.7.payara-p3): org.eclipse.persistence.exceptions.ConversionException
Exception Description: The object [SENIOR], of class [class java.lang.String], from mapping [org.eclipse.persistence.mappings.DirectToFieldMapping[status-->EMPLOYEE.STATUS]] with descriptor [RelationalDescriptor(fjp.converter.entity.Employee --> [DatabaseTable(EMPLOYEE)])], could not be converted to [class fjp.converter.entity.Employee$Status].
at com.sun.ejb.containers.EJBContainerTransactionManager.processSystemException(EJBContainerTransactionManager.java:723)
at com.sun.ejb.containers.EJBContainerTransactionManager.completeNewTx(EJBContainerTransactionManager.java:652)
at com.sun.ejb.containers.EJBContainerTransactionManager.postInvokeTx(EJBContainerTransactionManager.java:482)
at com.sun.ejb.containers.BaseContainer.postInvokeTx(BaseContainer.java:4592)
at com.sun.ejb.containers.BaseContainer.postInvoke(BaseContainer.java:2125)
at com.sun.ejb.containers.BaseContainer.postInvoke(BaseContainer.java:2095)
at com.sun.ejb.containers.EJBLocalObjectInvocationHandler.invoke(EJBLocalObjectInvocationHandler.java:220)
at com.sun.ejb.containers.EJBLocalObjectInvocationHandlerDelegate.invoke(EJBLocalObjectInvocationHandlerDelegate.java:90)
at com.sun.proxy.$Proxy392.findByStatus(Unknown Source)
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.base/java.lang.reflect.Method.invoke(Method.java:566)
at org.jboss.weld.util.reflection.Reflections.invokeAndUnwrap(Reflections.java:410)
at org.jboss.weld.module.ejb.EnterpriseBeanProxyMethodHandler.invoke(EnterpriseBeanProxyMethodHandler.java:134)
at org.jboss.weld.bean.proxy.EnterpriseTargetBeanInstance.invoke(EnterpriseTargetBeanInstance.java:56)
at org.jboss.weld.module.ejb.InjectionPointPropagatingEnterpriseTargetBeanInstance.invoke(InjectionPointPropagatingEnterpriseTargetBeanInstance.java:68)
at org.jboss.weld.bean.proxy.ProxyMethodHandler.invoke(ProxyMethodHandler.java:106)
at fjp.converter.dao.EmployeeDAO$1921730137$Proxy$_$$_Weld$EnterpriseProxy$.findByStatus(Unknown Source)
at fjp.converter.servlet.Test.doGet(Test.java:36)
logs with FINEST level
[2021-11-13T09:19:12.784+0100] [Payara 5.2021.3] [LE PLUS PRÉCIS] [] [org.eclipse.persistence.default] [tid: _ThreadID=173 _ThreadName=admin-thread-pool::admin-listener(6)] [timeMillis: 1636791552784] [levelValue: 300] [[
Missing class details for [fjp/converter/entity/converter/StatusConverterSubClass].]]
[2021-11-13T09:19:12.784+0100] [Payara 5.2021.3] [LE PLUS PRÉCIS] [] [org.eclipse.persistence.default] [tid: _ThreadID=173 _ThreadName=admin-thread-pool::admin-listener(6)] [timeMillis: 1636791552784] [levelValue: 300] [[
Using existing class bytes for [fjp/converter/entity/converter/StatusConverterSubClass].]]
[2021-11-13T09:19:12.785+0100] [Payara 5.2021.3] [LE PLUS PRÉCIS] [] [org.eclipse.persistence.default] [tid: _ThreadID=173 _ThreadName=admin-thread-pool::admin-listener(6)] [timeMillis: 1636791552785] [levelValue: 300] [[
Missing class details for [fjp/converter/entity/converter/EnumCodeConverter].]]
[2021-11-13T09:19:12.785+0100] [Payara 5.2021.3] [LE PLUS PRÉCIS] [] [org.eclipse.persistence.default] [tid: _ThreadID=173 _ThreadName=admin-thread-pool::admin-listener(6)] [timeMillis: 1636791552785] [levelValue: 300] [[
Using existing class bytes for [fjp/converter/entity/converter/EnumCodeConverter].]]
[2021-11-13T09:19:12.790+0100] [Payara 5.2021.3] [INFOS] [] [org.eclipse.persistence.session./file:/home/frederic/payara5/glassfish/domains/domain1/applications/converter-1.0/WEB-INF/classes/_primary] [tid: _ThreadID=173 _ThreadName=admin-thread-pool::admin-listener(6)] [timeMillis: 1636791552790] [levelValue: 800] [[
EclipseLink, version: Eclipse Persistence Services - 2.7.7.payara-p3]]
[2021-11-13T09:19:12.809+0100] [Payara 5.2021.3] [CONFIG] [] [org.eclipse.persistence.default] [tid: _ThreadID=173 _ThreadName=admin-thread-pool::admin-listener(6)] [timeMillis: 1636791552809] [levelValue: 700] [[
The default table generator could not locate or convert a java type (class fjp.converter.entity.Employee$Status) into a database type for database field (EMPLOYEE.STATUS). The generator uses "java.lang.String" as default java type for the field.]]
It's definitely a bug in EclipseLink.
Fortunately, there is a workaround. The AttributeConverter interface must be added to the subclass. It's totally useless as the superclass already implements it.
Related
I was working on JSF product crud application using the Java Persistence API with eclipse -link 2.5 and i was wondering why JPA is not recognizing my entities.
here's my entity class:
package Models;
import java.io.Serializable;
import javax.persistence.*;
#Entity
#Table(name = "Article")
#NamedQuery(name = "find all articles", query = "SELECT ar FROM ArticleEntity ar")
public class ArticleEntity implements Serializable{
/**
*
*/
private static final long serialVersionUID = 1L;
#Id
private int code;
private String designation;
private float prixHT;
private float prixTTC;
private float marge;
private float remise;
private float tva;
public int getCode() {
return code;
}
public String getDesignation() {
return designation;
}
public float getMarge() {
return marge;
}
public float getPrixHT() {
return prixHT;
}
public float getPrixTTC() {
return prixTTC;
}
public float getRemise() {
return remise;
}
public float getTva() {
return tva;
}
public void setCode(int code) {
this.code = code;
}
public void setDesignation(String designation) {
this.designation = designation;
}
public void setMarge(float marge) {
this.marge = marge;
}
public void setPrixHT(float prixHT) {
this.prixHT = prixHT;
}
public void setPrixTTC(float prixTTC) {
this.prixTTC = prixTTC;
}
public void setRemise(float remise) {
this.remise = remise;
}
public void setTva(float tva) {
this.tva = tva;
}
}
and this is the entity manager of my class:
package DAO;
import java.util.*;
import javax.persistence.*;
import Models.ArticleEntity;
public class ArticleORM {
private EntityManagerFactory articleMnagerFactory = Persistence.createEntityManagerFactory("JsfDatabase");
private EntityManager articleManager;
public ArticleORM() {
this.articleManager = this.articleMnagerFactory.createEntityManager();
}
public List<ArticleEntity> findAll(){
this.articleManager.getTransaction().begin();
Query query = this.articleManager.createQuery("SELECT ar FROM ArticleEntity ar");
return (List<ArticleEntity>) query.getResultList();
}
}
and this is my persistence.xml file:
<persistence version="2.1" xmlns="http://xmlns.jcp.org/xml/ns/persistence" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/persistence http://xmlns.jcp.org/xml/ns/persistence/persistence_2_1.xsd">
<persistence-unit name="JsfDatabase" transaction-type="RESOURCE_LOCAL">
<class>Models.ArticleEntity</class>
<properties>
<property name="javax.persistence.jdbc.url" value="jdbc:mysql://localhost:3306/JsfDatabase"/>
<property name="javax.persistence.jdbc.user" value="root"/>
<property name="javax.persistence.jdbc.password" value=""/>
<property name="javax.persistence.jdbc.driver" value="com.mysql.jdbc.Driver"/>
</properties>
</persistence-unit>
</persistence>
this is the error thrown in the console
SEVERE: Servlet.service() for servlet [Faces Servlet] in context with path [/AppJSF] threw exception [An exception occurred while creating a query in EntityManager:
Exception Description: Problem compiling [SELECT ar FROM ArticleEntity ar].
[15, 28] The abstract schema type 'ArticleEntity' is unknown.] with root cause
Local Exception Stack:
Exception [EclipseLink-0] (Eclipse Persistence Services - 2.7.6.v20200131-b7c997804f): org.eclipse.persistence.exceptions.JPQLException
Exception Description: Problem compiling [SELECT ar FROM ArticleEntity ar].
[15, 28] The abstract schema type 'ArticleEntity' is unknown.
at org.eclipse.persistence.internal.jpa.jpql.HermesParser.buildException(HermesParser.java:157)
at org.eclipse.persistence.internal.jpa.jpql.HermesParser.validate(HermesParser.java:349)
at org.eclipse.persistence.internal.jpa.jpql.HermesParser.populateQueryImp(HermesParser.java:280)
at org.eclipse.persistence.internal.jpa.jpql.HermesParser.buildQuery(HermesParser.java:165)
at org.eclipse.persistence.internal.jpa.EJBQueryImpl.buildEJBQLDatabaseQuery(EJBQueryImpl.java:142)
at org.eclipse.persistence.internal.jpa.EJBQueryImpl.buildEJBQLDatabaseQuery(EJBQueryImpl.java:118)
at org.eclipse.persistence.internal.jpa.EJBQueryImpl.<init>(EJBQueryImpl.java:104)
at org.eclipse.persistence.internal.jpa.EJBQueryImpl.<init>(EJBQueryImpl.java:88)
at org.eclipse.persistence.internal.jpa.EntityManagerImpl.createQuery(EntityManagerImpl.java:1749)
at DAO.ArticleORM.findAll(ArticleORM.java:17)
at Beans.MBArticle.selectAll(MBArticle.java:65)
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:77)
at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.base/java.lang.reflect.Method.invoke(Method.java:568)
at javax.el.BeanELResolver.invoke(BeanELResolver.java:147)
at javax.el.CompositeELResolver.invoke(CompositeELResolver.java:79)
at org.apache.el.parser.AstValue.getValue(AstValue.java:158)
at org.apache.el.ValueExpressionImpl.getValue(ValueExpressionImpl.java:189)
at com.sun.faces.facelets.el.TagValueExpression.getValue(TagValueExpression.java:109)
at javax.faces.component.ComponentStateHelper.eval(ComponentStateHelper.java:194)
at javax.faces.component.ComponentStateHelper.eval(ComponentStateHelper.java:182)
at javax.faces.component.UIData.getValue(UIData.java:731)
at org.primefaces.component.api.UIData.getDataModel(UIData.java:768)
at javax.faces.component.UIData.getRowCount(UIData.java:356)
at org.primefaces.component.datatable.DataTableRenderer.encodeTbody(DataTableRenderer.java:1085)
at org.primefaces.component.datatable.DataTableRenderer.encodeTbody(DataTableRenderer.java:1064)
at org.primefaces.component.datatable.DataTableRenderer.encodeRegularTable(DataTableRenderer.java:426)
at org.primefaces.component.datatable.DataTableRenderer.encodeMarkup(DataTableRenderer.java:361)
at org.primefaces.component.datatable.DataTableRenderer.encodeEnd(DataTableRenderer.java:94)
at javax.faces.component.UIComponentBase.encodeEnd(UIComponentBase.java:875)
at javax.faces.component.UIComponent.encodeAll(UIComponent.java:1764)
at javax.faces.render.Renderer.encodeChildren(Renderer.java:168)
at javax.faces.component.UIComponentBase.encodeChildren(UIComponentBase.java:845)
at javax.faces.component.UIComponent.encodeAll(UIComponent.java:1757)
at javax.faces.component.UIComponent.encodeAll(UIComponent.java:1760)
at javax.faces.component.UIComponent.encodeAll(UIComponent.java:1760)
at com.sun.faces.application.view.FaceletViewHandlingStrategy.renderView(FaceletViewHandlingStrategy.java:399)
at com.sun.faces.application.view.MultiViewHandler.renderView(MultiViewHandler.java:131)
at com.sun.faces.lifecycle.RenderResponsePhase.execute(RenderResponsePhase.java:121)
at com.sun.faces.lifecycle.Phase.doPhase(Phase.java:101)
at com.sun.faces.lifecycle.LifecycleImpl.render(LifecycleImpl.java:139)
at javax.faces.webapp.FacesServlet.service(FacesServlet.java:594)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:227)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:162)
at org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:53)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:189)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:162)
at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:197)
at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:97)
at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:541)
at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:135)
at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:92)
at org.apache.catalina.valves.AbstractAccessLogValve.invoke(AbstractAccessLogValve.java:687)
at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:78)
at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:360)
at org.apache.coyote.http11.Http11Processor.service(Http11Processor.java:399)
at org.apache.coyote.AbstractProcessorLight.process(AbstractProcessorLight.java:65)
at org.apache.coyote.AbstractProtocol$ConnectionHandler.process(AbstractProtocol.java:889)
at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.doRun(NioEndpoint.java:1743)
at org.apache.tomcat.util.net.SocketProcessorBase.run(SocketProcessorBase.java:49)
at org.apache.tomcat.util.threads.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1191)
at org.apache.tomcat.util.threads.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:659)
at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61)
at java.base/java.lang.Thread.run(Thread.java:833) ```
I wanted to try a simple test case with a converter. Unfortunately it doesn't work with payara 5. It works fine with Wildfly 20.0.1. Database is H2.
pom.xml
<project
xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0
http://maven.apache.org/xsd/maven-4.0.0.xsd"
>
<modelVersion>4.0.0</modelVersion>
<groupId>fjp</groupId>
<artifactId>converter</artifactId>
<version>1.0</version>
<packaging>war</packaging>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
<maven.compiler.source>11</maven.compiler.source>
<maven.compiler.target>11</maven.compiler.target>
<failOnMissingWebXml>false</failOnMissingWebXml>
</properties>
<dependencies>
<dependency>
<groupId>jakarta.platform</groupId>
<artifactId>jakarta.jakartaee-api</artifactId>
<version>8.0.0</version>
<scope>provided</scope>
</dependency>
</dependencies>
</project>
persistence.xml
<?xml version="1.0" encoding="UTF-8"?>
<persistence version="2.2"
xmlns="http://xmlns.jcp.org/xml/ns/persistence"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/persistence
http://xmlns.jcp.org/xml/ns/persistence/persistence_2_2.xsd"
>
<persistence-unit name="primary" transaction-type="JTA">
<!--jta-data-source>java:/TestDS</jta-data-source-->
<jta-data-source>jdbc/TestDS</jta-data-source>
<class>fjp.converter.entity.Employee</class>
<class>fjp.converter.entity.converter.StatusConverter</class>
<exclude-unlisted-classes>true</exclude-unlisted-classes>
<properties>
<property name="javax.persistence.schema-generation.database.action" value="drop-and-create" />
<property name="eclipselink.logging.level.sql" value="FINE"/>
<property name="eclipselink.logging.parameters" value="true"/>
<property name="hibernate.show_sql" value="true"/>
</properties>
</persistence-unit>
</persistence>
DAO :
package fjp.converter.dao;
import java.util.List;
import fjp.converter.entity.Employee;
public interface EmployeeDAO {
public Employee find(long i);
public void create(Employee e);
public void delete(Employee e);
public void delete(long i);
public List<Employee> findByStatus(Employee.Status status);
}
DAOImpl
package fjp.converter.dao;
import java.util.List;
import javax.ejb.Stateless;
import javax.persistence.PersistenceContext;
import javax.persistence.EntityManager;
import fjp.converter.entity.Employee;
#Stateless
public class EmployeeDAOImpl implements EmployeeDAO {
#PersistenceContext
private EntityManager em;
public Employee find(long i) {
return em.find(Employee.class, i);
}
#Override
public void create(Employee e) {
em.persist(e);
}
#Override
public void delete(long i) {
var e = this.find(i);
if(e != null) em.remove(e);
}
#Override
public void delete(Employee e) {
if(e == null) return;
delete(e.getId());
}
#Override
public List<Employee> findByStatus(Employee.Status status) {
return em.createNamedQuery("Employee.findByStatus", Employee.class)
.setParameter("status", status)
.getResultList();
}
}
Entity :
package fjp.converter.entity;
import javax.persistence.Entity;
import javax.persistence.Id;
import javax.persistence.AttributeConverter;
import javax.persistence.Convert;
import javax.persistence.NamedQuery;
import java.io.Serializable;
#NamedQuery(name="Employee.findByStatus", query="select e from Employee e where e.status=:status")
#Entity
public class Employee implements Serializable{
public enum Status {
SENIOR("SENIOR"),
JUNIOR("JUNIOR");
private String code;
private Status(String s) {
this.code = s;
}
public String getCode() {
return this.code;
}
}
#Id
private long id;
#Convert(converter = fjp.converter.entity.converter.StatusConverter.class)
private Status status;
public long getId() {
return id;
}
public void setId(long id) {
this.id = id;
}
public Status getStatus() {
return this.status;
}
public void setStatus(Status s) {
this.status = s;
}
#Override
public String toString() {
return String.format("id=%d, status=%s", id, status == null ? null : status.getCode());
}
}
Converter :
package fjp.converter.entity.converter;
import javax.persistence.Converter;
import javax.persistence.AttributeConverter;
import fjp.converter.entity.Employee.Status;
#Converter
public class StatusConverter implements AttributeConverter<Status, String> {
#Override
public String convertToDatabaseColumn(Status e) {
return e == null ? null : e.getCode();
}
#Override
public Status convertToEntityAttribute(String s) {
if(s == null) return null;
switch(s) {
case "SENIOR": return Status.SENIOR;
case "JUNIOR": return Status.JUNIOR;
default: return null;
}
}
}
Servlet
package fjp.converter.servlet;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpServlet;
import fjp.converter.dao.EmployeeDAO;
import fjp.converter.entity.Employee;
import fjp.converter.entity.Employee.Status;
import javax.inject.Inject;
#WebServlet("/test")
public class Test extends HttpServlet {
#Inject
private EmployeeDAO dao;
#Override
protected void doGet(HttpServletRequest request, HttpServletResponse response) {
Employee e = new Employee();
long id = 1;
dao.delete(id);
e.setId(id);
e.setStatus(Status.SENIOR);
dao.create(e);
id = 2;
dao.delete(id);
e.setId(id);
e.setStatus(Status.JUNIOR);
dao.create(e);
Status status = Status.SENIOR;
var list = dao.findByStatus(status);
for(var o : list) {
System.out.println(o);
if(o.getStatus() != status) {
System.out.println("ERROR !!!!!");
}
}
status = Status.JUNIOR;
list = dao.findByStatus(status);
for(var o : list) {
System.out.println(o);
if(o.getStatus() != status) {
System.out.println("ERROR !!!!!");
}
}
}
}
First time you ask the servlet you get the error message :
[2021-05-13T19:08:07.512+0200] [Payara 5.2021.3] [PRÉCIS] [] [org.eclipse.persistence.session./file:/home/frederic/payara5/glassfish/domains/domain1/applications/converter-1.0/WEB-INF/classes/_primary.sql] [tid: _ThreadID=76 _ThreadName=http-thread-pool::http-listener-1(5)] [timeMillis: 1620925687512] [levelValue: 500] [[
SELECT ID, STATUS FROM EMPLOYEE WHERE (STATUS = ?)
bind => [SENIOR]]]
[2021-05-13T19:08:07.514+0200] [Payara 5.2021.3] [INFOS] [] [] [tid: _ThreadID=76 _ThreadName=http-thread-pool::http-listener-1(5)] [timeMillis: 1620925687514] [levelValue: 800] [[
id=2, status=JUNIOR]]
[2021-05-13T19:08:07.514+0200] [Payara 5.2021.3] [INFOS] [] [] [tid: _ThreadID=76 _ThreadName=http-thread-pool::http-listener-1(5)] [timeMillis: 1620925687514] [levelValue: 800] [[
ERROR !!!!!]]
If you refresh the page : it blows !
Local Exception Stack:
Exception [EclipseLink-4002] (Eclipse Persistence Services - 2.7.7.payara-p3): org.eclipse.persistence.exceptions.DatabaseException
Internal Exception: org.h2.jdbc.JdbcSQLException: Violation dindex unique ou clé primaire: {0}
Unique index or primary key violation: {0}; SQL statement:
INSERT INTO EMPLOYEE (ID, STATUS) VALUES (?, ?) [23505-197]
The problem is you are editing an object after you call persist on it in ways not allowed by the JPA specification. What is happening here is you first create Employee e and set its ID and status (1, SENIOR), and call persist on this instance.
You then change the id and status values on e (2, JUNIOR) and again call persist on that same instance. Instance E though is already persisted, so this is ignored. When you query for status SENIOR, EclipseLink will query and find a row matching (1, SENIOR), but when it goes to the cache to look to see if it already has the data, it'll find your 'e' instance and so just return that. Your application logs an error because you've change the state of e to JUNIOR.
For proof of what is happening - try listing out what is in the database.
The solution is just to create a second Employee instance to represent the (2,JUNIOR) data.
Some differences in JPA providers are that EclipseLink will maintain 1st and 2nd level caches by default. This interferes with this situation because you are modifying objects in ways not allowed within the JPA spec, and EclipseLink remembers the data for longer than if there wasn't a cache. You are not allowed to modify primary keys within JPA.
It works if I add to persistence.xml :
<shared-cache-mode>ENABLE_SELECTIVE</shared-cache-mode>
So you can reuse the Employe but beware of second level cache.
This is really confusing, i have a rest service that works on some computers but refuses to work on others, no idea why.
The project is using Maven, EJB and glassfish
This is the rest service:
#Path("/")
public class ArticleService {
#EJB
private LocalArticle articleEJB;
#GET
#Produces(MediaType.APPLICATION_XML)
#Path("article/{articleId}")
public Article getArticleXML(#PathParam("articleId") int id) {
return articleEJB.getArticleById(id);
}
#GET
#Produces(MediaType.APPLICATION_JSON)
#Path("article/{articleId}")
public Article getArticleJSON(#PathParam("articleId") int id) {
return articleEJB.getArticleById(id);
}
}
The return value is a object, and if i instead return article.getName i get a 200 response, however if i try to return the entire object i get 500
Here is a rest management class(I'm not sure what this does, I followed an example from a book):
#ApplicationPath("rest")
public class ArticleMgmtRESTApplication extends ResourceConfig {
public ArticleMgmtRESTApplication () {
packages("se.alager.rest.ws.services");
}
}
}
Here is the Article in question:
#Entity
#NamedQueries({
#NamedQuery(name="Article.findAll", query="SELECT a FROM Article a"),
#NamedQuery(name="Article.findById", query="SELECT a FROM Article a WHERE a.id = :id")
})
#XmlRootElement
#XmlAccessorType(XmlAccessType.FIELD)
public class Article implements Serializable {
private static final long serialVersionUID = 1L;
#Id
#Column(name="id_article")
#XmlAttribute
private int id;
private int amount;
private String description;
private String name;
}
This exact code works flawlessly for mt friend, but I can't seem to get it to work, any ideas as to why?
Here is the Glassfish log for the error (ther was some 500 more lines of log, I hope this is relevant, I have no idea what I'm doing here)
[2016-10-20T16:31:44.140+0200] [glassfish 4.1]
[INFO] [] [org.jboss.weld.Bootstrap]
[tid: _ThreadID=142 _ThreadName=admin-listener(7)] [timeMillis: 1476973904140]
[levelValue: 800] [[
WELD-000119: Not generating any bean definitions from
org.glassfish.jersey.server.internal.inject.ParamConverters$CharacterProvider
because of underlying class loading error: Type [unknown] not found.
If this is unexpected, enable DEBUG logging to see the full error.]]
[2016-10-20T16:31:45.000+0200] [glassfish 4.1] [INFO] []
[org.glassfish.jersey.servlet.init.JerseyServletContainerInitializer]
[tid: _ThreadID=142 _ThreadName=admin-listener(7)] [timeMillis: 1476973905000]
[levelValue: 800] [[
Registering the Jersey servlet application, named
se.alager.rest.ws.ManagementRESTApplication,
at the servlet mapping /rest/*, with the Application class of the same name.]]
I'm newbie in EJB and jUnit, and I'm trying to do Embedded testing for the simple EJB-project that running by jBoss AS 7.1.1.Final.
I've written this test:
package com.staff.test.logic;
import java.io.File;
import javax.ejb.embeddable.EJBContainer;
import javax.naming.Context;
import javax.naming.NamingException;
import org.jboss.as.embedded.EmbeddedServerFactory;
import org.jboss.as.embedded.StandaloneServer;
import org.junit.Before;
import org.junit.Test;
import com.staff.main.logic.ProjectBean;
public class ProjectBeanTest {
private StandaloneServer server;
private static EJBContainer ec;
private static Context ctx;
#Before
public void initContainer() throws Exception {
String jbossHomeDir = System.getenv("JBOSS_HOME");
System.setProperty("jboss.home","C:/eclipse/jboss-as-7.1.1.Final");
assert jbossHomeDir != null;
server = EmbeddedServerFactory.create(new File(jbossHomeDir), System.getProperties(), System.getenv(), "org.jboss.logmanager");
server.start();
ctx=server.getContext();
}
// #After
// public static void closeContainer() throws Exception {
// if (ec != null) {
// ec.close();
// }
// }
#Test
public void test() throws NamingException {
ProjectBean bean = (ProjectBean) ctx.lookup("java:global/ProjectBean");
}
}
But string
ProjectBean bean = (ProjectBean) ctx.lookup("java:global/ProjectBean") make exception:
do this exception:
javax.naming.NameNotFoundException: ProjectBean -- service jboss.naming.context.java.global.ProjectBean
at org.jboss.as.naming.ServiceBasedNamingStore.lookup(ServiceBa sedNamingStore.java:97)
at org.jboss.as.naming.NamingContext.lookup(NamingContext.java: 178)
at org.jboss.as.naming.InitialContext.lookup(InitialContext.jav a:123)
at org.jboss.as.naming.NamingContext.lookup(NamingContext.java: 214)
at javax.naming.InitialContext.lookup(Unknown Source)
at com.staff.test.logic.ProjectBeanTest.test(ProjectBeanTest.ja va:80)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
at java.lang.reflect.Method.invoke(Unknown Source)
at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall( FrameworkMethod.java:47)
at org.junit.internal.runners.model.ReflectiveCallable.run(Refl ectiveCallable.java:12)
at org.junit.runners.model.FrameworkMethod.invokeExplosively(Fr ameworkMethod.java:44)
at org.junit.internal.runners.statements.InvokeMethod.evaluate( InvokeMethod.java:17)
at org.junit.internal.runners.statements.RunBefores.evaluate(Ru nBefores.java:26)
at org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:271 )
at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit 4ClassRunner.java:70)
at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit 4ClassRunner.java:50)
at org.junit.runners.ParentRunner$3.run(ParentRunner.java:238)
at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java: 63)
at org.junit.runners.ParentRunner.runChildren(ParentRunner.java :236)
at org.junit.runners.ParentRunner.access$000(ParentRunner.java: 53)
at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java: 229)
at org.junit.runners.ParentRunner.run(ParentRunner.java:309)
at org.eclipse.jdt.internal.junit4.runner.JUnit4TestReference.r un(JUnit4TestReference.java:50)
at org.eclipse.jdt.internal.junit.runner.TestExecution.run(Test Execution.java:38)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTe sts(RemoteTestRunner.java:467)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTe sts(RemoteTestRunner.java:683)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.run(R emoteTestRunner.java:390)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.main( RemoteTestRunner.java:197)
I dont understand why this string do exception, because I'm newbie.
My project have a bean "ProjectBean" with interface "ProjectBeanLocal" and an entity "Post". And I have a file persistence.xml to work with Oracle 10g.
ProjectBean:
package com.staff.main.logic;
import javax.ejb.LocalBean;
import javax.ejb.Stateless;
import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;
import org.hibernate.ejb.Ejb3Configuration;
import org.hibernate.tool.hbm2ddl.SchemaExport;
import com.staff.main.domain.Post;
/**
* Session Bean implementation class ProjectBean
*/
#Stateless
#LocalBean
public class ProjectBean implements ProjectBeanLocal {
#PersistenceContext(unitName="StaffPU")
EntityManager manager;
public ProjectBean()
{
Ejb3Configuration cfg = new Ejb3Configuration();
cfg.configure("StaffPU", null);
SchemaExport schemaExport = new SchemaExport(cfg.getHibernateConfiguration());
//schemaExport.setOutputFile("schema.sql");
schemaExport.create(true, true);
}
#Override
public void savePost(Post post){
manager.persist(post);
}
#Override
public Post findPost(long id) {
Post post=manager.find(Post.class, id);
return post;
}
}
Interface ProjectBeanLocal:
package com.staff.main.logic;
import javax.ejb.Local;
import com.staff.main.domain.Post;
#Local
public interface ProjectBeanLocal {
void savePost(Post post);
Post findPost(long id);
}
Entity "Post":
package com.staff.main.domain;
import java.io.Serializable;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.SequenceGenerator;
#Entity
public class Post implements Serializable{
private static final long serialVersionUID = 6767319776206583629L;
#Id
#SequenceGenerator(name="ent2seq",sequenceName="seq_post")
#GeneratedValue(strategy=GenerationType.SEQUENCE,generator="ent2seq")
private long id;
#Column(nullable=false)
private String name;
public long getId() {
return id;
}
public void setId(long id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
And persistence.xml:
<?xml version="1.0" encoding="UTF-8"?>
<persistence
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"
version="1.0">
<persistence-unit name="StaffPU">
<jta-data-source>java:jboss/datasources/OracleDS</jta-data-source>
<properties>
<property name="hibernate.dialect" value="org.hibernate.dialect.Oracle10gDialect"/>
<property name="hibernate.hbm2ddl.auto" value="create" />
<!-- <property name="javax.persistence.jdbc.show_sql" value="true" /> -->
<!-- <property name="hibernate.show_sql" value="true" /> -->
</properties>
</persistence-unit>
</persistence>
You need to expose your bean with a Remote interface.
After that, you probably will need to change the JNDI entry name used to lookup the ejb reference.
You don't provide information about how the bean is deployed which, among other things, determines the binding name, but you can search the correct lookup string in the server log.
import java.io.File;
import javax.naming.InitialContext;
import org.jboss.ejb3.embedded.EJB3StandaloneBootstrap;
import org.jboss.ejb3.embedded.EJB3StandaloneDeployer;
in your pom you have to add :
<dependency>
<groupId>org.jboss.embedded</groupId>
<artifactId>jboss-embedded-all</artifactId>
<version>beta3.SP9</version>
</dependency>
<dependency>
<groupId>org.jboss.embedded</groupId>
<artifactId>thirdparty-all</artifactId>
<version>beta3.SP9</version>
</dependency>
you have to add :
embedded-jboss-beans.xml
bean.xml,default.persistence.properties
ejb3-interceptors-aop.xml
into your resources folder and jndi.properties too whtch contains :
java.naming.factory.initial=org.jnp.interfaces.LocalOnlyContextFactory
java.naming.factory.url.pkgs=org.jboss.naming:org.jnp.interfaces
and you test class must contains :
EJB3StandaloneBootstrap.boot(null);
EJB3StandaloneBootstrap.scanClasspath();
EJB3StandaloneBootstrap.deployXmlResource(embeded.xml)
deployer = EJB3StandaloneBootstrap.createDeployer();
deployer.getArchives().add(new File("target/classes").toURI().toURL());
deployer.create();
deployer.start();
InitialContext context = new InitialContext();
and you look up your ejb
Good Morning
I use Eclipse link and JPA, I want to test a small native query and i have an error.
Would you please help me,
I searched in this site and in others and I didn't found a solution.
thank you.
Entity Class
package entites;
import java.io.Serializable;
import javax.persistence.Basic;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.NamedQueries;
import javax.persistence.NamedQuery;
import javax.persistence.Table;
import javax.validation.constraints.Size;
import javax.xml.bind.annotation.XmlRootElement;
/**
*
* #author Minoucha
*/
#Entity
#Table(name = "protocol")
#XmlRootElement
#NamedQueries({
#NamedQuery(name = "Protocol.findAll", query = "SELECT p FROM Protocol p"),
#NamedQuery(name = "Protocol.findByProtocolid", query = "SELECT p FROM Protocol p WHERE p.protocolid = :protocolid"),
#NamedQuery(name = "Protocol.findByProtocolname", query = "SELECT p FROM Protocol p WHERE p.protocolname = :protocolname")})
public class Protocol implements Serializable {
private static final long serialVersionUID = 1L;
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
#Basic(optional = false)
#Column(name = "protocolid")
private Integer protocolid;
#Size(max = 64)
#Column(name = "protocolname")
private String protocolname;
public Protocol() {
}
public Protocol(Integer protocolid) {
this.protocolid = protocolid;
}
public Integer getProtocolid() {
return protocolid;
}
public void setProtocolid(Integer protocolid) {
this.protocolid = protocolid;
}
public String getProtocolname() {
return protocolname;
}
public void setProtocolname(String protocolname) {
this.protocolname = protocolname;
}
#Override
public int hashCode() {
int hash = 0;
hash += (protocolid != null ? protocolid.hashCode() : 0);
return hash;
}
#Override
public boolean equals(Object object) {
// TODO: Warning - this method won't work in the case the id fields are not set
if (!(object instanceof Protocol)) {
return false;
}
Protocol other = (Protocol) object;
if ((this.protocolid == null && other.protocolid != null) || (this.protocolid != null && !this.protocolid.equals(other.protocolid))) {
return false;
}
return true;
}
#Override
public String toString() {
return "entites.Protocol[ protocolid=" + protocolid + " ]";
}
}
Main class
package main;
import java.util.Iterator;
import java.util.List;
import javax.persistence.EntityManager;
import javax.persistence.EntityManagerFactory;
import javax.persistence.EntityTransaction;
import javax.persistence.Persistence;
import javax.persistence.Query;
/**
*
* #author Minoucha
*/
public class Main {
/**
* #param args
*/
public static void main(String[] args) {
// TODO Auto-generated method stub
EntityManagerFactory emf = Persistence.createEntityManagerFactory("TestRestLast3PU");
EntityManager em = emf.createEntityManager();
try {
EntityTransaction entr = em.getTransaction();
entr.begin();
Query query = em.createNativeQuery("SELECT protocolname FROM protocol");
List stList = query.getResultList();
Iterator stIterator = stList.iterator();
while (stIterator.hasNext()) {
System.out.print("pname:" + stIterator.next());
System.out.println();
}
entr.commit();
} finally {
em.close();
}
}
}
Error :
run:
avr. 16, 2013 12:34:24 PM org.hibernate.validator.internal.util.Version <clinit>
INFO: HV000001: Hibernate Validator 4.3.0.Final
[EL Warning]: 2013-04-16 12:34:24.756--ServerSession(8630548)--PersistenceUnitInfo TestTP3RestPU has transactionType RESOURCE_LOCAL and therefore jtaDataSource will be ignored
[EL Info]: 2013-04-16 12:34:24.776--ServerSession(8630548)--EclipseLink, version: Eclipse Persistence Services - 2.3.2.v20111125-r10461
[EL Severe]: 2013-04-16 12:34:24.789--ServerSession(8630548)--Exception [EclipseLink-4021] (Eclipse Persistence Services - 2.3.2.v20111125-r10461): org.eclipse.persistence.exceptions.DatabaseException
Exception in thread "main" javax.persistence.PersistenceException: Exception [EclipseLink-4021] (Eclipse Persistence Services - 2.3.2.v20111125-r10461): org.eclipse.persistence.exceptions.DatabaseException
Exception Description: Unable to acquire a connection from driver [null], user [null] and URL [null]. Verify that you have set the expected driver class and URL. Check your login, persistence.xml or sessions.xml resource. The jdbc.driver property should be set to a class that is compatible with your database platform
Exception Description: Unable to acquire a connection from driver [null], user [null] and URL [null]. Verify that you have set the expected driver class and URL. Check your login, persistence.xml or sessions.xml resource. The jdbc.driver property should be set to a class that is compatible with your database platform
at org.eclipse.persistence.internal.jpa.EntityManagerSetupImpl.deploy(EntityManagerSetupImpl.java:517)
at org.eclipse.persistence.internal.jpa.EntityManagerFactoryDelegate.getDatabaseSession(EntityManagerFactoryDelegate.java:188)
at org.eclipse.persistence.internal.jpa.EntityManagerFactoryDelegate.createEntityManagerImpl(EntityManagerFactoryDelegate.java:277)
at org.eclipse.persistence.internal.jpa.EntityManagerFactoryImpl.createEntityManagerImpl(EntityManagerFactoryImpl.java:294)
at org.eclipse.persistence.internal.jpa.EntityManagerFactoryImpl.createEntityManager(EntityManagerFactoryImpl.java:272)
at main.Main.main(Main.java:23)
Caused by: Exception [EclipseLink-4021] (Eclipse Persistence Services - 2.3.2.v20111125-r10461): org.eclipse.persistence.exceptions.DatabaseException
Exception Description: Unable to acquire a connection from driver [null], user [null] and URL [null]. Verify that you have set the expected driver class and URL. Check your login, persistence.xml or sessions.xml resource. The jdbc.driver property should be set to a class that is compatible with your database platform
at org.eclipse.persistence.exceptions.DatabaseException.unableToAcquireConnectionFromDriverException(DatabaseException.java:376)
at org.eclipse.persistence.sessions.DefaultConnector.connect(DefaultConnector.java:91)
at org.eclipse.persistence.sessions.DatasourceLogin.connectToDatasource(DatasourceLogin.java:162)
at org.eclipse.persistence.internal.sessions.DatabaseSessionImpl.loginAndDetectDatasource(DatabaseSessionImpl.java:584)
at org.eclipse.persistence.internal.jpa.EntityManagerFactoryProvider.login(EntityManagerFactoryProvider.java:206)
at org.eclipse.persistence.internal.jpa.EntityManagerSetupImpl.deploy(EntityManagerSetupImpl.java:488)
... 5 more
Java Result: 1
I got the same exception.
Following the documentation at https://tomcat.apache.org/tomcat-7.0-doc/jndi-datasource-examples-howto.html#MySQL_DBCP_Example one step is missing if you are working with JPA's persistence unit.
Declare a persistence.xml like this:
<?xml version="1.0" encoding="UTF-8"?>
<persistence version="2.1" xmlns="http://xmlns.jcp.org/xml/ns/persistence" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/persistence http://xmlns.jcp.org/xml/ns/persistence/persistence_2_1.xsd">
<persistence-unit name="TestPU" transaction-type="JTA">
<provider>org.eclipse.persistence.jpa.PersistenceProvider</provider>
<jta-data-source>java:comp/env/jdbc/TestDB</jta-data-source>
<class>com.foo.Entity</class>
</persistence-unit>
</persistence>
Two things made it work for me:
Adding the attribute transaction-type="JTA" in the declaration of the persistence-unit element.
Prepending java:comp/env/ in the data source definition.
This has nothing to do with your native query not working, it has to do with not specifying how JPA/EclipseLink is to connect to the database. Your example seems complete except that you have not shown the persistence.xml where it would be configured. Check out the simple example here:
http://wiki.eclipse.org/EclipseLink/Examples/JPA/OutsideContainer