/******************************************************************************* | |
* Copyright (c) 1998, 2013 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 v1.0 and Eclipse Distribution License v. 1.0 | |
* which accompanies this distribution. | |
* The Eclipse Public License is available at http://www.eclipse.org/legal/epl-v10.html | |
* and the Eclipse Distribution License is available at | |
* http://www.eclipse.org/org/documents/edl-v10.php. | |
* | |
* Contributors: | |
* Oracle - initial API and implementation from Oracle TopLink | |
******************************************************************************/ | |
package org.eclipse.persistence.testing.tests.unitofwork; | |
import java.util.Vector; | |
import org.eclipse.persistence.expressions.Expression; | |
import org.eclipse.persistence.expressions.ExpressionBuilder; | |
import org.eclipse.persistence.internal.helper.Helper; | |
import org.eclipse.persistence.internal.sessions.AbstractSession; | |
import org.eclipse.persistence.queries.ReadObjectQuery; | |
import org.eclipse.persistence.sessions.remote.RemoteSession; | |
import org.eclipse.persistence.sessions.Session; | |
import org.eclipse.persistence.sessions.SessionEventListener; | |
import org.eclipse.persistence.sessions.UnitOfWork; | |
import org.eclipse.persistence.testing.tests.remote.RemoteModel; | |
import org.eclipse.persistence.testing.framework.AutoVerifyTestCase; | |
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; | |
import org.eclipse.persistence.testing.models.employee.domain.EmploymentPeriod; | |
import org.eclipse.persistence.testing.models.employee.domain.LargeProject; | |
import org.eclipse.persistence.testing.models.employee.domain.SmallProject; | |
public class ComplexMultipleUnitOfWorkTest extends AutoVerifyTestCase { | |
public Employee readInSession; | |
public Employee readInUow; | |
public Employee newEmployeeInUow; | |
public Employee readInFirstNestedUow; | |
public UnitOfWork firstUnitOfWork; | |
public UnitOfWork secondUnitOfWork; | |
public UnitOfWork thirdUnitOfWork; | |
// On some platforms (Sybase) if conn1 updates a row but hasn't yet committed transaction then | |
// reading the row through conn2 may hang. | |
// To avoid this problem the listener would decrement transaction isolation level, | |
// then reading through conn2 no longer hangs, however may result (results on Sybase) | |
// in reading of uncommitted data. | |
SessionEventListener listener; | |
/** | |
* MultipleUnitOfWorkTestCase constructor comment. | |
*/ | |
public ComplexMultipleUnitOfWorkTest() { | |
super(); | |
} | |
public Address addressExample1() { | |
Address address = new org.eclipse.persistence.testing.models.employee.domain.Address(); | |
address.setCity("Toronto"); | |
address.setPostalCode("L5J2B5"); | |
address.setProvince("ONT"); | |
address.setStreet("1450 Acme Cr., suite 4"); | |
address.setCountry("Canada"); | |
return address; | |
} | |
public Address addressExample2() { | |
Address address = new org.eclipse.persistence.testing.models.employee.domain.Address(); | |
address.setCity("Ottawa"); | |
address.setPostalCode("K5J2B5"); | |
address.setProvince("ONT"); | |
address.setStreet("1450 Acme Cr., suite 4"); | |
address.setCountry("Canada"); | |
return address; | |
} | |
public Address addressExample3() { | |
Address address = new org.eclipse.persistence.testing.models.employee.domain.Address(); | |
address.setCity("Sudbury"); | |
address.setPostalCode("L5J2B5"); | |
address.setProvince("ONT"); | |
address.setStreet("1450 Acme Cr., suite 4"); | |
address.setCountry("Canada"); | |
return address; | |
} | |
public Address addressExample4() { | |
Address address = new org.eclipse.persistence.testing.models.employee.domain.Address(); | |
address.setCity("Niagra"); | |
address.setPostalCode("L5J2B5"); | |
address.setProvince("ONT"); | |
address.setStreet("1450 Acme Cr., suite 4"); | |
address.setCountry("Canada"); | |
return address; | |
} | |
protected void changeObject(Employee employee, UnitOfWork unitOfWork) { | |
// Transformation | |
employee.setNormalHours(new java.sql.Time[2]); | |
employee.setStartTime(Helper.timeFromHourMinuteSecond(1, 1, 1)); | |
employee.setEndTime(Helper.timeFromHourMinuteSecond(1, 1, 1)); | |
// Aggregate | |
employee.setPeriod(new EmploymentPeriod(Helper.dateFromYearMonthDate(1901, 1, 1), | |
Helper.dateFromYearMonthDate(1902, 2, 2))); | |
// One to many private | |
employee.setPhoneNumbers(new Vector()); | |
employee.addPhoneNumber(new org.eclipse.persistence.testing.models.employee.domain.PhoneNumber("home", "613", | |
"2263374")); | |
employee.addPhoneNumber(new org.eclipse.persistence.testing.models.employee.domain.PhoneNumber("office", "416", | |
"8224599")); | |
// Many to many | |
employee.setProjects(new Vector()); | |
employee.addProject((org.eclipse.persistence.testing.models.employee.domain.Project)unitOfWork.readObject(SmallProject.class)); | |
employee.addProject((org.eclipse.persistence.testing.models.employee.domain.Project)unitOfWork.readObject(LargeProject.class)); | |
// Direct collection | |
employee.setResponsibilitiesList(new Vector()); | |
employee.addResponsibility("make coffee"); | |
employee.addResponsibility("buy donuts"); | |
// One to one private/public | |
employee.setAddress(addressExample4()); | |
((Employee)unitOfWork.readObject(Employee.class, new ExpressionBuilder().get("firstName").equal("Marcus"))).addManagedEmployee(employee); | |
} | |
public Employee createNewEmployeeObject() { | |
Employee employee = new org.eclipse.persistence.testing.models.employee.domain.Employee(); | |
employee.setFirstName("Judy"); | |
employee.setLastName("Barney"); | |
employee.setMale(); | |
employee.setSalary(35000); | |
employee.setPeriod(employmentPeriodExample()); | |
employee.setAddress(addressExample1()); | |
employee.addResponsibility("Make the coffee."); | |
employee.addResponsibility("Clean the kitchen."); | |
employee.addPhoneNumber(new org.eclipse.persistence.testing.models.employee.domain.PhoneNumber("Work", "613", | |
"2258812")); | |
employee.addProject(smallProjectExample()); | |
return employee; | |
} | |
public EmploymentPeriod employmentPeriodExample() { | |
EmploymentPeriod employmentPeriod = new org.eclipse.persistence.testing.models.employee.domain.EmploymentPeriod(); | |
employmentPeriod.setEndDate(org.eclipse.persistence.internal.helper.Helper.dateFromYearMonthDate(1996, 0, 1)); | |
employmentPeriod.setStartDate(org.eclipse.persistence.internal.helper.Helper.dateFromYearMonthDate(1993, 0, 1)); | |
return employmentPeriod; | |
} | |
public void processFirstUnitOfWork() throws Exception { | |
Expression firstNameExpression; | |
// Read the object in the session | |
firstNameExpression = new ExpressionBuilder().get("firstName").equal("Bob"); | |
this.readInSession = (Employee)getSession().readObject(Employee.class, firstNameExpression); | |
// Acquire unit of work | |
// Read first object in the uow | |
this.firstUnitOfWork = getSession().acquireUnitOfWork(); | |
firstNameExpression = new ExpressionBuilder().get("firstName").equal("John"); | |
this.readInUow = (Employee)this.firstUnitOfWork.readObject(Employee.class, firstNameExpression); | |
Employee regDel = (Employee)this.firstUnitOfWork.registerObject(this.readInSession); | |
// Must remove references to deleted objects. | |
if (regDel.getManager() != null) { | |
regDel.getManager().removeManagedEmployee(regDel); | |
} | |
for (java.util.Enumeration mgdEnum = regDel.getManagedEmployees().elements(); mgdEnum.hasMoreElements(); | |
) { | |
((Employee)mgdEnum.nextElement()).setManager(null); | |
} | |
for (java.util.Enumeration mgdProjEnum = | |
(this.firstUnitOfWork.readAllObjects(org.eclipse.persistence.testing.models.employee.domain.Project.class)).elements(); | |
mgdProjEnum.hasMoreElements(); ) { | |
((org.eclipse.persistence.testing.models.employee.domain.Project)mgdProjEnum.nextElement()).setTeamLeader(null); | |
} | |
// Delete the object read in the session without registration. | |
this.firstUnitOfWork.deleteObject(this.readInSession); | |
// Create object in uow and register it. | |
this.newEmployeeInUow = createNewEmployeeObject(); | |
Employee newEmployeeInFirstUow = (Employee)this.firstUnitOfWork.registerObject(this.newEmployeeInUow); | |
// Must remove references to deleted objects. | |
if (this.readInUow.getManager() != null) { | |
this.readInUow.getManager().removeManagedEmployee(this.readInUow); | |
} | |
for (java.util.Enumeration mgdEnum = this.readInUow.getManagedEmployees().elements(); | |
mgdEnum.hasMoreElements(); ) { | |
((Employee)mgdEnum.nextElement()).setManager(null); | |
} | |
// Acquire first nested unit of work | |
// Delete read object in the unit of work without registering it. | |
// Read some object and change it. | |
UnitOfWork firstNestedUow = this.firstUnitOfWork.acquireUnitOfWork(); | |
firstNestedUow.deleteObject(this.readInUow); | |
Employee workingCopyOfNewEmployeeInSecondNestedUow = | |
(Employee)firstNestedUow.registerObject(newEmployeeInFirstUow); | |
workingCopyOfNewEmployeeInSecondNestedUow.setAddress(addressExample2()); | |
firstNestedUow.commit(); | |
// Acquire second nested unit of work | |
// Change the new object created in the parent. | |
UnitOfWork secondNestedUow = this.firstUnitOfWork.acquireUnitOfWork(); | |
firstNameExpression = new ExpressionBuilder().get("firstName").equal("Marcus"); | |
this.readInFirstNestedUow = (Employee)secondNestedUow.readObject(Employee.class, firstNameExpression); | |
this.readInFirstNestedUow.setAddress(addressExample3()); | |
secondNestedUow.commit(); | |
// Assign correct clone from root unit of work so compare verifies works correctly. | |
this.readInFirstNestedUow = (Employee)secondNestedUow.getOriginalVersionOfObject(readInFirstNestedUow); | |
this.firstUnitOfWork.commit(); | |
} | |
public void processSecondUnitOfWork() { | |
this.secondUnitOfWork = getSession().acquireUnitOfWork(); | |
ReadObjectQuery query = new ReadObjectQuery(); | |
query.setSelectionObject(this.newEmployeeInUow); | |
Employee objectFromDatabase = (Employee)secondUnitOfWork.executeQuery(query); | |
if (!(((AbstractSession)getSession()).compareObjects(this.newEmployeeInUow, objectFromDatabase))) { | |
throw new TestErrorException("The object read from the database, '" + this.newEmployeeInUow + | |
"' does not match the originial, '" + objectFromDatabase + "."); | |
} | |
query = new ReadObjectQuery(); | |
query.setSelectionObject(this.readInFirstNestedUow); | |
objectFromDatabase = (Employee)secondUnitOfWork.executeQuery(query); | |
if (!(((AbstractSession)getSession()).compareObjects(this.readInFirstNestedUow, objectFromDatabase))) { | |
throw new TestErrorException("The object read from the database, '" + this.readInFirstNestedUow + | |
"' does not match the originial, '" + objectFromDatabase + "."); | |
} | |
Employee workingCopy = (Employee)secondUnitOfWork.registerObject(this.newEmployeeInUow); | |
changeObject(workingCopy, this.secondUnitOfWork); | |
secondUnitOfWork.release(); | |
// Use the original session for comparision | |
if (!((AbstractSession)getSession()).compareObjectsDontMatch(this.newEmployeeInUow, workingCopy)) { | |
throw new TestErrorException("The original object was changed through changing the clone."); | |
} | |
} | |
public void processThirdUnitOfWork() { | |
this.thirdUnitOfWork = getSession().acquireUnitOfWork(); | |
Employee workingCopy = (Employee)thirdUnitOfWork.registerObject(this.newEmployeeInUow); | |
changeObject(workingCopy, this.thirdUnitOfWork); | |
if (!((AbstractSession)getSession()).compareObjectsDontMatch(this.newEmployeeInUow, workingCopy)) { | |
throw new TestErrorException("The original object was changed through changing the clone."); | |
} | |
this.thirdUnitOfWork.commit(); | |
} | |
public void reset() { | |
if(getAbstractSession().isInTransaction()) { | |
getAbstractSession().rollbackTransaction(); | |
} | |
getSession().getIdentityMapAccessor().initializeAllIdentityMaps(); | |
if(listener != null) { | |
getAbstractSession().getParent().getEventManager().removeListener(listener); | |
listener = null; | |
} | |
} | |
public void setup() { | |
if (getSession().isClientSession()) { | |
listener = checkTransactionIsolation(); | |
} | |
getAbstractSession().beginTransaction(); | |
} | |
public SmallProject smallProjectExample() { | |
SmallProject smallProject = new SmallProject(); | |
smallProject.setName("Enterprise"); | |
smallProject.setDescription("A enterprise wide application using Visual J++ to report on the corporations Sybase and DB/2 database through TopLink."); | |
return smallProject; | |
} | |
public void test() throws Exception { | |
processFirstUnitOfWork(); | |
processSecondUnitOfWork(); | |
processThirdUnitOfWork(); | |
} | |
public void verify() { | |
getSession().getIdentityMapAccessor().initializeIdentityMaps(); | |
Session sessionToVerifyDelete; | |
if (getSession() instanceof RemoteSession) { | |
sessionToVerifyDelete = RemoteModel.getServerSession(); | |
} else { | |
sessionToVerifyDelete = getSession(); | |
} | |
// Verify if object deleted in the uow was deleted | |
if (!(((AbstractSession)sessionToVerifyDelete).verifyDelete(this.readInSession))) { | |
throw new TestErrorException("The object '" + this.readInSession + | |
"'deleted in the uow was not completely deleted from the database."); | |
} | |
// Verify if object deleted in the uow was deleted | |
if (!(((AbstractSession)sessionToVerifyDelete).verifyDelete(this.readInUow))) { | |
throw new TestErrorException("The object '" + this.readInUow + | |
"'deleted in the nested uow was not completely deleted from the database."); | |
} | |
ReadObjectQuery query = new ReadObjectQuery(); | |
query.setSelectionObject(this.newEmployeeInUow); | |
Employee objectFromDatabase = (Employee)getSession().executeQuery(query); | |
if (!(((AbstractSession)getSession()).compareObjects(this.newEmployeeInUow, objectFromDatabase))) { | |
throw new TestErrorException("The object read from the database, '" + this.newEmployeeInUow + | |
"' does not match the originial, '" + objectFromDatabase + "."); | |
} | |
} | |
} |