EclipseLink JPA: NullPointerException in ParameterizedSQLBatchWritingMechanism.executeBatchedStatements
Also posted on the Eclipse Forums: https://www.eclipse.org/forums/index.php/m/1471742/
I'm using EclipseLink JPA over the database H2 with compatibility with MySQL mode : * EclipseLink: 2.5.2-M1 * H2: 1.4.181
I created a datagathering binding that attaches listeners to various activities and updates the database accordingly.
Sometimes I get the following from EclipseLink NullPointerException
:
[EL Warning]: 2014-11-13 09:41:22.47--ClientSession(1918579332)--java.lang.NullPointerException
[EL Warning]: 2014-11-13 09:41:22.47--UnitOfWork(836633225)--java.lang.NullPointerException
[EL Warning]: 2014-11-13 09:41:22.472--UnitOfWork(836633225)--java.lang.NullPointerException
Nov 13, 2014 9:41:22 AM com.mycompany.myproduct.datagathering.listeners.PortHandle onPortConfigured
SEVERE: Persistence error at PortHandle.onPortConfigured for port 'port_lana_2_v6_slaac'
com.mycompany.myproduct.results.testdata.data.TestDataPersistenceError: Failed to persist idEntity PortEvent with id null (with rollback failed!):
at com.mycompany.myproduct.results.testdata.data.TestDataPersistenceController.persistIdEntity(TestDataPersistenceController.java:270)
at com.mycompany.myproduct.testdata.data.BaseEntityManager.persistIdEntity(BaseEntityManager.java:42)
at com.mycompany.myproduct.datagathering.listeners.PortHandle.onPortConfigured(PortHandle.java:830)
....
at com.mycompany.myproduct.run.actions.ConfigurePort$Forwarder.onPortConfigured(ConfigurePort.java:79)
at com.mycompany.myproduct.run.actions.ConfigurePort.invokeImpl(ConfigurePort.java:118)
....
at com.mycompany.myproduct.run.RuntimeScenarioRunner.initialize(RuntimeScenarioRunner.java:102)
at com.mycompany.myproduct.bear.controller.jobs.InitializeScenarioJob.work(InitializeScenarioJob.java:103)
at com.mycompany.myproduct.bear.controller.jobs.RuntimeBearJob.run(RuntimeBearJob.java:63)
at org.eclipse.core.internal.jobs.Worker.run(Worker.java:54)
Caused by: javax.persistence.RollbackException: java.lang.NullPointerException
at org.eclipse.persistence.internal.jpa.transaction.EntityTransactionImpl.commit(EntityTransactionImpl.java:157)
at com.mycompany.myproduct.results.testdata.data.TestDataPersistenceController.persistIdEntity(TestDataPersistenceController.java:261)
... 68 more
Caused by: java.lang.NullPointerException
at org.eclipse.persistence.internal.databaseaccess.ParameterizedSQLBatchWritingMechanism.executeBatchedStatements(ParameterizedSQLBatchWritingMechanism.java:131)
at org.eclipse.persistence.internal.databaseaccess.DatabaseAccessor.basicExecuteCall(DatabaseAccessor.java:608)
at org.eclipse.persistence.internal.databaseaccess.DatabaseAccessor.executeCall(DatabaseAccessor.java:558)
at org.eclipse.persistence.internal.sessions.AbstractSession.basicExecuteCall(AbstractSession.java:1991)
at org.eclipse.persistence.sessions.server.ClientSession.executeCall(ClientSession.java:298)
at org.eclipse.persistence.internal.queries.DatasourceCallQueryMechanism.executeCall(DatasourceCallQueryMechanism.java:242)
at org.eclipse.persistence.internal.queries.DatasourceCallQueryMechanism.executeCall(DatasourceCallQueryMechanism.java:228)
at org.eclipse.persistence.internal.queries.DatasourceCallQueryMechanism.executeSelectCall(DatasourceCallQueryMechanism.java:299)
at org.eclipse.persistence.internal.queries.DatasourceCallQueryMechanism.executeSelect(DatasourceCallQueryMechanism.java:281)
at org.eclipse.persistence.queries.DataReadQuery.executeNonCursor(DataReadQuery.java:197)
at org.eclipse.persistence.queries.DataReadQuery.executeDatabaseQuery(DataReadQuery.java:152)
at org.eclipse.persistence.queries.DatabaseQuery.execute(DatabaseQuery.java:899)
at org.eclipse.persistence.queries.DataReadQuery.execute(DataReadQuery.java:137)
at org.eclipse.persistence.internal.sessions.AbstractSession.internalExecuteQuery(AbstractSession.java:3203)
at org.eclipse.persistence.internal.sessions.AbstractSession.executeQuery(AbstractSession.java:1793)
at org.eclipse.persistence.internal.sessions.AbstractSession.executeQuery(AbstractSession.java:1775)
at org.eclipse.persistence.internal.sessions.AbstractSession.executeQuery(AbstractSession.java:1726)
at org.eclipse.persistence.sequencing.QuerySequence.select(QuerySequence.java:309)
at org.eclipse.persistence.sequencing.QuerySequence.updateAndSelectSequence(QuerySequence.java:254)
at org.eclipse.persistence.sequencing.StandardSequence.getGeneratedValue(StandardSequence.java:61)
at org.eclipse.persistence.sequencing.Sequence.getGeneratedValue(Sequence.java:225)
at org.eclipse.persistence.internal.sequencing.SequencingManager$NoPreallocation_State.getNextValue(SequencingManager.java:677)
at org.eclipse.persistence.internal.sequencing.SequencingManager.getNextValue(SequencingManager.java:1067)
at org.eclipse.persistence.internal.sequencing.ClientSessionSequencing.getNextValue(ClientSessionSequencing.java:70)
at org.eclipse.persistence.internal.descriptors.ObjectBuilder.assignSequenceNumber(ObjectBuilder.java:361)
at org.eclipse.persistence.internal.descriptors.ObjectBuilder.assignSequenceNumber(ObjectBuilder.java:334)
at org.eclipse.persistence.internal.queries.DatabaseQueryMechanism.updateObjectAndRowWithSequenceNumber(DatabaseQueryMechanism.java:859)
at org.eclipse.persistence.internal.queries.DatasourceCallQueryMechanism.insertObject(DatasourceCallQueryMechanism.java:372)
at org.eclipse.persistence.internal.queries.StatementQueryMechanism.insertObject(StatementQueryMechanism.java:165)
at org.eclipse.persistence.internal.queries.StatementQueryMechanism.insertObject(StatementQueryMechanism.java:180)
at org.eclipse.persistence.internal.queries.DatabaseQueryMechanism.insertObjectForWrite(DatabaseQueryMechanism.java:489)
at org.eclipse.persistence.queries.InsertObjectQuery.executeCommit(InsertObjectQuery.java:80)
at org.eclipse.persistence.queries.InsertObjectQuery.executeCommitWithChangeSet(InsertObjectQuery.java:90)
at org.eclipse.persistence.internal.queries.DatabaseQueryMechanism.executeWriteWithChangeSet(DatabaseQueryMechanism.java:301)
at org.eclipse.persistence.queries.WriteObjectQuery.executeDatabaseQuery(WriteObjectQuery.java:58)
at org.eclipse.persistence.queries.DatabaseQuery.execute(DatabaseQuery.java:899)
at org.eclipse.persistence.queries.DatabaseQuery.executeInUnitOfWork(DatabaseQuery.java:798)
at org.eclipse.persistence.queries.ObjectLevelModifyQuery.executeInUnitOfWorkObjectLevelModifyQuery(ObjectLevelModifyQuery.java:108)
at org.eclipse.persistence.queries.ObjectLevelModifyQuery.executeInUnitOfWork(ObjectLevelModifyQuery.java:85)
at org.eclipse.persistence.internal.sessions.UnitOfWorkImpl.internalExecuteQuery(UnitOfWorkImpl.java:2896)
at org.eclipse.persistence.internal.sessions.AbstractSession.executeQuery(AbstractSession.java:1793)
at org.eclipse.persistence.internal.sessions.AbstractSession.executeQuery(AbstractSession.java:1775)
at org.eclipse.persistence.internal.sessions.AbstractSession.executeQuery(AbstractSession.java:1726)
at org.eclipse.persistence.internal.sessions.CommitManager.commitNewObjectsForClassWithChangeSet(CommitManager.java:226)
at org.eclipse.persistence.internal.sessions.CommitManager.commitAllObjectsWithChangeSet(CommitManager.java:125)
at org.eclipse.persistence.internal.sessions.AbstractSession.writeAllObjectsWithChangeSet(AbstractSession.java:4196)
at org.eclipse.persistence.internal.sessions.UnitOfWorkImpl.commitToDatabase(UnitOfWorkImpl.java:1441)
at org.eclipse.persistence.internal.sessions.UnitOfWorkImpl.commitToDatabaseWithChangeSet(UnitOfWorkImpl.java:1531)
at org.eclipse.persistence.internal.sessions.RepeatableWriteUnitOfWork.commitRootUnitOfWork(RepeatableWriteUnitOfWork.java:277)
at org.eclipse.persistence.internal.sessions.UnitOfWorkImpl.commitAndResume(UnitOfWorkImpl.java:1169)
at org.eclipse.persistence.internal.jpa.transaction.EntityTransactionImpl.commit(EntityTransactionImpl.java:132)
... 69 more
This does not always happen, but rather 1 time in 5-10.
Some relevant code snippets:
public class PortHandle {
public void onPortCreated(RuntimePort rtPort) {
String portName = rtPort.getName();
try {
Port port = generatePersistedPort(rtPort);
---> creates and persists Port entity used below
portCache.put(rtPort, port); // put in cache, for use in other callbacks
} catch (TestDataPersistenceError e) {
logger.log(Level.SEVERE, "Persistence error at PortHandle.onPortCreated for port '" + portName + "'", e);
}
}
public void onPortConfigured(RuntimePort rtPort) {
Date time = new Date();
String portName = rtPort.getName();
try {
Port port = getCachedPortEntity(rtPort); // was filled by earlier callback, see above
port.setStatus(PortStatus.ACTIVE);
portManager.persistIdEntity(port);
// log the event
String message = "Port '" + portName + "' is configured.";
EventSeverity severity = EventSeverity.TEST_LOG;
PortEvent event = new PortEvent(time, message, severity, port);
eventManager.persistIdEntity(event);
---> eventManager has link to TestDataPersistenceController below
---> throws the exception!
} catch (TestDataPersistenceError e) {
logger.log(Level.SEVERE, "Persistence error at PortHandle.onPortConfigured for port '" + portName + "'", e);
----> seen in the log above!
}
}
private final Map<RuntimePort, Port> portCache; // kept in sync
private Port getCachedPortEntity(RuntimePort rtPort) throws TestDataPersistenceError {
String portName = rtPort.getName();
Port port = portCache.get(rtPort);
if (port == null) {
throw new IllegalStateException();
}
portManager.refreshIdEntity(port);
if (port.getId() == null) {
throw new IllegalStateException();
}
return port;
}
}
All events originate from the underlying object IdEntity
:
public interface IdEntity {
public Long getId();
}
@MappedSuperclass
public abstract class BaseEntity implements IdEntity, Serializable {
private static final long serialVersionUID = 1L;
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Column(name = "id", unique = true, nullable = false)
private Long id;
@Override
public Long getId() {
return id;
}
... (equals + hashcode implementation)
}
These objects are saved as follows:
public class TestDataPersistenceController {
void persistIdEntity(BaseEntity idEntity) throws TestDataPersistenceError {
if (idEntity == null) {
throw new IllegalArgumentException("Failed to persist entity; null entity provided");
}
String className = idEntity.getClass().getSimpleName();
EntityManager em = getEntityManager();
try {
em.getTransaction().begin();
if (idEntity.getId() == null) {
em.persist(idEntity);
} else {
em.merge(idEntity);
}
em.getTransaction().commit();
} catch (Exception ex) {
boolean rollBackFailed = false;
try {
em.getTransaction().rollback();
} catch (Exception exx) {
rollBackFailed = true;
}
if (rollBackFailed) {
throw new TestDataPersistenceError("Failed to persist idEntity " + className + " with id "
+ idEntity.getId() + " (with rollback failed!):", ex);
} else {
throw new TestDataPersistenceError("Failed to persist idEntity " + className + " with id "
+ idEntity.getId() + " (with successful rollback)", ex);
}
}
}
}
Finally, there are objects Event
and PortEvent
:
@Entity
@Inheritance(strategy = InheritanceType.JOINED)
@DiscriminatorColumn(name = "type")
@DiscriminatorValue(value = "GENERIC")
@Table(name = "event")
public class Event extends BaseEntity {
private static final long serialVersionUID = 1L;
@Temporal(TemporalType.TIMESTAMP)
@Column(name = "event_time", nullable = false)
private Date eventTime;
@Column(name = "description", length = 400, nullable = false)
private String description;
@Enumerated(EnumType.STRING)
@Column(name = "severity", length = 40, nullable = false)
private EventSeverity severity;
public Event(Date eventTime, String description, EventSeverity severity) {
.... (null checks + assignments)
}
Event() {
}
... (getters and setters)
}
@Entity
@DiscriminatorValue("PORT")
@Table(name = "event_port")
public class PortEvent extends Event {
private static final long serialVersionUID = 1L;
@ManyToOne
@JoinColumn(name = "port_id")
private Port port;
public PortEvent(Date eventTime, String description, EventSeverity severity, Port port) {
super(eventTime, description, severity);
this.port = port;
}
PortEvent() {
}
.... (getters and setters)
}
Am I doing something wrong here? Anyway, I think NPE shouldn't come from the EclipseLink library.
Thank!
[Edit]: additional information on subsequent error
Perhaps due to this initial error, I get the following exception later:
SEVERE: Persistence error at PortHandle.onScenarioStopped for port 'port_lana_1_v6_slaac'
com.mycompany.myproduct.results.testdata.data.TestDataPersistenceError: Failed to refresh idEntity Port with id 1
at com.mycompany.myproduct.results.testdata.data.TestDataPersistenceController.refreshIdEntity(TestDataPersistenceController.java:301)
at com.mycompany.myproduct.results.testdata.data.BaseEntityManager.refreshIdEntity(BaseEntityManager.java:46)
at com.mycompany.myproduct.datagathering.listeners.PortHandle.getCachedPortEntity(PortHandle.java:904)
at com.mycompany.myproduct.datagathering.listeners.PortHandle.onScenarioStopped(PortHandle.java:880)
...
at com.mycompany.myproduct.run.actions.StopScenario$Forwarder.onScenarioStopped(StopScenario.java:21)
at com.mycompany.myproduct.run.actions.StopScenario.invokeImpl(StopScenario.java:47)
...
at com.mycompany.myproduct.run.RuntimeScenarioRunner.run(RuntimeScenarioRunner.java:149)
at com.mycompany.myproduct.bear.controller.jobs.RunScenarioJob.work(RunScenarioJob.java:55)
at com.mycompany.myproduct.bear.controller.jobs.RuntimeBearJob.run(RuntimeBearJob.java:63)
at org.eclipse.core.internal.jobs.Worker.run(Worker.java:54)
Caused by: java.lang.IllegalArgumentException: Can not refresh not managed object: com.mycompany.myproduct.results.testdata.data.entities.Port@7ff72a57.
at org.eclipse.persistence.internal.jpa.EntityManagerImpl.refresh(EntityManagerImpl.java:1024)
at org.eclipse.persistence.internal.jpa.EntityManagerImpl.refresh(EntityManagerImpl.java:929)
at com.mycompany.myprodyct.results.testdata.data.TestDataPersistenceController.refreshIdEntity(TestDataPersistenceController.java:299)
... 44 more
This comes from the following code:
public class PortHandle {
public void onScenarioStopped(RuntimeScenario rtScenario) {
Date time = new Date(); // event time
for (RuntimePort rtPort : rtScenario.getRuntimePorts()) {
String portName = rtPort.getName();
try {
Port port = getCachedPortEntity(rtPort);
----> throws the exception!
port.setStatus(PortStatus.STOPPED);
portManager.persistIdEntity(port);
// log the event
String message = "Port '" + portName + "' is destroyed.";
EventSeverity severity = EventSeverity.TEST_LOG;
PortEvent event = new PortEvent(time, message, severity, port);
eventManager.persistIdEntity(event);
} catch (TestDataPersistenceError e) {
logger.log(Level.SEVERE, "Persistence error at PortHandle.onScenarioStopped for port '" + portName + "'", e);
----> seen in the log above!
}
}
}
}
[Edit2]: additional information on how the database is created
It is perhaps important to note that I am not generating my DDL statements and subsequent database from JPA entities, but from a separate MySQL Workbench tool .
In this tool, I am setting all columns id
to AUTO INCREMENT
. For example, it contains table generation instructions like this:
CREATE TABLE IF NOT EXISTS `testdata`.`event` (
`id` BIGINT(20) NOT NULL AUTO_INCREMENT,
`event_time` TIMESTAMP NOT NULL,
`description` VARCHAR(400) NOT NULL,
`severity` VARCHAR(40) NOT NULL,
`type` VARCHAR(40) NOT NULL,
PRIMARY KEY (`id`) )
ENGINE = InnoDB;
source to share
No one has answered this question yet
Check out similar questions: