Thanks for taking the time to document this, Oscar... I've added a note to
our website for this recommendation here [1]

Dan

[1]
http://isis.apache.org/components/objectstores/jdo/managed-1-to-m-relationships.html

~~~~~~~~~~~~~

On 1 May 2014 09:21, GESCONSULTOR - Óscar Bou <o....@gesconsultor.com>wrote:

>
> Just for others with the same problem.
>
> Seems there's a bug somewhere in DN, but there's an easy workaround.
>
>
> The situation generating the NPE was the following:
>
> Domain Entity:
>
> @PersistenceCapable
> @Inheritance(strategy = InheritanceStrategy.NEW_TABLE)
> public class InformationSystem extends ApplicationComponent {
>
>
>     // {{ ParentSystem (property)
>     private InformationSystem parentSystem;
>
>     @MemberOrder(sequence = "100")
>     @Column(allowsNull = "true")
>     public InformationSystem getParentSystem() {
>         return this.parentSystem;
>     }
>
>     public void setParentSystem(final InformationSystem
> partOfInformationSystem) {
>         this.parentSystem = partOfInformationSystem;
>     }
>
>     // }}
>
>     // {{ SubSystems (Collection)
>     @Persistent(mappedBy = "parentSystem", dependentElement = "false")
>     private SortedSet<InformationSystem> subSystems = new
> TreeSet<InformationSystem>();
>
>     @MemberOrder(sequence = "500")
>     public SortedSet<InformationSystem> getSubSystems() {
>         return this.subSystems;
>     }
>
>     public void setSubSystems(final SortedSet<InformationSystem>
> subSystems) {
>         this.subSystems = subSystems;
>     }
>
>     // }}
>
>    ...
>
> }
>
> Obviously, the exception is thrown because we are using managed
> relationships, so DN tries to keep synched both sides.
>
> That's relevant, because in this case we were trying to set the
> relationship as this:
>
> subSystem.setParentSystem(informationSystem);
>
> When executed, the previous line was causing the NPE on DataNucleus.
>
> If, instead, we update the bidir relationship with:
>
> informationSystem.getSubSystems().add(subSystem);
>
>
> It runs smoothly.
>
> As it was inside a Fixture, and we weren't wrapping the call, as in (an
> "idiom" we have adopted in all our domain code, unless properties/actions
> are hidden or disabled):
>
> wrapperFactory.wrap(subSystem).setParentSystem(informationSystem);
>
> The exception was thrown when persisting another entity, which in our
> case, also executes a this.getContainer().flush(), as any action executed
> inside a wrap(..).
>
>
> So, summarizing, when having a bidirectional 1-n relationship that must be
> automatically managed by DataNucleus, it's preferred to "add" to the
> parent's child collection, than set the parent on the child.
>
>
> HTH,
>
> Oscar
>
>
>
>
>
> El 29/04/2014, a las 23:13, Dan Haywood <d...@haywood-associates.co.uk>
> escribió:
>
>
> On 29 April 2014 21:34, GESCONSULTOR - Óscar Bou <o....@gesconsultor.com
> >wrote:
>
>
> Yes... relMgr is what I find to be null...
>
> I noticed it sometimes worked, sometimes not... I thought about a limit in
> nested transactions or something similar... But I didn't noticed it was a
> ConcurrentMap.
>
> The only option seems the one you pointed. The Map has been cleared and
> not initialized on:
>
>       if (getManageRelations() && managedRelationDetails != null)
>       {
>           managedRelationDetails.clear();
>       }
>
>
>
> I think it's probably worth asking on the DN forum (Andy Jefferson).  Say
> you work with me.  He'll probably ask for a test case, but I guess you
> could explain that's intermittent and possibly a threading issue.
>
> Also, do note that we're not on the latest version of DN; very outside
> change that it's a bug that's been recently fixed.
>
>
>
>
>
> While trying as a workaround to "hide" the exception in a try - catch
> block, as in:
>
>
>        // Send pending changes to the database.
>        try {
>            this.getContainer().flush();
>        } catch (final NullPointerException e) {
>            // Do nothing... Seems there's a bug in DN when updating
> Managed
>            // Relationships.
>            // It only occurs sometimes (it's lacy loaded; it's a
> multi-threaded
>            // ConcurrentMap.
>            System.err.print(String.format("XMS - FLUSING ERROR !!!: %s",
> e.getStackTrace().toString()));
>        }
>
>
>
> Then the Isis transaction was not in the correct state:
>
> Caused by: java.lang.IllegalStateException: state is: MUST_ABORT
> at
> org.apache.isis.core.commons.ensure.Ensure.ensureThatState(Ensure.java:111)
> at
>
> org.apache.isis.core.runtime.system.transaction.IsisTransaction.flush(IsisTransaction.java:363)
>
> at
>
> org.apache.isis.core.runtime.system.transaction.IsisTransactionManager.flushTransaction(IsisTransactionManager.java:311)
> at
>
> org.apache.isis.core.runtime.persistence.internal.RuntimeContextFromSession$7.flush(RuntimeContextFromSession.java:223)
> at
>
> org.apache.isis.core.metamodel.services.container.DomainObjectContainerDefault.flush(DomainObjectContainerDefault.java:229)
>
> Not sure how to deal with it ...
>
>
>
>
> Not sure I recommend this, but if you want to hack it, you could register a
> custom implementation of DomainObjectContainer that resets the
> IsisTransaction back to a good state (setState to IN_PROGRESS and
> setAbortCause to null.
>
> in isis.properties:
>
>
> isis.persistor.domain-object-container=org.apache.isis.core.metamodel.services.container.DomainObjectContainerDefault
>
> change as required...
>
> As I say, rather hacky, not sure it's to be recommended.
>
> Dan
>
>
>
> Óscar Bou Bou
> Responsable de Producto
> Auditor Jefe de Certificación ISO 27001 en BSI
> CISA, CRISC, APMG ISO 20000, ITIL-F
>
>    902 900 231 / 620 267 520
>    http://www.twitter.com/oscarbou
>
>    http://es.linkedin.com/in/oscarbou
>
>    http://www.GesConsultor.com <http://www.gesconsultor.com/>
>
>
>
> Este mensaje y los ficheros anexos son confidenciales. Los mismos
> contienen información reservada que no puede ser difundida. Si usted ha
> recibido este correo por error, tenga la amabilidad de eliminarlo de su
> sistema y avisar al remitente mediante reenvío a su dirección electrónica;
> no deberá copiar el mensaje ni divulgar su contenido a ninguna persona.
> Su dirección de correo electrónico junto a sus datos personales constan en
> un fichero titularidad de Gesdatos Software, S.L. cuya finalidad es la de
> mantener el contacto con Ud. Si quiere saber de qué información disponemos
> de Ud., modificarla, y en su caso, cancelarla, puede hacerlo enviando un
> escrito al efecto, acompañado de una fotocopia de su D.N.I. a la siguiente
> dirección: Gesdatos Software, S.L. , Paseo de la Castellana, 153 bajo -
> 28046 (Madrid), y Avda. Cortes Valencianas num. 50, 1ºC - 46015 (Valencia).
> Asimismo, es su responsabilidad comprobar que este mensaje o sus archivos
> adjuntos no contengan virus informáticos, y en caso que los tuvieran
> eliminarlos.
>
>
>
>
>
>

Reply via email to