Community
Participate
Working Groups
Some minor issues prevent the tests in eclipselink.jpa.wdf.test to be executed with shared cache enabled: - In some tests, the id of a Vehicle entity is assigned manually, although the Vehicle entity has automatic id generation. Vehilce has subclasses Car and Truck. Some tests creates a Car with id=1. The vehicle is cached in the cache with id 1. After the test, the cache content is evicted. Later, a different test created a Truck with id=1. This is not possible any longer as the data structure in the cache assumes that Vehicles with id=1 are Cars, always. - The cache content should be evicted before test execution to make tests indenpendent of each other.
Created attachment 188601 [details] proposed patch Proposed patch. Has no effect on test execution with disabled cache. Tested on MySQL: cache disabled: OK. cache enabled: Fixes the issues described in this bug. No additional test failures. WDF tests with cache enabled are not productive yet.
It would be helpful to know what operations are failing in the test. The issue here is an Entity is using the same ID as another Entity within the same class hierarchy. The other issue is that because EclipseLink has an Object cache and not just a data cache Cache.evict* does not remove the Entity instance from the cache but notifies the cache that the data must be refreshed on next access. To remove the Entity instances, and not just the data, the EclipseLink JPAHelper.getServerSession(entityManagerFactory).getIdentityMapAccessor().initializeAllIdentityMaps() API can be used between single threaded test runs. Some improvements could be made to invalidation to ensure this issue is resolved. 1 - when invalidated CacheKeys should be removed from any hard caches. 2 - existence checking should check for invalidation if it does not. 3 - based on the failing test EclipseLink's invalidation response could be updated to ensure invalidated CacheKeys did not prevent the desired behaviour.
As an example, please consider the following sequence: // create a car with id=99 em.getTransaction().begin(); Vehicle vehicle = new Car(); vehicle.setId(99); em.persist(vehicle); em.getTransaction().commit(); em.clear(); // remove the car again em.getTransaction().begin(); vehicle = em.find(Vehicle.class, 99); em.remove(vehicle); em.getTransaction().commit(); em.clear(); // create a bicycle with same id em.getTransaction().begin(); vehicle = new Bicycle(); vehicle.setId(id); em.persist(vehicle); em.getTransaction().commit(); // fails with exception below em.clear(); vehicle = em.find(Vehicle.class, id); This sequence fails with the following exception: javax.persistence.RollbackException: Exception [EclipseLink-32] (Eclipse Persistence Services - @VERSION@.@QUALIFIER@): org.eclipse.persistence.exceptions.DescriptorException Exception Description: Trying to set value [0] for instance variable [numberOfGears] of type [short] in the object. The specified object is not an instance of the class or interface declaring the underlying field, or an unwrapping conversion has failed. Internal Exception: java.lang.IllegalArgumentException: Can not set short field org.eclipse.persistence.testing.models.wdf.jpa1.employee.Bicycle.numberOfGears to org.eclipse.persistence.testing.models.wdf.jpa1.employee.Car Mapping: org.eclipse.persistence.mappings.DirectToFieldMapping[numberOfGears-->TMP_VEHICLE.NUM_GEARS] Descriptor: RelationalDescriptor(org.eclipse.persistence.testing.models.wdf.jpa1.employee.Bicycle --> [DatabaseTable(TMP_VEHICLE)]) at org.eclipse.persistence.internal.jpa.transaction.EntityTransactionImpl.commitInternal(EntityTransactionImpl.java:102) at org.eclipse.persistence.internal.jpa.transaction.EntityTransactionImpl.commit(EntityTransactionImpl.java:63) at org.eclipse.persistence.testing.framework.wdf.AbstractBaseTest$ResourceLocalEnvironment.commitTransaction(AbstractBaseTest.java:132) at org.eclipse.persistence.testing.framework.wdf.AbstractBaseTest$ResourceLocalEnvironment.commitTransactionAndClear(AbstractBaseTest.java:138) at org.eclipse.persistence.testing.tests.wdf.jpa1.inheritance.ChangeSubclassTest.testFindVehicle(ChangeSubclassTest.java:53) at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source) at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source) at java.lang.reflect.Method.invoke(Unknown Source) at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:44) at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:15) at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:41) at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:20) at org.junit.internal.runners.statements.RunBefores.evaluate(RunBefores.java:28) at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:76) at org.eclipse.persistence.testing.framework.wdf.SkipBugzillaTestRunner.runChild(SkipBugzillaTestRunner.java:184) at org.eclipse.persistence.testing.framework.wdf.SkipBugzillaTestRunner.runChild(SkipBugzillaTestRunner.java:38) at org.junit.runners.ParentRunner$3.run(ParentRunner.java:193) at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:52) at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:191) at org.junit.runners.ParentRunner.access$000(ParentRunner.java:42) at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:184) at org.junit.runners.ParentRunner.run(ParentRunner.java:236) at org.eclipse.persistence.testing.framework.wdf.SkipBugzillaTestRunner.run(SkipBugzillaTestRunner.java:50) at org.eclipse.jdt.internal.junit4.runner.JUnit4TestReference.run(JUnit4TestReference.java:49) at org.eclipse.jdt.internal.junit.runner.TestExecution.run(TestExecution.java:38) at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:467) at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:683) at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.run(RemoteTestRunner.java:390) at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.main(RemoteTestRunner.java:197) Caused by: Exception [EclipseLink-32] (Eclipse Persistence Services - @VERSION@.@QUALIFIER@): org.eclipse.persistence.exceptions.DescriptorException Exception Description: Trying to set value [0] for instance variable [numberOfGears] of type [short] in the object. The specified object is not an instance of the class or interface declaring the underlying field, or an unwrapping conversion has failed. Internal Exception: java.lang.IllegalArgumentException: Can not set short field org.eclipse.persistence.testing.models.wdf.jpa1.employee.Bicycle.numberOfGears to org.eclipse.persistence.testing.models.wdf.jpa1.employee.Car Mapping: org.eclipse.persistence.mappings.DirectToFieldMapping[numberOfGears-->TMP_VEHICLE.NUM_GEARS] Descriptor: RelationalDescriptor(org.eclipse.persistence.testing.models.wdf.jpa1.employee.Bicycle --> [DatabaseTable(TMP_VEHICLE)]) at org.eclipse.persistence.exceptions.DescriptorException.illegalArgumentWhileSettingValueThruInstanceVariableAccessor(DescriptorException.java:700) at org.eclipse.persistence.internal.descriptors.InstanceVariableAttributeAccessor.setAttributeValueInObject(InstanceVariableAttributeAccessor.java:188) at org.eclipse.persistence.mappings.DatabaseMapping.setAttributeValueInObject(DatabaseMapping.java:1428) at org.eclipse.persistence.mappings.foundation.AbstractDirectMapping.mergeIntoObject(AbstractDirectMapping.java:1097) at org.eclipse.persistence.internal.descriptors.ObjectBuilder.mergeIntoObject(ObjectBuilder.java:3444) at org.eclipse.persistence.internal.descriptors.ObjectBuilder.mergeChangesIntoObject(ObjectBuilder.java:3381) at org.eclipse.persistence.internal.sessions.MergeManager.mergeChangesOfWorkingCopyIntoOriginal(MergeManager.java:748) at org.eclipse.persistence.internal.sessions.MergeManager.mergeChangesOfWorkingCopyIntoOriginal(MergeManager.java:623) at org.eclipse.persistence.internal.sessions.MergeManager.mergeChanges(MergeManager.java:267) at org.eclipse.persistence.internal.sessions.UnitOfWorkImpl.mergeChangesIntoParent(UnitOfWorkImpl.java:3246) at org.eclipse.persistence.internal.sessions.RepeatableWriteUnitOfWork.mergeChangesIntoParent(RepeatableWriteUnitOfWork.java:368) at org.eclipse.persistence.internal.sessions.RepeatableWriteUnitOfWork.commitRootUnitOfWork(RepeatableWriteUnitOfWork.java:282) at org.eclipse.persistence.internal.sessions.UnitOfWorkImpl.commitAndResume(UnitOfWorkImpl.java:1135) at org.eclipse.persistence.internal.jpa.transaction.EntityTransactionImpl.commitInternal(EntityTransactionImpl.java:84) ... 29 more Caused by: java.lang.IllegalArgumentException: Can not set short field org.eclipse.persistence.testing.models.wdf.jpa1.employee.Bicycle.numberOfGears to org.eclipse.persistence.testing.models.wdf.jpa1.employee.Car at sun.reflect.UnsafeFieldAccessorImpl.throwSetIllegalArgumentException(Unknown Source) at sun.reflect.UnsafeFieldAccessorImpl.throwSetIllegalArgumentException(Unknown Source) at sun.reflect.UnsafeFieldAccessorImpl.ensureObj(Unknown Source) at sun.reflect.UnsafeShortFieldAccessorImpl.set(Unknown Source) at java.lang.reflect.Field.set(Unknown Source) at org.eclipse.persistence.internal.descriptors.InstanceVariableAttributeAccessor.setAttributeValueInObject(InstanceVariableAttributeAccessor.java:141) ... 41 more The attribute numberOfGears of the Bicycle cannot be set as the Bicycle used to be a Car (the 2nd level cache used to manage an entity with the same id, which was a Car).
Created attachment 197292 [details] Simple Repro for this bug.
Created attachment 197564 [details] Patch avoiding the issue for the bulk of the tests and adding one particular test to reproduce the issue This patch fixes the issue for the bulk of the tests (it avoids changing the subclass of a cached entity). To make sure that the issue is not lost, the test ChangeSubclassTest is added. Tested on SE/MySQL and JBoss/MySQL
This example has nothing to do with the Cache.evict() execution path and behaviour. It seems EntityManager.remove is not operating correctly and that is a far more severe issue.
Increasing priority. Requires investigation for 2.3.1 - potential issue with remove.
Changing target and priority. The fix for bug 336726 will address issues with remove. The issue with reassigning the same id to a new object in the same hierarchy is not yet addressed. To investigate this bug, add the attached test and fix any issues.
The Eclipselink project has moved to Github: https://github.com/eclipse-ee4j/eclipselink