You are viewing a plain text version of this content. The canonical link for it is here.
Posted to users@isis.apache.org by Michael Xiao <mi...@gmail.com> on 2014/02/02 02:58:27 UTC

Re: Regards to Audit Service

Hi Dan,

Thanks very much for your reply.

We are using Isis 1.3.0 (with the 1.3.1 wicket viewer). Hmm.... may be
worth trying the latest 1.3.1 and see if solves the problem.

I did a bit more testing today; I suspect it MIGHT be an issue related to
multi-threading. As said, the *enlistCreated *method was only invoked by
the FrameworkSynchronizer which updates the value of property
changedObjectProperties in a *new thread*. Upon the committing of the
transaction,  the master thread (the batch job thread) reads the property,
and creates audit entries based on it. In case if the master thread
finishes earlier than the thread updating the changedObjectProperties, the
program may pick up a partially completed list/map. However, this is just
my understanding. Might be wrong. :0) Any thoughts? Thanks in advance.


IsisTransaction
==============================================================
public void enlistUpdating(ObjectAdapter adapter)
 {
   enlist(adapter, PublishedObject.ChangeKind.UPDATE);

   for (ObjectAssociation property :
adapter.getSpecification().getAssociations(Contributed.EXCLUDED,
ObjectAssociation.Filters.PROPERTIES)) {
      AdapterAndProperty aap = AdapterAndProperty.of(adapter, property);
      if (property.isNotPersisted()) {
          continue;
      }

     PreAndPostValues papv = PreAndPostValues.pre(aap.getPropertyValue());
     this.*changedObjectProperties*.put(aap, papv);
   }
 }


Regards,
Michael



On 31 January 2014 22:23, Dan Haywood <da...@haywood-associates.co.uk> wrote:

> On 31 January 2014 01:34, Michael Xiao <mi...@gmail.com> wrote:
>
> > Hello Dan,
> >
> > This is my first email after using the Isis for more than a year. I've
> been
> > working with David Tildesley and we both loved the framework. Thank you
> for
> > the great work!!!
> >
>
> You're welcome, glad you've enjoyed using the framework.  I know from David
> that it's a commercial system so there's limits on what you can say, but
> it'd be great to have a little write-up of your app/system/product for the
> Isis website.  It's only through that sort of material will the community
> grow faster.
>
>
>
> >
> > David has urged me to drop you an email to discuss an "issue" we found
> > yesterday, which may relate to the audit function :0)
> > [snip]
> >
> > All entities including their relationships had been persisted correctly.
> > However, the auditing for employment position assignment change, was not
> > always triggered and persisted.
> >
> > I've done a few tests around this. What I've noticed is that if I run
> this
> > task in (Eclipse) debug mode, and add a break-point in
> > IsisTransaction.enlistUpdating method, the audit entry can be saved
> without
> > any problem. However, if running this without any pause, there is no
> > guarantee the audit entry will be logged.
> >
> > Not sure what actually caused this. Wonder if you guys have encountered
> > this before. Can you please advise?
> >
> >
> Hmm, tricky one... don't have a magic bullet for you, I'm afraid.  I have
> some a couple of ideas, though.
>
> How enlistUpdating works is that we are relying upon DataNucleus to do a
> callback to Isis when an entity is dirtied by it.  If - while in the
> debugger - you look at the callstack you should see a call through
> FrameworkSynchronizer class - this (and also IsisLifeCycleListener which
> delegates to it) is where Isis gets notified by DN that an entity has
> changed.
>
> My best guess is that the act of being in the debugger (and inspecting
> variables etc) is causing an additional resolve/load of an object to
> fire... a sort of Schrodinger's cat affair.
>
> To track this down, all I can think of is to run the same commands with
> logging, once in the debugger (when it works) and once outside the debugger
> (when it sometimes doesn't) and see how the log files vary.
>
> You could, then, perhaps force a resolve of the missed entity in your
> domain code.  The IsisJdoSupport service has some methods that might help.
>  A work-around, I know, but perhaps necessary to help us understand what's
> going on.
>
>
> ~~~
> My  only other thought was whether this was due to a threading issue
> (though I very much doubt it)?  We can easily rule it out... does this only
> occur in a multi-user environment, or can you replicate just by running
> your batch job as a single task.
>
>
> ~~~
> If you could put together a simple example on github showing the issue,
> I'll gladly take a look.  Can you also confirm which version of Isis are
> you running on - is it the latest 1.3.1, or are you (even) working off
> trunk?
>
>
> Thx
> Dan
>
> PS: I'm just working on enhancements to audit service and new related
> services.  I don't think they will fix this issue, but the API of
> AuditingService is changing a little bit... a ten minute refactoring job if
> you have your own implementation.  More details to follow.
>
>
>
>
> >  Many thanks in advance.
> >
> > Best Regards,
> >
> >
> > Michael
> >
>

Re: Regards to Audit Service

Posted by Michael Xiao <mi...@gmail.com>.
Thanks Dan,

Will try uploading the code somewhere and let you know.

Regards,
Michael


On 2 February 2014 21:40, Dan Haywood <da...@haywood-associates.co.uk> wrote:

> On 2 February 2014 01:58, Michael Xiao <mi...@gmail.com> wrote:
>
> > Hi Dan,
> >
> > Thanks very much for your reply.
> >
> > We are using Isis 1.3.0 (with the 1.3.1 wicket viewer). Hmm.... may be
> > worth trying the latest 1.3.1 and see if solves the problem.
> >
>
> I think you are on the latest... 1.3.1 was only an update to the wicket
> viewer. [1]
>
> >
> > I did a bit more testing today; I suspect it MIGHT be an issue related to
> > multi-threading. As said, the *enlistCreated *method was only invoked by
> > the FrameworkSynchronizer which updates the value of property
> > changedObjectProperties in a *new thread*. Upon the committing of the
> > transaction,  the master thread (the batch job thread) reads the
> property,
> > and creates audit entries based on it. In case if the master thread
> > finishes earlier than the thread updating the changedObjectProperties,
> the
> > program may pick up a partially completed list/map. However, this is just
> > my understanding. Might be wrong. :0) Any thoughts? Thanks in advance.
> >
> >
> It does sound like a possible reason, but it's a bid hard to say without
> seeing all the code and how the master thread (that sounds like it is
> co-ordinating the work/doing auditing) and child threads (that generate
> stuff) interact.
>
> In Isis (as I'm sure you've figured out), each transaction is scoped by
> thread by installing IsisContextThreadLocal as the implementation of
> IsisContext.  I'm presuming that each child thread uses its own
> IsisContext?  But if instead it's the master thread that creates an
> IsisContext and then hands it off to the child threads, then I'm not sure
> what would happen.
>
> So I guess what I'm asking is:
> a) how does the master thread know that the child thread has finished? and
> b) how do the two threads share information (the changedObjectProperties
> map)?
>
> Can you upload the relevant code somewhere so I can take a look?
>
> Cheers
> Dan
>
>
>
> > IsisTransaction
> > ==============================================================
> > public void enlistUpdating(ObjectAdapter adapter)
> >  {
> >    enlist(adapter, PublishedObject.ChangeKind.UPDATE);
> >
> >    for (ObjectAssociation property :
> > adapter.getSpecification().getAssociations(Contributed.EXCLUDED,
> > ObjectAssociation.Filters.PROPERTIES)) {
> >       AdapterAndProperty aap = AdapterAndProperty.of(adapter, property);
> >       if (property.isNotPersisted()) {
> >           continue;
> >       }
> >
> >      PreAndPostValues papv =
> PreAndPostValues.pre(aap.getPropertyValue());
> >      this.*changedObjectProperties*.put(aap, papv);
> >    }
> >  }
> >
> >
> > Regards,
> > Michael
> >
> >
>

Re: Regards to Audit Service

Posted by Dan Haywood <da...@haywood-associates.co.uk>.
On 2 February 2014 01:58, Michael Xiao <mi...@gmail.com> wrote:

> Hi Dan,
>
> Thanks very much for your reply.
>
> We are using Isis 1.3.0 (with the 1.3.1 wicket viewer). Hmm.... may be
> worth trying the latest 1.3.1 and see if solves the problem.
>

I think you are on the latest... 1.3.1 was only an update to the wicket
viewer. [1]

>
> I did a bit more testing today; I suspect it MIGHT be an issue related to
> multi-threading. As said, the *enlistCreated *method was only invoked by
> the FrameworkSynchronizer which updates the value of property
> changedObjectProperties in a *new thread*. Upon the committing of the
> transaction,  the master thread (the batch job thread) reads the property,
> and creates audit entries based on it. In case if the master thread
> finishes earlier than the thread updating the changedObjectProperties, the
> program may pick up a partially completed list/map. However, this is just
> my understanding. Might be wrong. :0) Any thoughts? Thanks in advance.
>
>
It does sound like a possible reason, but it's a bid hard to say without
seeing all the code and how the master thread (that sounds like it is
co-ordinating the work/doing auditing) and child threads (that generate
stuff) interact.

In Isis (as I'm sure you've figured out), each transaction is scoped by
thread by installing IsisContextThreadLocal as the implementation of
IsisContext.  I'm presuming that each child thread uses its own
IsisContext?  But if instead it's the master thread that creates an
IsisContext and then hands it off to the child threads, then I'm not sure
what would happen.

So I guess what I'm asking is:
a) how does the master thread know that the child thread has finished? and
b) how do the two threads share information (the changedObjectProperties
map)?

Can you upload the relevant code somewhere so I can take a look?

Cheers
Dan



> IsisTransaction
> ==============================================================
> public void enlistUpdating(ObjectAdapter adapter)
>  {
>    enlist(adapter, PublishedObject.ChangeKind.UPDATE);
>
>    for (ObjectAssociation property :
> adapter.getSpecification().getAssociations(Contributed.EXCLUDED,
> ObjectAssociation.Filters.PROPERTIES)) {
>       AdapterAndProperty aap = AdapterAndProperty.of(adapter, property);
>       if (property.isNotPersisted()) {
>           continue;
>       }
>
>      PreAndPostValues papv = PreAndPostValues.pre(aap.getPropertyValue());
>      this.*changedObjectProperties*.put(aap, papv);
>    }
>  }
>
>
> Regards,
> Michael
>
>