blob: bc4565d221e1e496fb1bba5895404ba3a2aed2d4 [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
package org.eclipse.persistence.testing.tests.distributedservers.rcm;
import java.util.Enumeration;
import java.util.Hashtable;
import org.eclipse.persistence.descriptors.ClassDescriptor;
import org.eclipse.persistence.internal.sessions.UnitOfWorkImpl;
import org.eclipse.persistence.queries.DatabaseQuery;
import org.eclipse.persistence.queries.ReadObjectQuery;
import org.eclipse.persistence.sessions.UnitOfWork;
import org.eclipse.persistence.testing.tests.distributedservers.DistributedServer;
import org.eclipse.persistence.testing.tests.distributedservers.DistributedServersModel;
import org.eclipse.persistence.testing.framework.TestErrorException;
import org.eclipse.persistence.testing.models.employee.domain.Address;
import org.eclipse.persistence.testing.models.employee.domain.Employee;
/**
* Tests fix for bug:3604593
* This test checks to see that when changing an object's reference that
* removing a referenced object in the database will not cause a corruption
* when the original changeset containing the reference change gets propogated.
*/
public class InvalidateObjectWithMissingReferenceTest extends ConfigurableCacheSyncDistributedTest {
ReadObjectQuery query;
Employee originalObject;
Address originalAddress;
Address newAddress;
DistributedServer server;
public InvalidateObjectWithMissingReferenceTest() {
super();
setName("InvalidateObjectWithMissingReferenceTest");
cacheSyncConfigValues.put(Employee.class, ClassDescriptor.SEND_OBJECT_CHANGES);
cacheSyncConfigValues.put(Address.class, ClassDescriptor.DO_NOT_SEND_CHANGES);
}
@Override
public void reset() {
getSession().getIdentityMapAccessor().initializeAllIdentityMaps();
Enumeration enumtr = DistributedServersModel.getDistributedServers().elements();
while (enumtr.hasMoreElements()) {
(((DistributedServer)enumtr.nextElement()).getDistributedSession()).getIdentityMapAccessor().initializeAllIdentityMaps();
}
Enumeration keys = oldCacheSyncConfigValues.keys();
while (keys.hasMoreElements()) {
Class keyClass = (Class)keys.nextElement();
ClassDescriptor descriptor = getSession().getDescriptor(keyClass);
int newCacheSyncType = (Integer) oldCacheSyncConfigValues.get(keyClass);
descriptor.setCacheSynchronizationType(newCacheSyncType);
}
}
@Override
public void setup() {
oldCacheSyncConfigValues = new Hashtable();
Enumeration keys = cacheSyncConfigValues.keys();
while (keys.hasMoreElements()) {
Class keyClass = (Class)keys.nextElement();
ClassDescriptor descriptor = getSession().getDescriptor(keyClass);
if (descriptor != null) {
int cacheSyncType = descriptor.getCacheSynchronizationType();
Object newCacheSyncType = cacheSyncConfigValues.get(keyClass);
if (newCacheSyncType != null) {
oldCacheSyncConfigValues.put(keyClass, cacheSyncType);
descriptor.setCacheSynchronizationType((Integer) newCacheSyncType);
}
}
}
getSession().getIdentityMapAccessor().initializeAllIdentityMaps();
this.originalObject = (Employee)getSession().readObject(Employee.class);
this.originalAddress = this.originalObject.getAddress();
this.query = new ReadObjectQuery();
this.query.setSelectionObject(this.originalObject);
this.server = (DistributedServer)DistributedServersModel.getDistributedServers().get(0);
getEmployeeFromDistributedSession(this.query);
}
@Override
protected void test() {
UnitOfWork uow = getSession().acquireUnitOfWork();
Employee empClone = (Employee)uow.registerObject(this.originalObject);
this.newAddress = new Address();
this.newAddress.setCity("Ottawa");
this.newAddress.setPostalCode("K5J2B5");
this.newAddress.setProvince("ONT");
this.newAddress.setStreet("should not exist when test completes");
this.newAddress.setCountry("Canada");
Address addressClone = (Address)uow.registerObject(this.newAddress);
empClone.setAddress(addressClone);
uow.assignSequenceNumber(addressClone);
//uow.commit() is broken into components to allow DB change before cache synch propogates changes
((UnitOfWorkImpl)uow).issueSQLbeforeCompletion();
getAbstractSession().insertObject(this.originalAddress);
getAbstractSession().getSessionForClass(Employee.class).executeNonSelectingSQL("UPDATE EMPLOYEE SET ADDR_ID = " + this.originalAddress.getId() + " WHERE (EMP_ID = " + empClone.getId() + ")");
getAbstractSession().deleteObject(addressClone);
((UnitOfWorkImpl)uow).mergeClonesAfterCompletion();
}
@Override
protected void verify() {
Employee remoteEmployee = (Employee)getObjectFromDistributedCache(this.originalObject);
if ((remoteEmployee != null) && (remoteEmployee.getAddress() == null)) {
throw new TestErrorException("Employee's Address reference was corrupted during RCM synch" + " when Address was removed from the database. ");
}
remoteEmployee = getEmployeeFromDistributedSession(this.query);
if (remoteEmployee.getAddress() == null) {
throw new TestErrorException("Employee's Address reference was corrupted during RCM synch" + " when Address was removed from the database. ");
}
if (remoteEmployee.getAddress().getId() == newAddress.getId()) {
throw new TestErrorException("New object Address was built/sent with the changeset in RCM " + "though its descriptor specifies DO_NOT_SEND_CHANGES");
}
}
public Employee getEmployeeFromDistributedSession(DatabaseQuery query) {
try {
Employee result = (Employee)this.server.getDistributedSession().executeQuery(query);
result.getAddress();
return result;
} catch (Exception exception) {
return null;
}
}
}