cayenne-dev mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From Aristedes Maniatis <>
Subject Making sense of callbacks
Date Thu, 29 Nov 2007 01:28:36 GMT
Even though the callback system in Cayenne 3 is simple to explain (

  ) there are some details which can bite. I'd like to create an  
overview of how I think they currently work and what issues remain:

How we use them
* set createdOn attribute in all entities
* set modifiedOn attributed in all entities
* update calculated denormalised summary fields. For example, invoice  
lines are added and payments subtracted to create an invoiceOwing  
attribute. This needs to be updated whenever a relevant record is  
created or updated.
* audit trail records. Every time a change is made to a record, a log  
entry is created (we actually use this for database replication).
* firing special events - in our system when a new payment is created,  
special credit card processing code runs, all before the ROP client  
gets a return value from the context.commit().

Now, I understand that lifecycle is tied up tightly with JPA so some  
of the naming reflects names imposed by JPA. But hopefully Cayenne  
functionality could go further.

Cayenne 2 tier

For new objects :
context.newObject() -> prePersist()
context.commitChanges() -> postPersist()

For existing objects:
context.commitChanges() -> preUpdate(), postUpdate()

Cayenne 3 tier (ROP)

For new objects :
context.commitChanges() -> prePersist(), postPersist()

For existing objects:
context.commitChanges() -> preUpdate(), postUpdate()

Object state
prePersist() in 2 tier: object attributes and relationships are all null
prePersist() in ROP: object attributes populated but relationships  
always invalid

preUpdate(): attributes and relationships are all dependable. In  
addition, within the context being committed, we can follow a  
relationship from one object to another and see its new updated  


* prePersist() is only useful as a place to set object attributes  
(such as creationDate) since you cannot follow relations reliably in a  
ROP environment.

* postUpdate() and postPersist() are useful for changes which do not  
need to be committed atomically with the original commit. So good for  
creating log records, but not ideal for updating invoiceOwing.

* postPersist() is badly named. It is really postInsert()

* we need preInsert()

Additional callbacks
preCommit() and postCommit() listeners on the context itself would be  
really useful. They should run AFTER the per object listeners have all  
run for that phase. This would be one per context and allow a single  
entry point which can examine and touch all objects in the context  
before commit or just after.

Additional ROP feature
If an object is touched within a pre-commit phase on the server, the  
ROP client does not get the updated object refreshed automatically. It  
appears the response the client is either just the validation  
exception (if there is one) or "all OK". We are currently remembering  
to set the object on the client to be hollow, but it would be nice for  
the server to return all committed objects to the client.

I hope that I haven't tried to cover too much ground here. My purpose  
is to get some feedback about the above ideas, and about how hard they  
are to implement in Cayenne. Since this is a blocking issue for our  
main commercial project we are want to focus and getting these things  
clear in the Cayenne docs and making appropriate improvements.

Ari Maniatis

Level 1, 30 Wilson Street Newtown 2042 Australia
phone +61 2 9550 5001   fax +61 2 9550 4001
GPG fingerprint CBFB 84B4 738D 4E87 5E5C  5EFA EF6A 7D2E 3E49 102A

View raw message