blob: eb3f5285e79dfe5271d64515b767e6e938d3ede5 [file] [log] [blame]
/*
* Copyright (c) 1998, 2021 Oracle and/or its affiliates. All rights reserved.
*
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License v. 2.0 which is available at
* http://www.eclipse.org/legal/epl-2.0,
* or the Eclipse Distribution License v. 1.0 which is available at
* http://www.eclipse.org/org/documents/edl-v10.php.
*
* SPDX-License-Identifier: EPL-2.0 OR BSD-3-Clause
*/
// Contributors:
// Oracle - initial API and implementation from Oracle TopLink
// 01/05/2010-2.1 Guy Pelletier
// - 211324: Add additional event(s) support to the EclipseLink-ORM.XML Schema
// 01/26/2011-2.3 Guy Pelletier
// - 307664: Lifecycle callbacks not called for object from IndirectSet
// 07/15/2011-2.2.1 Guy Pelletier
// - 349424: persists during an preCalculateUnitOfWorkChangeSet event are lost
package org.eclipse.persistence.testing.tests.jpa.inheritance;
import java.util.List;
import jakarta.persistence.EntityManager;
import junit.framework.*;
import org.eclipse.persistence.testing.framework.junit.JUnitTestCase;
import org.eclipse.persistence.testing.models.jpa.inheritance.AAA;
import org.eclipse.persistence.testing.models.jpa.inheritance.Car;
import org.eclipse.persistence.testing.models.jpa.inheritance.Bus;
import org.eclipse.persistence.testing.models.jpa.inheritance.DDD;
import org.eclipse.persistence.testing.models.jpa.inheritance.MacBook;
import org.eclipse.persistence.testing.models.jpa.inheritance.SportsCar;
import org.eclipse.persistence.testing.models.jpa.inheritance.AbstractBus;
import org.eclipse.persistence.testing.models.jpa.inheritance.InheritanceTableCreator;
import org.eclipse.persistence.testing.models.jpa.inheritance.listeners.BusListener;
import org.eclipse.persistence.testing.models.jpa.inheritance.listeners.BusNativeListener;
import org.eclipse.persistence.testing.models.jpa.inheritance.listeners.VehicleListener;
import org.eclipse.persistence.testing.models.jpa.inheritance.listeners.ListenerSuperclass;
import org.eclipse.persistence.testing.models.jpa.inheritance.listeners.FueledVehicleListener;
import org.eclipse.persistence.testing.models.jpa.xml.inheritance.listeners.DefaultListener;
public class LifecycleCallbackJunitTest extends JUnitTestCase {
private static Number m_busID;
public LifecycleCallbackJunitTest() {
super();
}
public LifecycleCallbackJunitTest(String name) {
super(name);
}
public static Test suite() {
TestSuite suite = new TestSuite();
suite.setName("LifecycleCallbackJunitTest");
suite.addTest(new LifecycleCallbackJunitTest("testSetup"));
suite.addTest(new LifecycleCallbackJunitTest("testPrePersistBusOverrideAndAbstractInheritAndDefault"));
suite.addTest(new LifecycleCallbackJunitTest("testPostPersistBusInheritAndDefault"));
suite.addTest(new LifecycleCallbackJunitTest("testPostLoadBusInheritAndDefault"));
suite.addTest(new LifecycleCallbackJunitTest("testPrePersistSportsCarInheritAndExcludeDefault"));
suite.addTest(new LifecycleCallbackJunitTest("testPostPersistSportsCarInheritAndExcludeDefault"));
suite.addTest(new LifecycleCallbackJunitTest("testPrePersistSportsCarOverride"));
suite.addTest(new LifecycleCallbackJunitTest("testQueryInNativePreUpdateEvent"));
suite.addTest(new LifecycleCallbackJunitTest("testDefaultListenerOnMacBook"));
suite.addTest(new LifecycleCallbackJunitTest("testPostLoadFromMembersOfSet"));
suite.addTest(new LifecycleCallbackJunitTest("testSessionEventListenerOnBus"));
return suite;
}
/**
* The setup is done as a test, both to record its failure, and to allow execution in the server.
*/
public void testSetup() {
new InheritanceTableCreator().replaceTables(JUnitTestCase.getServerSession());
clearCache();
}
/**
* Test added for bug 307664.
*/
public void testPostLoadFromMembersOfSet() {
EntityManager em = createEntityManager();
beginTransaction(em);
String aaaId;
try {
int dddPostLoadCountInitial = 0;
int dddListenerPostLoadCountInitial = 0;
AAA aaa = new AAA();
DDD ddd = new DDD();
ddd.setAaa(aaa);
aaa.getDdds().add(ddd);
em.persist(aaa);
aaaId = aaa.getId();
em.flush();
// This should fire a postLoad event ...
em.refresh(aaa);
DDD refreshedDDD = aaa.getDdds().iterator().next();
int dddPostLoadCountRefresh = refreshedDDD.getCount();
int dddListenerPostLoadCountRefresh = refreshedDDD.getCount2();
assertTrue("The PostLoad callback method on DDD was not called after the refresh.", (dddPostLoadCountRefresh - dddPostLoadCountInitial) == 1);
assertTrue("The PostLoad callback method on the DDD Listener was not called after the refresh.", (dddListenerPostLoadCountRefresh - dddListenerPostLoadCountInitial) == 1);
commitTransaction(em);
// Clear the cache and all the works.
clearCache();
em.clear();
AAA findAAA = em.find(AAA.class, aaa.getId());
// This should fire a postLoad event ...
DDD findDDD = findAAA.getDdds().iterator().next();
int dddPostLoadCountFind = findDDD.getCount();
int dddListenerPostLoadCountFind = findDDD.getCount2();
assertTrue("The PostLoad callback method on DDD was not called afer the find.", (dddPostLoadCountFind - dddPostLoadCountRefresh) == 1);
assertTrue("The PostLoad callback method on the DDD Listener was not called afer the find.", (dddListenerPostLoadCountFind - dddListenerPostLoadCountRefresh) == 1);
} catch (RuntimeException ex) {
if (isTransactionActive(em)){
rollbackTransaction(em);
}
closeEntityManager(em);
throw ex;
}
}
public void testPostLoadBusInheritAndDefault() {
int vehiclePostLoadCountBefore = VehicleListener.POST_LOAD_COUNT;
int defaultListenerPostLoadCountBefore = DefaultListener.POST_LOAD_COUNT;
Bus bus = createEntityManager().find(Bus.class, m_busID);
int vehiclePostLoadCountAfter = VehicleListener.POST_LOAD_COUNT;
int defaultListenerPostLoadCountAfter = DefaultListener.POST_LOAD_COUNT;
assertFalse("The PostLoad callback method for Vehicle was not called.", vehiclePostLoadCountBefore == vehiclePostLoadCountAfter);
assertFalse("The PostLoad callback method for DefaultListener was not called.", defaultListenerPostLoadCountBefore == defaultListenerPostLoadCountAfter);
}
public void testPostPersistBusInheritAndDefault() {
int busListenerPostPersistCountBefore = BusListener.POST_PERSIST_COUNT;
int fueledVehiclePostPersistCountBefore = FueledVehicleListener.POST_PERSIST_COUNT;
int defaultListenerPostPersistCountBefore = DefaultListener.POST_PERSIST_COUNT;
int defaultListenerPostLoadCountBefore = DefaultListener.POST_LOAD_COUNT;
int defaultListenerPostLoadCountIntermidiate;
EntityManager em = createEntityManager();
beginTransaction(em);
try {
Bus bus = new Bus();
bus.setPassengerCapacity(50);
bus.setFuelCapacity(175);
bus.setDescription("OC Transpo Bus");
bus.setFuelType("Diesel");
em.persist(bus);
em.flush();
// This should fire a postLoad event ...
em.refresh(bus);
defaultListenerPostLoadCountIntermidiate = DefaultListener.POST_LOAD_COUNT;
jakarta.persistence.Query q = em.createQuery("select distinct b from Bus b where b.id = " + bus.getId());
// This should not fire a postLoad event ...
q.getResultList();
commitTransaction(em);
} catch (RuntimeException ex) {
if (isTransactionActive(em)){
rollbackTransaction(em);
}
closeEntityManager(em);
throw ex;
}
int busListenerPostPersistCountAfter = BusListener.POST_PERSIST_COUNT;
int fueledVehiclePostPersistCountAfter = FueledVehicleListener.POST_PERSIST_COUNT;
int defaultListenerPostPersistCountAfter = DefaultListener.POST_PERSIST_COUNT;
int defaultListenerPostLoadCountAfter = DefaultListener.POST_LOAD_COUNT;
assertFalse("The PostPersist callback method on BusListener was not called.", busListenerPostPersistCountBefore == busListenerPostPersistCountAfter);
assertFalse("The PostPersist callback method on FueledVehicleListener was not called.", fueledVehiclePostPersistCountBefore == fueledVehiclePostPersistCountAfter);
assertFalse("The PostPersist callback method on DefaultListener was not called.", defaultListenerPostPersistCountBefore == defaultListenerPostPersistCountAfter);
assertTrue("The PostLoad callback method on DefaultListener was called more than once, possibly on the refresh.", (defaultListenerPostLoadCountIntermidiate - defaultListenerPostLoadCountBefore) == 1);
assertTrue("The PostLoad callback method on DefaultListener was called on the getQueryResult().", defaultListenerPostLoadCountIntermidiate == defaultListenerPostLoadCountAfter);
}
public void testPostPersistSportsCarInheritAndExcludeDefault() {
int fueledVehiclePostPersistCountBefore = FueledVehicleListener.POST_PERSIST_COUNT;
int defaultListenerPostPersistCountBefore = DefaultListener.POST_PERSIST_COUNT;
EntityManager em = createEntityManager();
beginTransaction(em);
try {
SportsCar sportsCar = new SportsCar();
sportsCar.setPassengerCapacity(4);
sportsCar.setFuelCapacity(55);
sportsCar.setDescription("Porshe");
sportsCar.setFuelType("Gas");
em.persist(sportsCar);
commitTransaction(em);
} catch (RuntimeException ex) {
if (isTransactionActive(em)){
rollbackTransaction(em);
}
closeEntityManager(em);
throw ex;
}
int fueledVehiclePostPersistCountAfter = FueledVehicleListener.POST_PERSIST_COUNT;
int defaultListenerPostPersistCountAfter = DefaultListener.POST_PERSIST_COUNT;
assertFalse("The PostPersist callback method on FueledVehicleListener was not called.", fueledVehiclePostPersistCountBefore == fueledVehiclePostPersistCountAfter);
assertTrue("The PostPersist callback method on DefaultListener was called.", defaultListenerPostPersistCountBefore == defaultListenerPostPersistCountAfter);
}
public void testPrePersistBusOverrideAndAbstractInheritAndDefault() {
int busListenerPrePersistCountBefore = BusListener.PRE_PERSIST_COUNT;
int busNativeListenerPreWriteCountBefore = BusNativeListener.PRE_WRITE_COUNT;
int busNativeListenerPostWriteCountBefore = BusNativeListener.POST_WRITE_COUNT;
int listenerSuperclassPrePersistCountBefore = ListenerSuperclass.COMMON_PRE_PERSIST_COUNT;
int abstractBusPrePeristCountBefore = AbstractBus.PRE_PERSIST_COUNT;
int defaultListenerPrePersistCountBefore = DefaultListener.PRE_PERSIST_COUNT;
EntityManager em = createEntityManager();
beginTransaction(em);
try {
Bus bus = new Bus();
bus.setPassengerCapacity(30);
bus.setFuelCapacity(100);
bus.setDescription("School Bus");
bus.setFuelType("Diesel");
em.persist(bus);
m_busID = bus.getId();
commitTransaction(em);
} catch (RuntimeException ex) {
if (isTransactionActive(em)){
rollbackTransaction(em);
}
closeEntityManager(em);
throw ex;
}
closeEntityManager(em);
int busListenerPrePersistCountAfter = BusListener.PRE_PERSIST_COUNT;
int busNativeListenerPreWriteCountAfter = BusNativeListener.PRE_WRITE_COUNT;
int busNativeListenerPostWriteCountAfter = BusNativeListener.POST_WRITE_COUNT;
int listenerSuperclassPrePersistCountAfter = ListenerSuperclass.COMMON_PRE_PERSIST_COUNT;
int abstractBusPrePeristCountAfter = AbstractBus.PRE_PERSIST_COUNT;
int defaultListenerPrePersistCountAfter = DefaultListener.PRE_PERSIST_COUNT;
assertFalse("The PrePersist callback method on BusListener was not called.", busListenerPrePersistCountBefore == busListenerPrePersistCountAfter);
assertFalse("The PreWrite (native) callback method on BusNativeListener was not called.", busNativeListenerPreWriteCountBefore == busNativeListenerPreWriteCountAfter);
assertFalse("The PostWrite (native) callback method on BusNativeListener was not called.", busNativeListenerPostWriteCountBefore == busNativeListenerPostWriteCountAfter);
assertTrue("The PrePersist callback method on ListenerSuperclass was called.", listenerSuperclassPrePersistCountBefore == listenerSuperclassPrePersistCountAfter);
assertFalse("The PrePersist callback method on AbstractBus was not called.", abstractBusPrePeristCountBefore == abstractBusPrePeristCountAfter);
assertFalse("The PrePersist callback method on DefaultListener was not called.", defaultListenerPrePersistCountBefore == defaultListenerPrePersistCountAfter);
assertFalse("The PrePersist callback method on DefaultListener was called more than once.", defaultListenerPrePersistCountAfter - defaultListenerPrePersistCountBefore >1 );
}
public void testPrePersistSportsCarInheritAndExcludeDefault() {
int listenerSuperclassPrePersistCountBefore = ListenerSuperclass.COMMON_PRE_PERSIST_COUNT;
int defaultListenerPrePersistCountBefore = DefaultListener.PRE_PERSIST_COUNT;
EntityManager em = createEntityManager();
beginTransaction(em);
try {
SportsCar sportsCar = new SportsCar();
sportsCar.setPassengerCapacity(2);
sportsCar.setFuelCapacity(60);
sportsCar.setDescription("Corvette");
sportsCar.setFuelType("Gas");
em.persist(sportsCar);
commitTransaction(em);
} catch (RuntimeException ex) {
if (isTransactionActive(em)){
rollbackTransaction(em);
}
closeEntityManager(em);
throw ex;
}
closeEntityManager(em);
int listenerSuperclassPrePersistCountAfter = ListenerSuperclass.COMMON_PRE_PERSIST_COUNT;
int defaultListenerPrePersistCountAfter = DefaultListener.PRE_PERSIST_COUNT;
assertFalse("The PrePersist callback method on ListenerSuperclass was not called.", listenerSuperclassPrePersistCountBefore == listenerSuperclassPrePersistCountAfter);
assertTrue("The PrePersist callback method on DefaultListener was called.", defaultListenerPrePersistCountBefore == defaultListenerPrePersistCountAfter);
}
public void testPrePersistSportsCarOverride() {
int carPrePersistCountBefore = Car.PRE_PERSIST_COUNT;
int sportsCarPrePersistCountBefore = SportsCar.PRE_PERSIST_COUNT;
EntityManager em = createEntityManager();
beginTransaction(em);
try {
SportsCar sportsCar = new SportsCar();
sportsCar.setPassengerCapacity(2);
sportsCar.setFuelCapacity(90);
sportsCar.setDescription("Viper");
sportsCar.setFuelType("Gas");
em.persist(sportsCar);
commitTransaction(em);
} catch (RuntimeException ex) {
if (isTransactionActive(em)){
rollbackTransaction(em);
}
closeEntityManager(em);
throw ex;
}
closeEntityManager(em);
int carPrePersistCountAfter = Car.PRE_PERSIST_COUNT;
int sportsCarPrePersistCountAfter = SportsCar.PRE_PERSIST_COUNT;
assertTrue("The PrePersist callback method on Car was called.", carPrePersistCountBefore == carPrePersistCountAfter);
assertFalse("The PrePersist callback method on Sports car was not called.", sportsCarPrePersistCountBefore == sportsCarPrePersistCountAfter);
}
/**
* bug: 243993 - RepeatableWriteUnitOfWork's usage of UnitOfWorkImpl can cause ConcurrentModificationException
* - will occur if a native EclipseLink preUpdate event reads entities into the UOW, as it occurs while
* the uow is iterating over its clone list.
*/
public void testQueryInNativePreUpdateEvent(){
clearCache();
EntityManager em = createEntityManager();
List<Bus> results = em.createQuery("Select e from Bus e").getResultList();
for (Bus bus:results){
bus.setDescription("QueryInNativePreUpdateEvent");
}
beginTransaction(em);
try{
em.flush();
} finally {
if(this.isTransactionActive(em)) {
rollbackTransaction(em);
}
closeEntityManager(em);
}
}
public void testDefaultListenerOnMacBook() {
// Tests the default listeners on those entities that don't have their
// own separate entity listener(s) as well.
int defaultListenerPrePersistCountBefore = DefaultListener.PRE_PERSIST_COUNT;
EntityManager em = createEntityManager();
beginTransaction(em);
try {
MacBook macBook = new MacBook();
macBook.setRam(8);
em.persist(macBook);
commitTransaction(em);
} catch (RuntimeException ex) {
if (isTransactionActive(em)){
rollbackTransaction(em);
}
closeEntityManager(em);
throw ex;
}
closeEntityManager(em);
int defaultListenerPrePersistCountAfter = DefaultListener.PRE_PERSIST_COUNT;
assertFalse("The PrePersist callback method on DefaultListener was not called.", defaultListenerPrePersistCountBefore == defaultListenerPrePersistCountAfter);
}
public void testSessionEventListenerOnBus() {
EntityManager em = createEntityManager();
try {
beginTransaction(em);
Bus bus = new Bus();
// This string must not change ... session event listener will look
// for it and will create a new bus with description 'Listener test Bus2'
bus.setDescription("Listener test Bus1");
em.persist(bus);
commitTransaction(em);
// Should be able to find the bus created through the listener.
List results = em.createQuery("select object(bus) from Bus bus where bus.description = 'Listener test Bus2'").getResultList();
assertTrue("Did not find the bus created by the session listener.", results.size() == 1);
} catch (RuntimeException ex) {
if (isTransactionActive(em)){
rollbackTransaction(em);
}
throw ex;
} finally {
closeEntityManager(em);
}
}
}