I'm having troubles implementing JPA methods in my WebApp built in Java ee 7, its returned me "EJBException : Transaction aborted" , but the parameters "ID" and "Description" had send correctly.
package entities;
import java.io.Serializable;
import java.util.List;
import javax.persistence.Basic;
import javax.persistence.CascadeType;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.Id;
import javax.persistence.NamedQueries;
import javax.persistence.NamedQuery;
import javax.persistence.OneToMany;
import javax.persistence.Table;
import javax.validation.constraints.NotNull;
import javax.validation.constraints.Size;
import javax.xml.bind.annotation.XmlRootElement;
import javax.xml.bind.annotation.XmlTransient;
/**
*
* #author Fede-Frost
*/
#Entity
#Table(name = "especialidad")
#XmlRootElement
#NamedQueries({
#NamedQuery(name = "Especialidad.findAll", query = "SELECT e FROM Especialidad e")
, #NamedQuery(name = "Especialidad.findById", query = "SELECT e FROM Especialidad e WHERE e.id = :id")
, #NamedQuery(name = "Especialidad.findByDesc", query = "SELECT e FROM Especialidad e WHERE e.desc = :desc")})
public class Especialidad implements Serializable {
private static final long serialVersionUID = 1L;
#Id
#Basic(optional = false)
#NotNull
#Column(name = "id")
private Integer id;
#Size(max = 45)
#Column(name = "desc")
private String desc;
#OneToMany(cascade = CascadeType.ALL, mappedBy = "especialidad")
private List<Medico> medicoList;
public Especialidad() {
}
public Especialidad(Integer id) {
this.id = id;
}
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getDesc() {
return desc;
}
public void setDesc(String desc) {
this.desc = desc;
}
#XmlTransient
public List<Medico> getMedicoList() {
return medicoList;
}
public void setMedicoList(List<Medico> medicoList) {
this.medicoList = medicoList;
}
#Override
public int hashCode() {
int hash = 0;
hash += (id != null ? id.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 Especialidad)) {
return false;
}
Especialidad other = (Especialidad) object;
if ((this.id == null && other.id != null) || (this.id != null && !this.id.equals(other.id))) {
return false;
}
return true;
}
#Override
public String toString() {
return "MyHospital.Especialidad[ id=" + id + " ]";
}
}
/*
* To change this license header, choose License Headers in Project Properties.
* To change this template file, choose Tools | Templates
* and open the template in the editor.
*/
package model;
import entities.Estudiolab;
import javax.ejb.Stateless;
import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;
/**
*
* #author Fede-Frost
*/
#Stateless
public class EstudiolabFacade extends AbstractFacade<Estudiolab> implements EstudiolabFacadeLocal {
#PersistenceContext(unitName = "MyHospital-ejbPU")
private EntityManager em;
#Override
protected EntityManager getEntityManager() {
return em;
}
public EstudiolabFacade() {
super(Estudiolab.class);
}
}
/*
* To change this license header, choose License Headers in Project Properties.
* To change this template file, choose Tools | Templates
* and open the template in the editor.
*/
package model;
import entities.Especialidad;
import java.util.List;
import javax.ejb.Local;
/**
*
* #author Fede-Frost
*/
#Local
public interface EspecialidadFacadeLocal {
void create(Especialidad especialidad);
void edit(Especialidad especialidad);
void remove(Especialidad especialidad);
Especialidad find(Object id);
List<Especialidad> findAll();
List<Especialidad> findRange(int[] range);
int count();
}
And here it's the big deal, on the controller
/*
* To change this license header, choose License Headers in Project Properties.
* To change this template file, choose Tools | Templates
* and open the template in the editor.
*/
package controller;
import entities.Especialidad;
import javax.inject.Named;
import java.io.Serializable;
import javax.ejb.EJB;
import javax.ejb.EJBException;
import javax.faces.application.FacesMessage;
import javax.faces.view.ViewScoped;
import javax.faces.context.FacesContext;
import javax.inject.Inject;
import model.EspecialidadFacadeLocal;
/**
*
* #author Fede-Frost
*/
#ViewScoped
#Named(value = "mediCon")
public class mediCon implements Serializable {
#EJB
private EspecialidadFacadeLocal especFac;
#Inject
private Especialidad espec;
/**
* Creates a new instance of MediCon
* #return
*/
public void addSpec() {
try {
especFac.create(espec);
FacesContext.getCurrentInstance().addMessage(null, new FacesMessage(FacesMessage.SEVERITY_INFO, "Exito", "Se registro correctamente"));
} catch (EJBException e) {
FacesContext.getCurrentInstance().addMessage(null, new FacesMessage(FacesMessage.SEVERITY_ERROR,"Aviso", e.toString() ));
}
}
public Especialidad getEspec() {
return espec;
}
public void setEspec(Especialidad espec) {
this.espec = espec;
}
}
As I said, JSF sent me the correct parameters which I tested with FacesContext.addMessage, but I don't know why it doesn't work, thanks in advance.
If a SystemException(A system exception must be a subclass
of a RuntimeException or java.rmi.RemoteException) is thrown, the current transaction will be rollbacked
For more information about the Exception types in EJB, you could have a look at this link.
but the query it's from JPA standard created on especialidadFacade
with especialidaEntity
please have a look at JPA: Weird error when I try to persist an object
in your case, "desc" is a reserved keyword
Related
I have a basic "Department"/"Employee" example.
Full example here (in master branch) : https://github.com/granadacoder/jpa-simple-example-one.git
If you setup 4 environment variables (listed in the README), the code is runnable/debuggable.
For my "findAll()" method, I am trying to only bring back the scalars of the Department entity. (key and name). Aka, I do NOT want any child Employees to be tacked onto the Department .. when I do a findAll().
I have tried using an name EntityGraph, but it is not working (I still get the full object graph)
I am using FetchType.LAZY as well. (which should have been enough IMHO)... And I am not calling (department) .getEmployees at all.
But I took the extra step of defining and using "departmentJustScalarsEntityGraphName".
#EntityGraph("departmentJustScalarsEntityGraphName")
List<Department> findAll();
The above is loading the entire graph (all department scalar AND the employees) and doing it in an N+1 manner. :(
The #EntityGraph should only be loading the key and name for the findAll() method.
If you find the code comment
/* right here, desperately hoping for each Department in the "entities" to NOT have employees hydrated */
you can put the debugger there and see the issue.
Note, that when I do a "find by single" (findById(key) or findDepartmentByDepartmentNameEquals(name))......I DO want the employees. So answers that broad stroke disassociate the Employees are not ideal.
No matter what I've tried, I'm getting the N+1 issue. (The sample seed data has three Departments.)
Hibernate: select department0_.DepartmentKey as departme1_0_, department0_.CreateOffsetDateTime as createof2_0_, department0_.DepartmentName as departme3_0_ from DepartmentTable department0_
Hibernate: select employees0_.DepartmentForeignKey as departme6_1_0_, employees0_.EmployeeKey as employee1_1_0_, employees0_.EmployeeKey as employee1_1_1_, employees0_.CreateOffsetDateTime as createof2_1_1_, employees0_.FirstName as firstnam3_1_1_, employees0_.LastName as lastname4_1_1_, employees0_.DepartmentForeignKey as departme6_1_1_, employees0_.Ssn as ssn5_1_1_ from EmployeeTable employees0_ where employees0_.DepartmentForeignKey=?
Hibernate: select employees0_.DepartmentForeignKey as departme6_1_0_, employees0_.EmployeeKey as employee1_1_0_, employees0_.EmployeeKey as employee1_1_1_, employees0_.CreateOffsetDateTime as createof2_1_1_, employees0_.FirstName as firstnam3_1_1_, employees0_.LastName as lastname4_1_1_, employees0_.DepartmentForeignKey as departme6_1_1_, employees0_.Ssn as ssn5_1_1_ from EmployeeTable employees0_ where employees0_.DepartmentForeignKey=?
Hibernate: select employees0_.DepartmentForeignKey as departme6_1_0_, employees0_.EmployeeKey as employee1_1_0_, employees0_.EmployeeKey as employee1_1_1_, employees0_.CreateOffsetDateTime as createof2_1_1_, employees0_.FirstName as firstnam3_1_1_, employees0_.LastName as lastname4_1_1_, employees0_.DepartmentForeignKey as departme6_1_1_, employees0_.Ssn as ssn5_1_1_ from EmployeeTable employees0_ where employees0_.DepartmentForeignKey=?
Here are the main code components:
Department.java
import com.fasterxml.jackson.annotation.JsonBackReference;
import com.fasterxml.jackson.annotation.JsonInclude;
import com.mycompany.organizationdemo.domain.constants.OrmConstants;
import javax.persistence.CascadeType;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.FetchType;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.NamedAttributeNode;
import javax.persistence.NamedEntityGraph;
import javax.persistence.NamedEntityGraphs;
import javax.persistence.OneToMany;
import javax.persistence.Table;
import java.io.Serializable;
import java.time.OffsetDateTime;
import java.util.LinkedHashSet;
import java.util.Set;
#Entity
#NamedEntityGraphs({
#NamedEntityGraph(name = "departmentJustScalarsEntityGraphName", attributeNodes = {
#NamedAttributeNode("departmentKey"),
#NamedAttributeNode("departmentName")})
})
#Table(name = "DepartmentTable")
public class Department implements Serializable {
#Id
#Column(name = "DepartmentKey", unique = true)
#GeneratedValue(strategy = GenerationType.AUTO)
private long departmentKey;
#Column(name = "DepartmentName", unique = true)
private String departmentName;
#Column(name = "CreateOffsetDateTime", columnDefinition = OrmConstants.OffsetDateTimeColumnDefinition)
private OffsetDateTime createOffsetDateTime;
//region Navigation
#OneToMany(
mappedBy = "parentDepartment",
cascade = CascadeType.REMOVE,
orphanRemoval = true,
fetch = FetchType.LAZY /* Lazy or Eager here */
)
private Set<Employee> employees = new LinkedHashSet<>();
//endregion
public long getDepartmentKey() {
return departmentKey;
}
public void setDepartmentKey(long departmentKey) {
this.departmentKey = departmentKey;
}
public String getDepartmentName() {
return departmentName;
}
public void setDepartmentName(String departmentName) {
this.departmentName = departmentName;
}
public OffsetDateTime getCreateOffsetDateTime() {
return createOffsetDateTime;
}
public void setCreateOffsetDateTime(OffsetDateTime createOffsetDateTime) {
this.createOffsetDateTime = createOffsetDateTime;
}
//region Navigation
public Set<Employee> getEmployees() {
return employees;
}
public void setEmployees(Set<Employee> employees) {
this.employees = employees;
}
//endregion
#Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
Department that = (Department) o;
return new org.apache.commons.lang3.builder.EqualsBuilder()
.append(departmentKey, that.departmentKey)
.append(departmentName, that.departmentName)
.isEquals();
}
#Override
public int hashCode() {
return new org.apache.commons.lang3.builder.HashCodeBuilder(17, 37)
.append(departmentKey)
.append(departmentName)
.toHashCode();
}
}
Employee.java
import com.mycompany.organizationdemo.domain.constants.OrmConstants;
import org.apache.commons.lang3.builder.EqualsBuilder;
import org.apache.commons.lang3.builder.HashCodeBuilder;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.FetchType;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.ManyToOne;
import javax.persistence.Table;
import java.io.Serializable;
import java.time.OffsetDateTime;
#Entity
#Table(name = "EmployeeTable")
public class Employee implements Serializable {
#Id
#Column(name = "EmployeeKey", unique = true)
#GeneratedValue(strategy = GenerationType.AUTO)
private long employeeKey;
#Column(name = "Ssn")
private String ssn;
#Column(name = "LastName")
private String lastName;
#Column(name = "FirstName")
private String firstName;
#Column(name = "CreateOffsetDateTime", columnDefinition = OrmConstants.OffsetDateTimeColumnDefinition)
private OffsetDateTime createOffsetDateTime;
//region Navigation
#ManyToOne(fetch = FetchType.LAZY, targetEntity = Department.class)//, cascade = CascadeType.REMOVE)
#JoinColumn(name = "DepartmentForeignKey")
private Department parentDepartment;
//endregion
public long getEmployeeKey() {
return employeeKey;
}
public void setEmployeeKey(long departmentKey) {
this.employeeKey = departmentKey;
}
public String getSsn() {
return ssn;
}
public void setSsn(String ssn) {
this.ssn = ssn;
}
public String getLastName() {
return lastName;
}
public void setLastName(String lastName) {
this.lastName = lastName;
}
public String getFirstName() {
return firstName;
}
public void setFirstName(String firstName) {
this.firstName = firstName;
}
public OffsetDateTime getCreateOffsetDateTime() {
return createOffsetDateTime;
}
public void setCreateOffsetDateTime(OffsetDateTime createOffsetDateTime) {
this.createOffsetDateTime = createOffsetDateTime;
}
//region Navigation
public Department getParentDepartment() {
return parentDepartment;
}
public void setParentDepartment(Department parentDepartment) {
this.parentDepartment = parentDepartment;
}
//endregion
#Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
Employee employee = (Employee) o;
return new EqualsBuilder()
.append(employeeKey, employee.employeeKey)
.append(ssn, employee.ssn)
.isEquals();
}
#Override
public int hashCode() {
return new HashCodeBuilder(17, 37)
.append(employeeKey)
.append(ssn)
.toHashCode();
}
}
Spring JPA
import com.mycompany.organizationdemo.domain.entities.Department;
import com.mycompany.organizationdemo.domaindatalayer.interfaces.IDepartmentRepository;
import org.springframework.data.jpa.repository.EntityGraph;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.Modifying;
import org.springframework.data.jpa.repository.Query;
import org.springframework.data.repository.query.Param;
import javax.transaction.Transactional;
import java.time.OffsetDateTime;
import java.util.Collection;
import java.util.List;
import java.util.Optional;
import java.util.Set;
public interface DepartmentJpaRepository extends JpaRepository<Department, Long>, IDepartmentRepository {
#EntityGraph("departmentJustScalarsEntityGraphName")
List<Department> findAll();
#Query("SELECT d FROM Department d LEFT JOIN FETCH d.employees WHERE d.departmentName = :departmentName") /* this works because departmentName is a UNIQUE constraint...otherwise it might give back duplicate parents (Departments) */
Optional<Department> findDepartmentByDepartmentNameEquals(#Param("departmentName") String departmentName);
/* note the below, this is "lookup strategy". see https://docs.spring.io/spring-data/jpa/docs/current/reference/html/#jpa.query-methods */
Collection<Department> findByCreateOffsetDateTimeBefore(OffsetDateTime zdt);
//#Query("SELECT d FROM Department d LEFT JOIN FETCH d.employees WHERE d.departmentKey IN ?1") /* here a Query will bring back repeat parent (Department) rows */
#EntityGraph(attributePaths = {"employees"})
Collection<Department> findDepartmentByDepartmentKeyIn(Set<Long> departmentKeys);
#Modifying
#Transactional
int deleteDepartmentByDepartmentKey(long departmentKey); /* suffers from N+1 problem */
}
and the repository (plain jane) interface
import com.mycompany.organizationdemo.domain.entities.Department;
import java.time.OffsetDateTime;
import java.util.Collection;
import java.util.List;
import java.util.Optional;
import java.util.Set;
public interface IDepartmentRepository {
List<Department> findAll();
Optional<Department> findById(long key);
Optional<Department> findDepartmentByDepartmentNameEquals(String departmentName);
Collection<Department> findByCreateOffsetDateTimeBefore(OffsetDateTime zdt);
Collection<Department> findDepartmentByDepartmentKeyIn(Set<Long> departmentKeys);
Department save(Department item);
int deleteDepartmentByDepartmentKey(long departmentKey);
}
I have found this:
Spring Data JPARepository: How to conditionally fetch children entites
and this:
https://docs.oracle.com/javaee/7/tutorial/persistence-entitygraphs002.htm
Spring Boot is fairly new. (from gradle settings in the project)
spring_plugin_version = '2.2.6.RELEASE'
springBootVersion = '2.2.6.RELEASE'
slf4jVersion = "1.7.25"
javaxInjectVersion = "1"
javaxPersistenceApiVersion = "2.2"
junitVersion = "4.12"
mockitoVersion = "3.3.0"
jacksonAnnotationsVersion = "2.11.0"
modelMapperVersion = "2.3.7"
commonsLangVersion = '3.7'
PS
I'm also using the "convert to Dto" trick (as seen here) : https://www.baeldung.com/entity-to-and-from-dto-for-a-java-spring-application but the Department(orm-entity) is already hydrated by that point. :(
I have a simple JavaFX TableView which is populated by a JPA database query. I have one column set as editable and that works. However, after a change is made in a cell, it disappears as soon as I sort or even navigate through the TableView. Also, how would you persist these edits back to the database?
Here is the FXML file and its controller:
<?xml version="1.0" encoding="UTF-8"?>
<?import java.lang.*?>
<?import java.net.*?>
<?import java.util.*?>
<?import javafx.scene.*?>
<?import javafx.scene.control.*?>
<?import javafx.scene.control.cell.*?>
<?import javafx.scene.layout.*?>
<AnchorPane id="AnchorPane" prefHeight="600.0" prefWidth="800.0" styleClass="mainFxmlClass" xmlns="http://javafx.com/javafx/8" xmlns:fx="http://javafx.com/fxml/1" fx:controller="com.IXS.synergyixs.ingestor.ViewUsersController">
<stylesheets>
<URL value="#/styles/IssueTrackingLite.css" />
</stylesheets>
<children>
<TableView fx:id="loginsTable" editable="true" prefHeight="593.0" prefWidth="794.0">
<columns>
<TableColumn fx:id="idCol" editable="false" text="Id">
</TableColumn>
<TableColumn fx:id="loginCol" text="Login">
</TableColumn>
<TableColumn fx:id="partyCol" editable="false" text="Party ID">
</TableColumn>
<TableColumn fx:id="creatorCol" editable="false" text="Creator ID">
</TableColumn>
<TableColumn fx:id="modifierCol" editable="false" text="Modifier ID">
</TableColumn>
</columns>
</TableView>
</children>
</AnchorPane>
the controller:
package com.IXS.synergyixs.ingestor;
import com.IXS.synergyixs.ingestor.data.Usr;
import java.net.URL;
import java.util.List;
import java.util.ResourceBundle;
import javafx.collections.FXCollections;
import javafx.collections.ObservableList;
import javafx.fxml.FXML;
import javafx.fxml.Initializable;
import javafx.scene.control.TableColumn;
import javafx.scene.control.TableView;
import javafx.scene.control.cell.PropertyValueFactory;
import javafx.scene.control.cell.TextFieldTableCell;
import javafx.scene.layout.Pane;
import javax.persistence.EntityManager;
import javax.persistence.EntityManagerFactory;
import javax.persistence.Persistence;
/**
* FXML Controller class
*
* #author Owner
*/
public class ViewUsersController implements Initializable {
public EntityManagerFactory emf = Persistence.createEntityManagerFactory("com.mycompany_SynergyIXS-Ingestor_jar_1.0-SNAPSHOTPU");
public EntityManager em = emf.createEntityManager();
public ObservableList<Usr> tableData;
public Usr currentUsr;
/**
* Initializes the controller class.
*/
#FXML
private Pane rootPane;
#FXML
private TableView<Usr> loginsTable;
#FXML
private TableColumn<Usr, Number> idCol;
#FXML
private TableColumn<Usr, String> loginCol;
#FXML
private TableColumn<Usr, Number> partyCol;
#FXML
private TableColumn<Usr, Number> creatorCol;
#FXML
private TableColumn<Usr, Integer> modifierCol;
#Override
public void initialize(URL location, ResourceBundle resources) {
/* to verify query is returning data
for (Usr u : userList) {
System.out.println(u.getId() + " " + u.getLogin());
}
*/
idCol.setCellValueFactory(new PropertyValueFactory<>("id"));
loginCol.setCellValueFactory(new PropertyValueFactory<>("login"));
loginCol.setCellFactory(TextFieldTableCell.forTableColumn‌());
partyCol.setCellValueFactory(new PropertyValueFactory<>("partyId"));
creatorCol.setCellValueFactory(new PropertyValueFactory<>("creatorId"));
modifierCol.setCellValueFactory(new PropertyValueFactory<>("modifierId"));
updateUserList();
loginsTable.setItems(tableData);
}
public void updateUserList() {
List<Usr> userList = em.createNamedQuery("Usr.findAll").getResultList();
if (tableData == null) {
tableData = FXCollections.observableArrayList(userList);
} else {
tableData.clear();
tableData.addAll(userList);
}
}
/*
public void saveUser()
{
em.getTransaction().begin();
em.persist(currentUsr);
em.getTransaction().commit();
updateUserList();
}
*/
}​
Usr class:
package com.IXS.synergyixs.ingestor.data;
import java.io.Serializable;
import java.math.BigDecimal;
import java.math.BigInteger;
import java.util.Date;
import java.util.List;
import javax.persistence.Basic;
import javax.persistence.CascadeType;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.Id;
import javax.persistence.NamedQueries;
import javax.persistence.NamedQuery;
import javax.persistence.OneToMany;
import javax.persistence.Table;
import javax.persistence.Temporal;
import javax.persistence.TemporalType;
import javax.xml.bind.annotation.XmlRootElement;
import javax.xml.bind.annotation.XmlTransient;
/**
*
* #author Owner
*/
#Entity
#Table(name = "USR", catalog = "", schema = "ADMIN")
#XmlRootElement
#NamedQueries({
#NamedQuery(name = "Usr.findAll", query = "SELECT u FROM Usr u")
, #NamedQuery(name = "Usr.findById", query = "SELECT u FROM Usr u WHERE u.id = :id")
, #NamedQuery(name = "Usr.findAllLogin", query = "SELECT u.login FROM Usr u")
, #NamedQuery(name = "Usr.findByLogin", query = "SELECT u FROM Usr u WHERE u.login = :login")
, #NamedQuery(name = "Usr.findByPwd", query = "SELECT u FROM Usr u WHERE u.pwd = :pwd")
, #NamedQuery(name = "Usr.findByPartyId", query = "SELECT u FROM Usr u WHERE u.partyId = :partyId")
, #NamedQuery(name = "Usr.findByCreatorId", query = "SELECT u FROM Usr u WHERE u.creatorId = :creatorId")
, #NamedQuery(name = "Usr.findByCreationDttm", query = "SELECT u FROM Usr u WHERE u.creationDttm = :creationDttm")
, #NamedQuery(name = "Usr.findByModifierId", query = "SELECT u FROM Usr u WHERE u.modifierId = :modifierId")
, #NamedQuery(name = "Usr.findByModificationDttm", query = "SELECT u FROM Usr u WHERE u.modificationDttm = :modificationDttm")})
public class Usr implements Serializable {
private static final long serialVersionUID = 1L;
// #Max(value=?) #Min(value=?)//if you know range of your decimal fields consider using these annotations to enforce field validation
#Id
#Basic(optional = false)
#Column(name = "ID")
private BigDecimal id;
#Basic(optional = false)
#Column(name = "LOGIN")
private String login;
#Basic(optional = false)
#Column(name = "PWD")
private String pwd;
#Column(name = "PARTY_ID")
private BigInteger partyId;
#Basic(optional = false)
#Column(name = "CREATOR_ID")
private BigInteger creatorId;
#Basic(optional = false)
#Column(name = "CREATION_DTTM")
#Temporal(TemporalType.TIMESTAMP)
private Date creationDttm;
#Basic(optional = false)
#Column(name = "MODIFIER_ID")
private BigInteger modifierId;
#Basic(optional = false)
#Column(name = "MODIFICATION_DTTM")
#Temporal(TemporalType.TIMESTAMP)
private Date modificationDttm;
#OneToMany(cascade = CascadeType.ALL, mappedBy = "usr")
private List<UsrAppRole> usrAppRoleList;
public Usr() {
}
public Usr(BigDecimal id) {
this.id = id;
}
public Usr(BigDecimal id, String login, String pwd, BigInteger creatorId, Date creationDttm, BigInteger modifierId, Date modificationDttm) {
this.id = id;
this.login = login;
this.pwd = pwd;
this.creatorId = creatorId;
this.creationDttm = creationDttm;
this.modifierId = modifierId;
this.modificationDttm = modificationDttm;
}
public BigDecimal getId() {
return id;
}
public void setId(BigDecimal id) {
this.id = id;
}
public String getLogin() {
return login;
}
public void setLogin(String login) {
this.login = login;
}
public String getPwd() {
return pwd;
}
public void setPwd(String pwd) {
this.pwd = pwd;
}
public BigInteger getPartyId() {
return partyId;
}
public void setPartyId(BigInteger partyId) {
this.partyId = partyId;
}
public BigInteger getCreatorId() {
return creatorId;
}
public void setCreatorId(BigInteger creatorId) {
this.creatorId = creatorId;
}
public Date getCreationDttm() {
return creationDttm;
}
public void setCreationDttm(Date creationDttm) {
this.creationDttm = creationDttm;
}
public BigInteger getModifierId() {
return modifierId;
}
public void setModifierId(BigInteger modifierId) {
this.modifierId = modifierId;
}
public Date getModificationDttm() {
return modificationDttm;
}
public void setModificationDttm(Date modificationDttm) {
this.modificationDttm = modificationDttm;
}
#XmlTransient
public List<UsrAppRole> getUsrAppRoleList() {
return usrAppRoleList;
}
public void setUsrAppRoleList(List<UsrAppRole> usrAppRoleList) {
this.usrAppRoleList = usrAppRoleList;
}
#Override
public int hashCode() {
int hash = 0;
hash += (id != null ? id.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 Usr)) {
return false;
}
Usr other = (Usr) object;
if ((this.id == null && other.id != null) || (this.id != null && !this.id.equals(other.id))) {
return false;
}
return true;
}
#Override
public String toString() {
return "com.mycompany.synergyixs.ingestor.Usr[ id=" + id + " ]";
}
}
The default onEditCommit handler assumes the table's model uses the JavaFX properties pattern (see TableView documentation, section titled "Editing"). Since your Usr class is essentially a plain JavaBean, with no property accessor methods, the default handler reduces to a no-op.
You either need to refactor your Usr class so that it uses JavaFX properties (see Using javafx.beans properties in model classes for a discussion on using JavaFX properties in JPA entities), or set an onEditCommit handler on the column:
loginCol.setOnEditCommit(e -> {
Usr usr = e.getRowValue();
usr.setLogin(e.getNewValue());
});
To store the value in the database, use merge(...):
loginCol.setOnEditCommit(e -> {
Usr usr = e.getRowValue();
usr.setLogin(e.getNewValue());
// merge change to database:
Usr mergedUsr = em.merge(usr);
// ensure table has same reference as ORM cache:
loginsTable.set(e.getTablePosition().getRow(), mergedUsr);
});
I developed an messaging EJB application with its services that uses WILDFLY 9 server.
Now the application is working and the database is fully functional, I am trying to develop a REST web-service for this app. So I created my RestActivator :
package tn.carmate.webservice;
import javax.ws.rs.ApplicationPath;
import javax.ws.rs.core.Application;
#ApplicationPath("rest")
public class RestActivator extends Application {
}
and my messageRessources.java as follows
package tn.carmate.webservice;
import java.util.List;
import javax.ejb.EJB;
import javax.enterprise.context.RequestScoped;
import javax.ws.rs.Consumes;
import javax.ws.rs.DELETE;
import javax.ws.rs.GET;
import javax.ws.rs.POST;
import javax.ws.rs.Path;
import javax.ws.rs.Produces;
import javax.ws.rs.QueryParam;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.Response;
import javax.ws.rs.core.Response.Status;
import tn.esprit.pi.Services.Services;
import tn.esprit.pi.persistance.Message;
#Path("message")
#RequestScoped
public class MessageRessource {
#EJB
Services servicemessage;
#GET
#Produces(MediaType.APPLICATION_JSON)
#Path("{idreceiver}")
public Response getMessageList(#QueryParam(value = "idreceiver") int idReceiver) {
List<Message> message = servicemessage.getMessageList(idReceiver);
return Response.status(Status.OK).entity(message).build();
}
#POST
#Consumes(MediaType.APPLICATION_JSON)
#Path("{idSrc/idDest/content}")
public Response sendMessage(#QueryParam(value = "idSrc") int idSrc, #QueryParam(value = "idDest") int idDest,
#QueryParam(value = "content") String content) {
servicemessage.sendMessage(idSrc, idDest, content);
return Response.status(Status.OK).build();
}
#DELETE
#Path("{idm}")
public Response deleteMessage(#QueryParam(value = "idm") int id) {
servicemessage.deleteMessage(id);
return Response.status(Status.OK).build();
}
#GET
#Produces(MediaType.APPLICATION_JSON)
#Path("{idSender/idReceiver}")
public Response getConversation(#QueryParam(value = "idSender") int idSender,
#QueryParam(value = "idReceiver") int idReceiver) {
List<Message> conversion = servicemessage.getConversation(idSender, idReceiver);
return Response.status(Status.OK).entity(conversion).build();
}
#GET
#Produces(MediaType.APPLICATION_JSON)
#Path("{idR}")
public Response returnInbox (#QueryParam(value = "idR")int idR){
List<Message> listmessage = servicemessage.returnInbox(idR);
return Response.status(Status.OK).entity(listmessage).build();
}
#DELETE
#Path("{idc}")
public Response deleteConversation(#QueryParam(value = "idc")int id){
servicemessage.deleteConversation(id);
return Response.status(Status.OK).build();
}
}
but whenever I try to consume a service like this one I get this error:
This is the message Entity
package tn.esprit.pi.persistance;
import java.io.Serializable;
import java.lang.String;
import java.util.Date;
import javax.persistence.*;
/**
* Entity implementation class for Entity: Message
*
*/
#Entity(name="message")
public class Message implements Serializable {
/* #EmbeddedId
private MessageId Id;
*/
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
private int id;
private String object;
private String content;
#Temporal(TemporalType.TIMESTAMP)
private Date dateEmission;
#ManyToOne
private User sender;
#ManyToOne
private User receiver;
private static final long serialVersionUID = 1L;
public Message(User src, User dest, String content) {
this.sender = src;
this.receiver = dest;
this.content = content;
this.dateEmission = new Date();
}
public Message() {
super();
}
/* public MessageId getId() {
return Id;
}public void setId(MessageId id) {
Id = id;
}
*/
public int getIdMessage() {
return this.id;
}
public String getObject() {
return this.object;
}
public void setObject(String object) {
this.object = object;
}
public User getReceiver() {
return this.receiver;
}
public void setReceiver(User reciver) {
this.receiver = reciver;
}
public User getSender() {
return this.sender;
}
public void setSender(User sender) {
this.sender = sender;
}
public String getContent() {
return this.content;
}
public void setContent(String content) {
this.content = content;
}
public Date getDateEmission() {
return this.dateEmission;
}
public void setDateEmission(Date dateEmission) {
this.dateEmission = dateEmission;
}
}
Double check your URL, I think it should be
http://localhost:8080 not http://localhost:18080. Just a typo mistake.
Secondly, Application base path for restful services set to rest
so url should be
http://localhost:8080/CarMate-web/rest/message?idreceiver=1
Finally, idreceiver is a Query Parameter but #Path("{idreceiver}") treat it as path parameter.
So, In http://localhost:8080/CarMate-web/rest/message?idreceiver=1
Rest Endpoint expect a path variable after /message/{idreceiver}?idreceiver=1 as mentioned by #Leonardo in comments.
I would suggest any of below listed solutions:
Remove #Path from method
#GET
#Produces(MediaType.APPLICATION_JSON)
public Response getMessageList(#QueryParam(value = "idreceiver") int idReceiver) {
List<Message> message = servicemessage.getMessageList(idReceiver);
return Response.status(Status.OK).entity(message).build();
}
and use this URL: http://localhost:8080/CarMate-web/rest/message?idreceiver=1
Or Change #Path("{idreceiver}") to #Path("idreceiver")
#GET
#Produces(MediaType.APPLICATION_JSON)
#Path("idreceiver")
public Response getMessageList(#QueryParam(value = "idreceiver") int idReceiver) {
List<Message> message = servicemessage.getMessageList(idReceiver);
return Response.status(Status.OK).entity(message).build();
}
and use this URL: http://localhost:8080/CarMate-web/rest/message/idreceiver?idreceiver=1
I'am working with JPA eclipselink at the moment and like to connect to my Database with Eclipselink
I have some classes for de Tables in My database and a Query to get my Entries:
final Query query = entityManager.createQuery("SELECT q FROM FDC_DBCHANGE q ORDER BY q.CHANGE_ID");
I made some classes for my tables:
FDC_DBCHANGE
package com.bechtle.dbchanges.model;
import java.util.ArrayList;
import java.util.List;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.OneToMany;
#Entity
public class FDC_DBCHANGE {
#Id
#GeneratedValue(strategy = GenerationType.TABLE)
private long CHANGE_ID;
private String CHANGE_NAME;
private String CHANGE_DATE;
private int CHANGE_NUMBER;
#OneToMany(mappedBy = "FDC_DBCHANGE")
private final List<FDC_EXECUTED> checkBoxes = new ArrayList<FDC_EXECUTED>();
public String getChangeName() {
return CHANGE_NAME;
}
public void setChangeName(final String pChangeName) {
CHANGE_NAME = pChangeName;
}
public String getChangeDate() {
return CHANGE_DATE;
}
public void setChangeDate(final String pChangeDate) {
CHANGE_DATE = pChangeDate;
}
public int getChangeNumber() {
return CHANGE_NUMBER;
}
public void setChangeNumber(final int pChangeNumber) {
CHANGE_NUMBER = pChangeNumber;
}
public List<FDC_EXECUTED> getCheckBoxes() {
return checkBoxes;
}
#Override
public String toString() {
return "FDC_DBCHANGE [CHANGE_NAME=" + CHANGE_NAME + ", CHANGE_DATE="
+ CHANGE_DATE + "CHANGE_NUMBER=" + CHANGE_NUMBER + "]";
}
}
FDC_EXECUTED
package com.bechtle.dbchanges.model;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.OneToOne;
#Entity
public class FDC_EXECUTED {
#Id
#GeneratedValue(strategy = GenerationType.TABLE)
private int ENTRY_ID;
private FDC_DBCHANGE FDC_DBCHANGE;
private FDC_SYSTEM FDC_SYSTEM;
#OneToOne
#JoinColumn
public FDC_DBCHANGE getDbChange() {
return FDC_DBCHANGE;
}
public void setDbChange(final FDC_DBCHANGE pDbChange) {
FDC_DBCHANGE = pDbChange;
}
#OneToOne
#JoinColumn
public FDC_SYSTEM getSystem() {
return FDC_SYSTEM;
}
public void setSystem(final FDC_SYSTEM pSystem) {
FDC_SYSTEM = pSystem;
}
}
and FDC_SYSTEM
package com.bechtle.dbchanges.model;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.OneToMany;
#Entity
public class FDC_SYSTEM {
#Id
#GeneratedValue(strategy = GenerationType.TABLE)
private int SYSTEM_ID;
private String NAME;
private FDC_EXECUTED fdcexecuted;
public String getName() {
return NAME;
}
public void setName(final String pName) {
NAME = pName;
}
#OneToMany(mappedBy = "FED_SYSTEM")
public FDC_EXECUTED getExecuted() {
return fdcexecuted;
}
public void setExecuted(final FDC_EXECUTED pExecuted) {
fdcexecuted = pExecuted;
}
}
When I run it on my Tomcat there is this Exception:
org.springframework.web.util.NestedServletException: Request processing failed; nested exception is Exception [EclipseLink-4002] (Eclipse Persistence Services - 2.5.0.v20130507-3faac2b): org.eclipse.persistence.exceptions.DatabaseException
Internal Exception: java.sql.SQLSyntaxErrorException: ORA-00904: "FDC_DBCHANGE_CHANGE_ID": invalid identifier
Error Code: 904
Call: SELECT ENTRY_ID, FDC_DBCHANGE_CHANGE_ID, FDC_SYSTEM_SYSTEM_ID FROM FDC_EXECUTED WHERE (FDC_DBCHANGE_CHANGE_ID = ?)
bind => [1 parameter bound]
Query: ReadAllQuery(name="checkBoxes" referenceClass=FDC_EXECUTED sql="SELECT ENTRY_ID, FDC_DBCHANGE_CHANGE_ID, FDC_SYSTEM_SYSTEM_ID FROM FDC_EXECUTED WHERE (FDC_DBCHANGE_CHANGE_ID = ?)")
org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:932)
org.springframework.web.servlet.FrameworkServlet.doGet(FrameworkServlet.java:816)
javax.servlet.http.HttpServlet.service(HttpServlet.java:620)
org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:801)
javax.servlet.http.HttpServlet.service(HttpServlet.java:727)
Eclipselink tries to run the SQL Statement SELECT ENTRY_ID, FDC_DBCHANGE_CHANGE_ID, FDC_SYSTEM_SYSTEM_ID FROM FDC_EXECUTED WHERE (FDC_DBCHANGE_CHANGE_ID = ?)
instead of SELECT ENTRY_ID, CHANGE_ID, SYSTEM_ID FROM FDC_EXECUTED WHERE (CHANGE_ID = ?)
I don't konw why...
I hope someone can help me and sorry for my bad english...
obsidianfarmer
Ok, problem solved, its cause Eclipselink needs an OID I have no acces to, that was the problem...
We are trying to set up an application running on a Glassfish 4 Server. For data retrieval, we are using JPA 2.0 (EclipseLink Kepler). For several reasons, additionally to the normal user management, we also want users to authorize via the DMBS user management.
In order to accomplish that, we create a user-specific JpaEntityManager when the user logs in (In order to check the login itself, we also have a general server-side JpaEntityManager, whose DBMS credentials are located in the persistence.xml). Some code here:
import java.util.Enumeration;
import java.util.HashMap;
import java.util.Hashtable;
import javax.persistence.EntityManager;
import javax.persistence.EntityManagerFactory;
import javax.persistence.Persistence;
import org.eclipse.persistence.jpa.JpaEntityManager;
import org.eclipse.persistence.jpa.JpaHelper;
import application.auth.general.Credentials;
import application.config.Config;
import application.data.model.JpaSession;
import application.logger.Logger;
/**
*/
public class EntityManagerBase {
/**
* Singleton instance
*/
private static EntityManagerBase instance = new EntityManagerBase();
/**
* Hashtable for storage of user specific EntityManagers
*
* #param String userName
* #param EntityManager corresponding EntityManager
*/
private Hashtable<Integer, JpaEntityManager> jpaEms = new Hashtable<>();
/**
* Default constructor for singleton, creates single jpaEm instance for
* user ID -1, rights are defined in server-side persistence.xml
*/
private EntityManagerBase() {
String persistenceUnitName = Config.get("pvapp.data.persistence.unitName");
EntityManagerFactory emf = Persistence.createEntityManagerFactory(persistenceUnitName);
EntityManager em = emf.createEntityManager();
JpaEntityManager jpaEm = JpaHelper.getEntityManager(em);
jpaEms.put(-1, jpaEm);
}
public static EntityManagerBase getInstance() {
return instance;
}
/**
* Prevent cloning of singleton instance
*/
#Override
protected Object clone() throws CloneNotSupportedException {
String name = this.getClass().getCanonicalName();
throw new CloneNotSupportedException(name
+ " does not support clone(). Use " + name
+ ".getInstance() instead.");
}
public void createJpaEntityManager(JpaSession session, Credentials credentials) {
String persistenceUnitName = Config.get("pvapp.data.persistence.unitName");
EntityManagerFactory emf = Persistence.createEntityManagerFactory(persistenceUnitName);
HashMap<String, String> properties = new HashMap<>();
properties.put("javax.persistence.jdbc.user", credentials.getUserName());
properties.put("javax.persistence.jdbc.password", credentials.getPassword());
EntityManager em = emf.createEntityManager(properties);
JpaEntityManager jpaEm = JpaHelper.getEntityManager(em);
jpaEms.put(session.getUser().getId(), jpaEm);
}
public JpaEntityManager getJpaEntityManager(JpaSession session) {
return this.jpaEms.get(session.getUser().getId());
}
/**
* Get a JPA entity manager for a numeric user id
*
* #param id
* #return
*/
public JpaEntityManager getJpaEntityManager(int id) {
return this.jpaEms.get(id);
}
}
So, when a user logs in, createJpaEntityManager is being called, the newly created JpaEntityManager is being stored in a Hashtable with his userId. This works fine for retrieving default POJOs, but if we have relations to other objects, like that:
import java.io.Serializable;
import java.util.List;
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.OneToMany;
import javax.persistence.Table;
import javax.xml.bind.annotation.XmlRootElement;
import application.auth.general.Authorizable;
import static javax.persistence.FetchType.EAGER;
/**
* The persistent class for the modulesignature database table.
*
*/
#Entity(name="JpaModuleSignature")
#Table(name="modulesignature")
#XmlRootElement
#NamedQueries({
#NamedQuery(name="JpaModuleSignature.findAll", query="SELECT m FROM JpaModuleSignature m"),
#NamedQuery(name="JpaModuleSignature.findById", query="SELECT m FROM JpaModuleSignature m WHERE m.id = :id")
})
public class JpaModuleSignature implements Serializable, Authorizable, JpaRecord {
private static final long serialVersionUID = 1L;
#Id
#GeneratedValue(strategy=GenerationType.IDENTITY)
#Column(name="id")
private int id;
#Column(name="authObjId")
private int authObjId;
#Column(name="className")
private String className;
#Column(name="version")
private int version;
//bi-directional many-to-one association to JpaMenuItem
#OneToMany(mappedBy="moduleSignature", fetch = EAGER)
private List<JpaMenuItem> menuItems;
public JpaModuleSignature() {
}
public int getId() {
return this.id;
}
public void setId(int id) {
this.id = id;
}
public int getAuthObjId() {
return this.authObjId;
}
public void setAuthObjId(int authObjId) {
this.authObjId = authObjId;
}
public String getClassName() {
return this.className;
}
public void setClassName(String className) {
this.className = className;
}
public int getVersion() {
return this.version;
}
public void setVersion(int version) {
this.version = version;
}
public List<JpaMenuItem> getMenuItems() {
return this.menuItems;
}
public void setMenuItems(List<JpaMenuItem> menuItems) {
this.menuItems = menuItems;
}
public JpaMenuItem addMenuItem(JpaMenuItem menuItem) {
getMenuItems().add(menuItem);
menuItem.setModuleSignature(this);
return menuItem;
}
public JpaMenuItem removeMenuItem(JpaMenuItem menuItem) {
getMenuItems().remove(menuItem);
menuItem.setModuleSignature(null);
return menuItem;
}
}
Let's say we proceed as follows - determine the user's id and fetch the correct JpaEntityManager (unfortunately, some more code is necessary for that):
First the Jersey 2.0-Webservice, which is rather unspectacular:
import java.util.List;
import javax.ws.rs.GET;
import javax.ws.rs.POST;
import javax.ws.rs.Path;
import javax.ws.rs.Produces;
import javax.ws.rs.QueryParam;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.ext.Provider;
import application.data.model.JpaMenuItem;
import application.data.model.JpaModuleSignature;
import application.data.model.JpaSession;
import application.logger.Logger;
import application.server.storage.GenericStorage;
/**
*/
#Provider
#Path("JpaModuleSignature")
public class ModuleSignatureService extends AbstractService {
/**
* Storage unit dealing with storage of the JPA entities
*/
//private ModuleSignatureStorage storage = ModuleSignatureStorage.getInstance();
private GenericStorage<JpaModuleSignature> storage =
GenericStorage.createInstance(JpaModuleSignature.class);
/**
* Include application.data.model classes
*/
public ModuleSignatureService() {
super();
}
/**
* Get a list of all ModuleSignatures in the database
*
* #return list of ModuleSignatures
*/
#Produces(MediaType.APPLICATION_XML)
#Path("list")
#GET
public JpaModuleSignature[] getModuleSignatures(#QueryParam("sessionId") String sessionId) {
Logger.getInstance().setVerbosity((byte) 3);
JpaSession session = this.getSession(sessionId);
List<JpaModuleSignature> ms = storage.getList(session);
Logger.getInstance().log("-----3-----");
for (int i = 0; i < ms.size(); i++) {
Logger.getInstance().log("signature #" + i + ": " + ms.get(i).getTitle());
List<JpaMenuItem> menuItems = ms.get(i).getMenuItems();
for (int j = 0; j < menuItems.size(); j++) {
Logger.getInstance().log("menu item #" + i + "-" + j + ": " + menuItems.get(j));
}
}
Logger.getInstance().log("-----4-----");
JpaModuleSignature ret[] = new JpaModuleSignature[0];
return ms.toArray(ret);
}
}
There's a callback to our generic storage, which contains the call to the user-specific JpaEntityManager (just look at the one line in getList where StorageBase is called statically:
import java.util.Hashtable;
import java.util.Iterator;
import java.util.List;
import java.util.Set;
import javax.persistence.Entity;
import javax.persistence.Query;
import org.eclipse.persistence.jpa.JpaEntityManager;
import application.auth.general.Authorizable;
import application.data.model.JpaRecord;
import application.data.model.JpaSession;
import application.logger.Logger;
import application.server.auth.AuthorizationManager;
public class GenericStorage<T> extends StorageBase {
/**
* This is an internal variable in order to store the class
* of the generic object. It is used as a helper later in the code
*/
private final Class<T> storageClass;
/**
* The constructor has only "protected" visibility so the formal type
* parameter has to be specified via createClient
*
* #param clientClass
*/
protected GenericStorage(Class<T> storageClass) {
this.storageClass = storageClass;
}
/**
* Static method for creating instances of GenericStorage.
*
* #param className
* #return
*/
public static <U> GenericStorage<U> createInstance(Class<U> className) {
return new GenericStorage<U>(className);
}
/**
* Get a list of all items
*
* #return
*/
public List<T> getList(JpaSession session) {
return this.getList(session, null);
}
public List<T> getList(JpaSession session, Hashtable<String,Object> parameters) {
Entity e = (Entity) this.storageClass.getAnnotation(Entity.class);
String entityName = e.name();
String queryString = "SELECT r FROM " + entityName + " r";
if (parameters != null && parameters.size() > 0) {
String where = " WHERE ";
Set<String> paramKeys = parameters.keySet();
Iterator<String> i = paramKeys.iterator();
while (i.hasNext()) {
String key = i.next();
where += key + " = :" + key;
}
queryString += where;
}
// GET USER-SPECIFIC JpaEntityManager HERE:
JpaEntityManager jpaEm = StorageBase.getJpaEM(session);
Query query = jpaEm.createQuery(queryString);
Logger.getInstance().log("-----1-----");
if (parameters != null && parameters.size() > 0) {
Set<String> paramKeys = parameters.keySet();
Iterator<String> i = paramKeys.iterator();
while (i.hasNext()) {
String key = i.next();
query.setParameter(key, parameters.get(key));
}
}
List<T> L = (List<T>) query.getResultList();
Logger.getInstance().log("-----2----- (" + entityName + ")");
return L;
}
}
Code for StorageBase:
import org.eclipse.persistence.jpa.JpaEntityManager;
import application.data.model.JpaSession;
/**
* Implements general functionality for retrieval of
* user specific JpaEntityManager instances using the
* EntityManagerBase
*/
abstract class StorageBase {
public static JpaEntityManager getJpaEM(JpaSession session) {
return EntityManagerBase.getInstance().getJpaEntityManager(session);
}
public static JpaEntityManager getJpaEM(int id) {
return EntityManagerBase.getInstance().getJpaEntityManager(id);
}
}
If there are any questions what "AbstractService" does - not really necessary to read, it just calls Jersey's 'this.packages(..)' and provides a method to get a JPA Session object by the user's provided session id.
The problem is, that, if we run getModuleSignatures of the ModuleSignatureService, something odd happens: The JpaModuleSignature can basically be retrieved via the correct JpaEntityManager, but when trying to access the linked attribute "menuItems", we get the following error:
INFO: [EL Severe]: 2013-10-09 16:50:24.34--ServerSession(1625769026)--Exception [EclispseLink-4002] (Eclipse Persistence Services - 2.5.0.v20130507-3faac2b): org.eclipe.persistence.exceptions.DatabaseException
Internal Exception: java.sql.SQLException: Access denied for user 'PERSISTENCE.XML-USER'#'localhost' (using password: YES)
Error Code: 1045
Of course the real username is not PERSISTENCE.XML-USER - but it is the one that has been defined in the persistence.xml. We double-checked that the original records are being fetched by the correct user that authorized against the datebase system. However, JPA apparently tries to fetch the linked records via the wrong JpaEntityManager.
Can anyone explain if there is some error on our side, if that is a known problem, or something else that might help?
Thanks in advance.
EMFs wrap shared resources, so as long as the EMF context exists for this persistence unit, the base EMF is used with the base login properties. You will need to setup EclipseLink so that it uses exclusive connections rather than shared connections as described here http://wiki.eclipse.org/EclipseLink/Examples/JPA/Auditing