After some more testing I found I can avoid the exception in first
instance but it will crash anyway.
The problem is deleting a User with some related SessionLogWeb
SessionLog has a relationship with User to be able to find the user
logged and the back relationship was modeled from User to SessionLog
(abstract) with Cascade.
So deleting User triggers a delete on all SessionLog related and to
verify the cascade rules of that element it tries to instanciate it.
So I changed the model to remove that back relationship and instead have
2 backs relationship with SessionLogApi and SessionLogWeb, this
generates a warning about discouraged back relationships... but allows
to progress in the cascade but just to fail a couple of levels later.
SessionLog is related with User and with ActivityLog and ActivityLog has
the same problem it has 3 back relationships (to SessionLog,
SessionLogApi and SessionLogWeb) to avoid problems I setted
ActivityLog->SessionLog as No action and left the other two as cascade,
as now it does not have any relationship requiring deleting a SessionLog
everything should be ok..... but no.
As SessionLog is related with ActivityLog it tries to remove the object
from the back relationship and thus generates and instance exception.
Caused by: org.apache.cayenne.reflect.PropertyException: [v.3.1B1 May 28
2012 18:42:43] Error unsetting to-many DataObject property: activityArray
at
org.apache.cayenne.reflect.generic.DataObjectToManyProperty.removeTarget(DataObjectToManyProperty.java:91)
at
org.apache.cayenne.ObjectContextDeleteAction$1.visitToMany(ObjectContextDeleteAction.java:206)
at
org.apache.cayenne.reflect.generic.DataObjectToManyProperty.visit(DataObjectToManyProperty.java:111)
at
org.apache.cayenne.ObjectContextDeleteAction.processDeleteRules(ObjectContextDeleteAction.java:196)
at
org.apache.cayenne.ObjectContextDeleteAction.deletePersistent(ObjectContextDeleteAction.java:112)
at
org.apache.cayenne.ObjectContextDeleteAction.performDelete(ObjectContextDeleteAction.java:91)
at
org.apache.cayenne.ObjectContextDeleteAction.processDeleteRules(ObjectContextDeleteAction.java:230)
at
org.apache.cayenne.ObjectContextDeleteAction.deletePersistent(ObjectContextDeleteAction.java:112)
at
org.apache.cayenne.ObjectContextDeleteAction.performDelete(ObjectContextDeleteAction.java:91)
at org.apache.cayenne.BaseContext.deleteObjects(BaseContext.java:712)
at
com.proton.cayenne.utils.CayenneTemplate.deleteObjects(CayenneTemplate.java:84)
at
com.proton.ks.services.business.HostingService.rejectUserRequestToDomain(HostingService.java:414)
... 119 more
Caused by: org.apache.cayenne.CayenneRuntimeException: [v.3.1B1 May 28
2012 18:42:43] Error creating object of class
'com.proton.ks.persistence.SessionLog'
at
org.apache.cayenne.reflect.PersistentDescriptor.createObject(PersistentDescriptor.java:288)
at
org.apache.cayenne.reflect.LazyClassDescriptorDecorator.createObject(LazyClassDescriptorDecorator.java:73)
at
org.apache.cayenne.access.DataContext.findOrCreateObject(DataContext.java:1178)
at
org.apache.cayenne.access.ObjectResolver.objectFromDataRow(ObjectResolver.java:151)
at
org.apache.cayenne.access.ObjectResolver.objectFromDataRow(ObjectResolver.java:137)
at
org.apache.cayenne.access.ObjectResolver.objectsFromDataRows(ObjectResolver.java:121)
at
org.apache.cayenne.access.ObjectResolver.synchronizedObjectsFromDataRows(ObjectResolver.java:102)
at
org.apache.cayenne.access.ObjectResolver.synchronizedRootResultNodeFromDataRows(ObjectResolver.java:93)
at
org.apache.cayenne.access.DataDomainQueryAction$ObjectConversionStrategy.toResultsTree(DataDomainQueryAction.java:581)
at
org.apache.cayenne.access.DataDomainQueryAction$SingleObjectConversionStrategy.convert(DataDomainQueryAction.java:637)
at
org.apache.cayenne.access.DataDomainQueryAction.interceptObjectConversion(DataDomainQueryAction.java:465)
at
org.apache.cayenne.access.DataDomainQueryAction.execute(DataDomainQueryAction.java:129)
at
org.apache.cayenne.access.DataDomain.onQueryNoFilters(DataDomain.java:754)
at
org.apache.cayenne.access.DataDomain$DataDomainQueryFilterChain.onQuery(DataDomain.java:1003)
at org.apache.cayenne.access.DataDomain.onQuery(DataDomain.java:744)
at
org.apache.cayenne.util.ObjectContextQueryAction.runQuery(ObjectContextQueryAction.java:350)
at
org.apache.cayenne.util.ObjectContextQueryAction.executePostCache(ObjectContextQueryAction.java:106)
at
org.apache.cayenne.util.ObjectContextQueryAction.execute(ObjectContextQueryAction.java:93)
at org.apache.cayenne.access.DataContext.onQuery(DataContext.java:989)
at
org.apache.cayenne.access.DataContext.performQuery(DataContext.java:978)
at
org.apache.cayenne.access.ToOneFault.doResolveFault(ToOneFault.java:81)
at
org.apache.cayenne.access.ToOneFault.resolveFault(ToOneFault.java:54)
at
org.apache.cayenne.CayenneDataObject.readProperty(CayenneDataObject.java:186)
at
org.apache.cayenne.CayenneDataObject.setToOneTarget(CayenneDataObject.java:273)
at
org.apache.cayenne.CayenneDataObject.unsetReverseRelationship(CayenneDataObject.java:363)
at
org.apache.cayenne.CayenneDataObject.removeToManyTarget(CayenneDataObject.java:234)
at
org.apache.cayenne.reflect.generic.DataObjectToManyProperty.removeTarget(DataObjectToManyProperty.java:85)
... 130 more
Caused by: java.lang.InstantiationException
at
sun.reflect.InstantiationExceptionConstructorAccessorImpl.newInstance(Unknown
Source)
at java.lang.reflect.Constructor.newInstance(Unknown Source)
at java.lang.Class.newInstance0(Unknown Source)
at java.lang.Class.newInstance(Unknown Source)
at
org.apache.cayenne.reflect.PersistentDescriptor.createObject(PersistentDescriptor.java:285)
... 156 more
I think that removing the back relationship from ActivityLog to
SessionLog can avoid the error, but I need to use that in some queries
to filter and order by User (that is a shared relationship between both
Entities).
My model can be checked at: http://db.tt/XRtJcNoL
I will try to find a workaround about this and the only way is not
creating related entities unless I am 100% sure the object will not be
deleted (in this case I think I can do that but it is a rare exception).
As things are now the abstract checkbox at Cayenne Modeller should be
removed or at least forbid creating relationship from or to abstract
entities.
The only fix I can think of is that createObject of PersistentDescriptor
should check if the class is abstract or not before trying to
instanciate it and if it is instanciate the correct subclass y possible,
but I see no way how you can identify the correct subclass with only the
ObjectId
And by the way I found what seems a Copy Paste error at performDelete
inside ObjectContextDeleteAction, there is double call to
"context.prepareForAccess(object, null, false);*" *
Ramiro
El 03/01/2013 19:16, Andrus Adamchik escribió:
Hi Ramiro,
Happy New Year to you too :)
So is it possible that the database row that causes this exception does not map
to any concrete subclass entity qualifier?
Andrus
On Jan 3, 2013, at 8:54 PM, Ramiro Aparicio <[email protected]> wrote:
Hi and happy new year to everyone,
I am back with my happy inheritance one more time.
I am using single table inheritance and just in case someone did not remember
the model here is a simplification about it:
abstract SessionLog it has relations to other tables as Log or User
SessionLogApi and SessionLogWeb that inherits from SessionLog they have
specific information about the session type and their own relations
I have found some problems with this kind of mapping but till now I have always
find a way to hack around Cayenne problems with this and today (we are really
near to put the new version with inheritance in production) I have struck
against this exception:
Caused by: org.apache.cayenne.CayenneRuntimeException: [v.3.1B1 May 28 2012
18:42:43] Error creating object of class 'com.proton.ks.persistence.SessionLog'
at
org.apache.cayenne.reflect.PersistentDescriptor.createObject(PersistentDescriptor.java:288)
at
org.apache.cayenne.reflect.LazyClassDescriptorDecorator.createObject(LazyClassDescriptorDecorator.java:73)
at
org.apache.cayenne.access.DataContext.findOrCreateObject(DataContext.java:1178)
at
org.apache.cayenne.access.ObjectResolver.objectFromDataRow(ObjectResolver.java:151)
at
org.apache.cayenne.access.ObjectResolver.objectFromDataRow(ObjectResolver.java:137)
at
org.apache.cayenne.access.ObjectResolver.objectsFromDataRows(ObjectResolver.java:121)
at
org.apache.cayenne.access.ObjectResolver.synchronizedObjectsFromDataRows(ObjectResolver.java:102)
at
org.apache.cayenne.access.ObjectResolver.synchronizedRootResultNodeFromDataRows(ObjectResolver.java:93)
at
org.apache.cayenne.access.DataDomainQueryAction$ObjectConversionStrategy.toResultsTree(DataDomainQueryAction.java:581)
at
org.apache.cayenne.access.DataDomainQueryAction$SingleObjectConversionStrategy.convert(DataDomainQueryAction.java:637)
at
org.apache.cayenne.access.DataDomainQueryAction.interceptObjectConversion(DataDomainQueryAction.java:465)
at
org.apache.cayenne.access.DataDomainQueryAction.execute(DataDomainQueryAction.java:129)
at org.apache.cayenne.access.DataDomain.onQueryNoFilters(DataDomain.java:754)
at
org.apache.cayenne.access.DataDomain$DataDomainQueryFilterChain.onQuery(DataDomain.java:1003)
at org.apache.cayenne.access.DataDomain.onQuery(DataDomain.java:744)
at
org.apache.cayenne.util.ObjectContextQueryAction.runQuery(ObjectContextQueryAction.java:350)
at
org.apache.cayenne.util.ObjectContextQueryAction.executePostCache(ObjectContextQueryAction.java:106)
at
org.apache.cayenne.util.ObjectContextQueryAction.execute(ObjectContextQueryAction.java:93)
at org.apache.cayenne.access.DataContext.onQuery(DataContext.java:989)
at org.apache.cayenne.access.DataContext.performQuery(DataContext.java:978)
at
org.apache.cayenne.util.RelationshipFault.resolveFromDB(RelationshipFault.java:89)
at
org.apache.cayenne.util.PersistentObjectList.resolvedObjectList(PersistentObjectList.java:301)
at
org.apache.cayenne.util.PersistentObjectList.toArray(PersistentObjectList.java:278)
at java.util.ArrayList.(ArrayList.java:131)
at
org.apache.cayenne.ObjectContextDeleteAction.toCollection(ObjectContextDeleteAction.java:124)
at
org.apache.cayenne.ObjectContextDeleteAction.processDeleteRules(ObjectContextDeleteAction.java:153)
at
org.apache.cayenne.ObjectContextDeleteAction.deletePersistent(ObjectContextDeleteAction.java:112)
at
org.apache.cayenne.ObjectContextDeleteAction.performDelete(ObjectContextDeleteAction.java:91)
at org.apache.cayenne.BaseContext.deleteObjects(BaseContext.java:698)
at
com.proton.cayenne.utils.CayenneTemplate.deleteObject(CayenneTemplate.java:79)
at
com.proton.ks.services.business.HostingService.rejectUserRequestToDomain(SourceFile:413)
... 120 more
Caused by: java.lang.InstantiationException
at
sun.reflect.InstantiationExceptionConstructorAccessorImpl.newInstance(InstantiationExceptionConstructorAccessorImpl.java:30)
at java.lang.reflect.Constructor.newInstance(Constructor.java:513)
at java.lang.Class.newInstance0(Class.java:355)
at java.lang.Class.newInstance(Class.java:308)
at
org.apache.cayenne.reflect.PersistentDescriptor.createObject(PersistentDescriptor.java:285)
... 150 more
In case it is not clear in the trace I am only doing a
context.deleteObjects(user) that user is cascading throught the model and in
some way hitting a SessionLogApi or SessionLogWeb which Cayenne treats as a
standard SessionLog and fails.
I hope Andrus can help with this, at least with a way to circunvent the error
as the fix, if feasible, will take some time to arrive a Cayenne release
version.
As always just ask for model, tests, or whatever as I am happy to provide them.
Thank you in advance and merry christmas