Even though the callback system in Cayenne 3 is simple to explain (http://cayenne.apache.org/doc/lifecycle-callbacks.html
) 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
attributes.
Summary
-------
* 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.
Cheers
Ari Maniatis
-------------------------->
ish
http://www.ish.com.au
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
This archive was generated by hypermail 2.0.0 : Wed Nov 28 2007 - 20:29:15 EST