jo-source / jo-client-platform

The jo-client-platform is a CRUD application framework for java
http://jo-source.github.io/jo-client-platform
2 stars 0 forks source link

Deleting two linked beans fails #20

Closed abentele closed 8 years ago

abentele commented 9 years ago

folgendes Problem:

 dialog: "Deletion failed" with "unknown error" console:

java.lang.IllegalArgumentException: Removing a detached instance <hier steht die Klasse für die Link-Entity>#861
    at org.hibernate.ejb.event.EJB3DeleteEventListener.performDetachedEntityDeletionCheck(EJB3DeleteEventListener.java:65)
    at org.hibernate.event.def.DefaultDeleteEventListener.onDelete(DefaultDeleteEventListener.java:107)
    at org.hibernate.impl.SessionImpl.fireDelete(SessionImpl.java:965)
    at org.hibernate.impl.SessionImpl.delete(SessionImpl.java:948)
    at org.hibernate.engine.CascadingAction$1.cascade(CascadingAction.java:145)
    at org.hibernate.engine.Cascade.cascadeToOne(Cascade.java:392)
    at org.hibernate.engine.Cascade.cascadeAssociation(Cascade.java:335)
    at org.hibernate.engine.Cascade.cascadeProperty(Cascade.java:204)
    at org.hibernate.engine.Cascade.cascadeCollectionElements(Cascade.java:425)
    at org.hibernate.engine.Cascade.cascadeCollection(Cascade.java:362)
    at org.hibernate.engine.Cascade.cascadeAssociation(Cascade.java:338)
    at org.hibernate.engine.Cascade.cascadeProperty(Cascade.java:204)
    at org.hibernate.engine.Cascade.cascade(Cascade.java:161)
    at org.hibernate.event.def.DefaultDeleteEventListener.cascadeBeforeDelete(DefaultDeleteEventListener.java:328)
    at org.hibernate.event.def.DefaultDeleteEventListener.deleteEntity(DefaultDeleteEventListener.java:267)
    at org.hibernate.event.def.DefaultDeleteEventListener.onDelete(DefaultDeleteEventListener.java:162)
    at org.hibernate.event.def.DefaultDeleteEventListener.onDelete(DefaultDeleteEventListener.java:73)
    at org.hibernate.impl.SessionImpl.fireDelete(SessionImpl.java:956)
    at org.hibernate.impl.SessionImpl.delete(SessionImpl.java:934)
    at org.hibernate.ejb.AbstractEntityManagerImpl.remove(AbstractEntityManagerImpl.java:869)
    at org.jowidgets.cap.service.jpa.impl.SyncJpaDeleterServiceImpl$1.execute(SyncJpaDeleterServiceImpl.java:67)
    at org.jowidgets.cap.service.jpa.impl.SyncJpaDeleterServiceImpl$1.execute(SyncJpaDeleterServiceImpl.java:61)
    at org.jowidgets.cap.service.impl.SyncExecutorServiceImpl.execute(SyncExecutorServiceImpl.java:250)
    at org.jowidgets.cap.service.impl.SyncExecutorServiceImpl.execute(SyncExecutorServiceImpl.java:169)
    at org.jowidgets.cap.service.jpa.impl.SyncJpaDeleterServiceImpl.delete(SyncJpaDeleterServiceImpl.java:78)
    at org.jowidgets.cap.service.impl.DeleterServiceAdapter.delete(DeleterServiceAdapter.java:53)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:606)
    at org.jowidgets.cap.security.service.impl.SecureServiceDecoratorProviderImpl$SecurityInvocationHandler.invoke(SecureServiceDecoratorProviderImpl.java:111)
    at com.sun.proxy.$Proxy642.delete(Unknown Source)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:606)
    at org.jowidgets.cap.service.hibernate.impl.CancelServicesDecoratorProviderImpl$CancelableInvoker.invoke(CancelServicesDecoratorProviderImpl.java:201)
    at org.jowidgets.cap.service.hibernate.impl.CancelServicesDecoratorProviderImpl$CancelableInvoker.access$300(CancelServicesDecoratorProviderImpl.java:139)
    at org.jowidgets.cap.service.hibernate.impl.CancelServicesDecoratorProviderImpl$CancelInvocationHandler.invokeAsyncSignature(CancelServicesDecoratorProviderImpl.java:134)
    at org.jowidgets.cap.common.tools.proxy.AbstractCapServiceInvocationHandler.invoke(AbstractCapServiceInvocationHandler.java:60)
    at com.sun.proxy.$Proxy642.delete(Unknown Source)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:606)
    at org.jowidgets.cap.service.jpa.impl.JpaServicesDecoratorProviderImpl$JpaInvocationHandler.invokeAsyncSignature(JpaServicesDecoratorProviderImpl.java:236)
    at org.jowidgets.cap.common.tools.proxy.AbstractCapServiceInvocationHandler.invoke(AbstractCapServiceInvocationHandler.java:60)
    at com.sun.proxy.$Proxy642.delete(Unknown Source)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:606)
    at org.jowidgets.cap.remoting.server.GenericRemoteMethod.invokeMethodOnService(GenericRemoteMethod.java:172)
    at org.jowidgets.cap.remoting.server.GenericRemoteMethod.invoke(GenericRemoteMethod.java:68)
    at org.jowidgets.cap.remoting.server.GenericRemoteMethod.invoke(GenericRemoteMethod.java:47)
    at org.jowidgets.invocation.service.server.impl.MethodImpl.invoke(MethodImpl.java:104)
    at org.jowidgets.invocation.server.impl.InvocationServerServiceRegistryImpl.onMethodInvocation(InvocationServerServiceRegistryImpl.java:75)
    at org.jowidgets.invocation.server.impl.InvocationServerMessageReceiver.onMessage(InvocationServerMessageReceiver.java:69)
    at org.jowidgets.message.impl.http.server.Connection.doRun(Connection.java:75)
    at org.jowidgets.message.impl.http.server.Connection.doRun(Connection.java:80)
    at org.jowidgets.message.impl.http.server.Connection.doRun(Connection.java:80)
    at org.jowidgets.message.impl.http.server.Connection.access$000(Connection.java:44)
    at org.jowidgets.message.impl.http.server.Connection$1.run(Connection.java:65)
    at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1145)
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:615)
    at java.lang.Thread.run(Thread.java:744)

Analyse:

    class BeanEntity {
    …
           @OneToMany(cascade = CascadeType.REMOVE, fetch = FetchType.LAZY, mappedBy ="destination", orphanRemoval = true)
           private Set<LinkBean> sourceToDestinationLinks = new HashSet<LinkBean>();

           @OneToMany(cascade = CascadeType.REMOVE, fetch = FetchType.LAZY, mappedBy = "source", orphanRemoval = true)
           private Set<LinkBean> destinationToSourceLinks = new HashSet<LinkBean>();
    ..
    }

Mögliche Lösungen (Ideen):

herrgrossmann commented 8 years ago

Ich habe versucht den Fehler im Kitchensink 2 example wie folgt zu reproduzieren:

  1. Neue Person Test1 angelegt
  2. Neue Person Test2 angelegt
  3. Test2 als Kinde von Test ein verlinkt (im Children Knoten des Baums hinzugefügt)
  4. Test1 und Test2 in der Tabelle gelöscht

Der Fehler tritt so nicht auf.

Vermutung: Die h2 DB verhält sich anders als Oracle

Andreas, könntest du das persistence.xml des Sample2 bei dir so anpassen, dass es auf eine Oracle geht, ich habe die nächsten 2 Wochen nicht die Möglichkeit dazu, und dann Testen ob der Fehler mit der obigen Anleitung und Oracle fehlschlägt?

Kannst du in deiner Applikation gegen einen jo-client-platform snapshot bauen und den SyncJpaDeleterServiceImpl wie folgt modifizieren und prüfen ob das dann das Problem lösen würde:

executorServiceBuilder.setExecutor(new IBeanExecutor<BEAN_TYPE, Void>() { @Override public BEAN_TYPE execute(final BEAN_TYPE data, final Void parameter, final IExecutionCallback executionCallback) { CapServiceToolkit.checkCanceled(executionCallback); interceptor.beforeDelete(data, executionCallback); if (data != null) { EntityManagerProvider.get().remove(data); EntityManagerProvider.get().flush(); } CapServiceToolkit.checkCanceled(executionCallback); return null; } });

Dann würde zumindest nach jedem remove der Session Cache geflusht.

abentele commented 8 years ago

zum Kommentar:

Es ist wahrscheinlich, dass der Fehler tatsächlich durch eigenen Code (im Interceptor) entstanden ist. Ich gehe dem weiter nach.

herrgrossmann commented 8 years ago

Hast du eine Idee, was bei dir anders ist?

Von meinem iPhone gesendet

Am 18.01.2016 um 13:06 schrieb Andreas Bentele notifications@github.com:

zum Kommentar:

der Fehler lässt sich mit dem Sample auch unter Oracle nicht reproduzieren das eingefügte flush ist keine Lösung: Fehler tritt auch damit noch auf — Reply to this email directly or view it on GitHub.

abentele commented 8 years ago

Fehler aufgrund flush() im eigenen Interceptor Code. Insofern kein Fehler in jo-cap.

Der Fehler wäre so nicht aufgetreten, wenn die Identities jeweils in Einzel-Transaktionen geladen und gelöscht worden wären. Auf der anderen Seite erwartet der Benutzer vielleicht eher eine Transaktion und nicht mehrere bei einer Aktion.

Von mir aus kann das Ticket also geschlossen werden.

herrgrossmann commented 8 years ago

Ok, danke für die Info.

Von meinem iPhone gesendet

Am 18.01.2016 um 14:17 schrieb Andreas Bentele notifications@github.com:

Fehler aufgrund flush() im eigenen Interceptor Code. Insofern kein Fehler in jo-cap.

Der Fehler wäre so nicht aufgetreten, wenn die Identities jeweils in Einzel-Transaktionen geladen und gelöscht worden wären. Auf der anderen Seite erwartet der Benutzer vielleicht eher eine Transaktion und nicht mehrere bei einer Aktion.

Von mir aus kann das Ticket also geschlossen werden.

— Reply to this email directly or view it on GitHub.