// $HeadURL$ // $Id$ // // Copyright © 2006, 2010, 2011, 2012 by the President and Fellows of Harvard College. // // Screensaver is an open-source project developed by the ICCB-L and NSRB labs // at Harvard Medical School. This software is distributed under the terms of // the GNU General Public License. package edu.harvard.med.screensaver.db; import javax.persistence.EntityManager; import javax.persistence.PersistenceContext; import org.apache.log4j.Logger; import org.hibernate.Hibernate; import org.joda.time.LocalDate; import org.springframework.test.annotation.IfProfileValue; import edu.harvard.med.screensaver.model.Volume; import edu.harvard.med.screensaver.model.cherrypicks.CherryPickAssayPlate; import edu.harvard.med.screensaver.model.cherrypicks.CherryPickLiquidTransfer; import edu.harvard.med.screensaver.model.cherrypicks.CherryPickLiquidTransferStatus; import edu.harvard.med.screensaver.model.cherrypicks.CherryPickRequest; import edu.harvard.med.screensaver.model.cherrypicks.LabCherryPick; import edu.harvard.med.screensaver.model.libraries.Copy; import edu.harvard.med.screensaver.model.libraries.CopyUsageType; import edu.harvard.med.screensaver.model.libraries.Library; import edu.harvard.med.screensaver.model.libraries.PlateType; import edu.harvard.med.screensaver.model.libraries.Well; import edu.harvard.med.screensaver.model.screens.CherryPickScreening; import edu.harvard.med.screensaver.model.screens.Screen; import edu.harvard.med.screensaver.model.screens.ScreenType; import edu.harvard.med.screensaver.model.users.AdministratorUser; import edu.harvard.med.screensaver.model.users.LabHead; import edu.harvard.med.screensaver.model.users.ScreeningRoomUser; import edu.harvard.med.screensaver.test.AbstractSpringPersistenceTest; import edu.harvard.med.screensaver.test.MakeDummyEntities; /** * See <a href= * "http://forge.abcd.harvard.edu/gf/project/screensaver/tracker/?action=TrackerItemEdit&tracker_item_id=2516" * >[#2516]</a> */ @IfProfileValue(name = "demonstrate.hibernate.bugs", value = "true") public class ProxyInitializationTest extends AbstractSpringPersistenceTest { private static final Logger log = Logger.getLogger(ProxyInitializationTest.class); @PersistenceContext protected EntityManager entityManager; protected void setUp() throws Exception { super.setUp(); genericEntityDao.doInTransaction(new DAOTransaction() { @Override public void runTransaction() { Library library = MakeDummyEntities.makeDummyLibrary(1, ScreenType.RNAI, 1); Well well = library.getWells().iterator().next(); Copy copy = library.createCopy((AdministratorUser) library.getCreatedBy(), CopyUsageType.CHERRY_PICK_SOURCE_PLATES, "A"); copy.findPlate(1000).withPlateType(PlateType.ABGENE).withWellVolume(new Volume(10)); genericEntityDao.persistEntity(library); Screen screen = dataFactory.newInstance(Screen.class); screen.setFacilityId("1"); screen.setLabHead(dataFactory.newInstance(LabHead.class)); screen.setLeadScreener(dataFactory.newInstance(LabHead.class)); screen.setScreenType(ScreenType.RNAI); CherryPickRequest cpr = screen.createCherryPickRequest(dataFactory.newInstance(AdministratorUser.class), dataFactory.newInstance(ScreeningRoomUser.class), new LocalDate()); cpr.setTransferVolumePerWellApproved(new Volume(1)); cpr.setRequestedBy(screen.getLeadScreener()); LabCherryPick lcp = cpr.createScreenerCherryPick(well).createLabCherryPick(well); CherryPickAssayPlate cpap = cpr.createCherryPickAssayPlate(0, 0, PlateType.ABGENE); lcp.setAllocated(copy); lcp.setMapped(cpap, 0, 0); AdministratorUser admin1 = new AdministratorUser("Admin1", "User"); CherryPickLiquidTransfer cplt = screen.createCherryPickLiquidTransfer(admin1, screen.getLeadScreener(), new LocalDate(), CherryPickLiquidTransferStatus.SUCCESSFUL); cplt.addCherryPickAssayPlate(cpap); genericEntityDao.persistEntity(screen); } }); } class TestTxn implements DAOTransaction { public CherryPickRequest _cpr; public CherryPickScreening _screening; @Override public void runTransaction() { log.info("initial session:" /* TODO */); ScreeningRoomUser originalPerformedBy = _cpr.getRequestedBy(); log.info("original performedBy class=" + originalPerformedBy.getClass()); // Screen screen = genericEntityDao.reloadEntity(_cpr.getScreen()); // CherryPickRequest cpr = genericEntityDao.reloadEntity(_cpr); /* calling Hibernate.initialize does not fix the problem */ //Hibernate.initialize(screen.getLeadScreener()); /* calling genericEntityDao.findEntityById DOES fix the problem */ //ScreeningRoomUser reloadedPerformedBy = genericEntityDao.findEntityById(ScreeningRoomUser.class, originalPerformedBy.getEntityId()); /* this custom HQL fixes the problem */ //ScreeningRoomUser reloadedPerformedBy = genericEntityDao.findEntitiesByHql(ScreeningRoomUser.class, "from ScreeningRoomUser x where x = ?", originalPerformedBy).get(0); /* this custom HQL, which is the same as that generated by the original reloadEntity() call, recreates the problem */ //ScreeningRoomUser reloadedPerformedBy = genericEntityDao.findEntitiesByHql(ScreeningRoomUser.class, "from LabHead x where x.id = ?", originalPerformedBy.getEntityId()).get(0); /* this call which requests a ScreeningRoomUser type explicitly DOES fix the problem */ //ScreeningRoomUser reloadedPerformedBy = genericEntityDao.findEntityById(ScreeningRoomUser.class, originalPerformedBy.getEntityId(), true); /* this call which requests a LabHead type explicitly does NOT fix the problem */ //ScreeningRoomUser reloadedPerformedBy = genericEntityDao.findEntityById(LabHead.class, originalPerformedBy.getEntityId(), true); /* * the original code, that causes the problem; returns a non-proxy instance, and so differs from * Screen.leadScreener */ ScreeningRoomUser reloadedPerformedBy = genericEntityDao.reloadEntity(originalPerformedBy); /* * if we load the performedBy entity before the screen and cherryPickRequest, then these latter two can be loaded * with the non-proxy instance, which fixes the problem */ Screen screen = genericEntityDao.reloadEntity(_cpr.getScreen()); CherryPickRequest cpr = genericEntityDao.reloadEntity(_cpr); assertSame(screen.getLeadScreener(), reloadedPerformedBy); assertSame(cpr.getRequestedBy(), reloadedPerformedBy); log.info("pre-eager-fetch cpr requestedBy initialized: " + Hibernate.isInitialized(cpr.getRequestedBy())); log.info("pre-eager-fetch screen lead screener initialized: " + Hibernate.isInitialized(screen.getLeadScreener())); log.info("pre-eager-fetch session:" /* TODO */); genericEntityDao.needReadOnly(screen, Screen.leadScreener); log.info("post-eager-fetch cpr requestedBy initialized: " + Hibernate.isInitialized(cpr.getRequestedBy())); log.info("post-eager-fetch screen lead screener initialized: " + Hibernate.isInitialized(screen.getLeadScreener())); log.info("post-eager-fetch session:" /* TODO */); assertTrue(Hibernate.isInitialized(screen.getLeadScreener())); assertTrue(Hibernate.isInitialized(cpr.getRequestedBy())); } }; public void testInitializeExtantProxy() { TestTxn txn = new TestTxn(); txn._cpr = genericEntityDao.findAllEntitiesOfType(CherryPickRequest.class, true, CherryPickRequest.requestedBy).get(0); log.info("pre-txn cpr requestedBy initialized: " + Hibernate.isInitialized(txn._cpr.getRequestedBy())); log.info("pre-txn cpr requestedBy: " + txn._cpr.getRequestedBy().getClass() + " " + txn._cpr.getRequestedBy().getEntityId()); genericEntityDao.doInTransaction(txn); // log.info("post txn screening.screen.leadScreener=" + txn._screening.getScreen().getLeadScreener().getClass() + " " + // txn._screening.getScreen().getLeadScreener()); //txn._cpr.getRequestedBy().getLastName(); // txn._screen.getLeadScreener().getScreensaverUserId(); //txn._screen.getLeadScreener().getEntityId(); } }