/******************************************************************************* * Copyright (c) 1998, 2015 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 + "."); } } }