Property changes made in a TransactionEventHandler not persisted

135 views
Skip to first unread message

brian

unread,
Oct 12, 2012, 10:46:17 AM10/12/12
to ne...@googlegroups.com
Hello,

I've written a TransactionEventHandler that creates certain properties on newly created Nodes and Relationships.  It also modifies certain existing properties even if those properties have been modified as part of that transaction. For example, I set a modified date stamp and increment a version number on entities that have been modified. This is all done in the beforeCommit() method. The problem is that the modifications to those properties are not persisted.

Putting it more concretely.  I add a UUID, version, created date, and updated date property to all entities returned by  TransactionData.createdNodes/Relationships().  This part works fine.  However, when I receive a modified entity.  I don't appear to be able to override the value of any property that is returned from TransactionData.assignedNode/RelationshipProperties().  Take the following code where I try to set an updated time stamp on a modified Node:

Assume that I've iterated over all modified Node properties using TransactionData.assignedNodeProperties() to find all entities (Nodes) associated with the modified properties.  I then do:

for (PropertyContainer node: changedNodes) {
    node.setProperty("updated_at", formatISO8601Date());
}

I do a similar thing to increment the value of a version stamp.

The problem is that this new value is not persisted.  After the transaction has completed, I looked at the affected Nodes and the old values for the "updated_at" property are still there.  In fact in debugging this, I put a breakpoint in this code to confirm that this code was in fact being executed.  I also put a breakpoint in afterCommit() and saw that the values for those properties were the old values--as if the setProperty() calls in beforeCommit() had no affect.

One more piece of information, the REST driver I'm using (node-neo4j) has a Node.save() method.  When a previously-persisted Node is saved, node-neo4j does an update by sending all properties in a .../properties request.  So even properties that have not been added or modified are included in this request.

Is it expected behavior that properties that are being modified in a transaction can't be modified in TransactionEventHandler.beforeCommit() method?

Thanks.

-brian





brian

unread,
Oct 15, 2012, 2:54:56 PM10/15/12
to ne...@googlegroups.com
Anyone have any guidance on this?  I'm completely stumped

Thanks.

-b
 

Axel Morgner

unread,
Oct 15, 2012, 5:55:47 PM10/15/12
to ne...@googlegroups.com
Hi Brian,

not sure that I fully understand your context. Could you write a little more about how you're using Neo4j (embedded? REST server? Which driver? Server extension?)

From what I learned from Neo4j transactions, you can't be sure to see all changes made in a transaction during the beforeCommit phase:

http://docs.neo4j.org/chunked/stable/transactions-events.html: "  Right before a transaction is about to be committed the beforeCommit method is called with the entire diff of modifications made in the transaction. At this point the transaction is still running so changes can still be made. However there’s no guarantee that other handlers will see such changes since the order in which handlers are executed is undefined."

Maybe some of the Neo4j guys can shed a little light on this.

Cheers
Axel
--
 
 


--

Axel Morgner · ax...@morgner.de · @amorgner

c/o Morgner UG · Hanauer Landstr. 291a · 60314 Frankfurt · Germany
phone: +49 151 40522060 · skype: axel.morgner

structr - Open Source CMS and Web Framework based on Neo4j: http://structr.org
structr Mailing List and Forum: https://groups.google.com/forum/#!forum/structr
Graph Database Usergroup "graphdb-frankfurt", sponsored by Neo4j: http://www.meetup.com/graphdb-frankfurt
Das Sport-Sharing-Netzwerk des Deutschen Olympischen Sportbundes (DOSB): https://splink.de


brian

unread,
Oct 16, 2012, 11:36:12 AM10/16/12
to ne...@googlegroups.com
Hi,

Context:
 Neo4j Community 1.8GA
 Using REST API from Node.js via the node-neo4j driver

My Node.js code invokes a REST request to update properties on a node by doing a PUT similar to:

PUT http://localhost:7474/db/data/node/9/properties (with properties in the payload)

I've written a TransactionEventHandler.beforeCommit() method in which I mutate values that have already been changed as part of that REST request and are therefore returned from TransactionData.assignedNodeProperties().  Consider the following code:

Object propValueFromTransaction = entity.getProperty("myprop");
entity.setProperty("myprop", newMutatedValue);

After this code executes and after the entire transaction has committed, the value of the "myprop" property on the node is propValueFromTransaction, not newMutatedValue.  In other words, my setProperty call appears to have had no effect.

-brian

Mattias Persson

unread,
Oct 23, 2012, 8:59:31 AM10/23/12
to ne...@googlegroups.com
I just tried your scenario as closely as possible, with this test (added TransactionEventHandler.Adapter in case you wonder):

    @Test
    public void modifiedPropertyCanByFurtherModifiedInBeforeCommit() throws Exception
    {
        // Given
        // -- create node and set property on it in one transaction
        final String key = "key";
        final Object value1 = "the old value";
        final Object value2 = "the new value";
        final Node node = getGraphDb().createNode();
        node.setProperty( key, "initial value" );
        commit();
        // -- register a tx handler which will override a property
        getGraphDb().registerTransactionEventHandler( new TransactionEventHandler.Adapter<Void>()
        {
            @Override
            public Void beforeCommit( TransactionData data ) throws Exception
            {
                Node modifiedNode = data.assignedNodeProperties().iterator().next().entity();
                assertEquals( node, modifiedNode );
                modifiedNode.setProperty( key, value2 );
                return null;
            }
        } );
       
        // When
        newTransaction();
        node.setProperty( key, value1 );
        commit();
       
        // Then
        assertEquals( value2, node.getProperty( key ) );
    }

and it passes. How is your scenario different from mine?

2012/10/16 brian <blevi...@gmail.com>
--
 
 



--
Mattias Persson, [mat...@neotechnology.com]
Hacker, Neo Technology
www.neotechnology.com

brian

unread,
Oct 23, 2012, 9:55:35 AM10/23/12
to ne...@googlegroups.com
I think this is probably due to a bug in my code (mostly). I also had some code that checked whether properties that were not allowed to be modified by the client had been and if so I through an exception and aborted the transaction.  Part of the problem was that, in addition to my own unit test, I was driving this from the Data Browser.  It appears that the Data Browser issues 2 puts whenever you click the Save button and so I was actually getting two transactions.  The first worked, the second didn't because it appeared that I was getting the previous value for a value I had just changed in the TransactionEventHandler.  This is because the second PUT resent the data in the Data Browser form.  I have opened an issue on the double-PUT problem, but it looks like the issue I reported below is not a bug.

Thanks for taking the time to look into this.

-brian

Mattias Persson

unread,
Oct 25, 2012, 3:25:35 AM10/25/12
to ne...@googlegroups.com
Sure, no problem. Interesting with the double-PUT thingie as well.

2012/10/23 brian <blevi...@gmail.com>
Reply all
Reply to author
Forward
0 new messages