You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@cayenne.apache.org by Lachlan Deck <la...@gmail.com> on 2007/12/05 00:06:24 UTC

Re: Making sense of callbacks

Hi there,

On 29/11/2007, at 11:22 PM, Andrus Adamchik wrote:

> On Nov 29, 2007, at 10:56 AM, Aristedes Maniatis wrote:
>
>>> * prePersist() is only useful as a place to set object attributes  
>>> (such as creationDate) since you cannot follow relations reliably  
>>> in a ROP environment.
>
> True, and a workaround would be to support relationships for  
> transient objects. Something Kevin was bringing up on multiple  
> occasions.

Yeah the prePersist on server (from ROP commit) would just give you a  
chance to initialise things that the client is unaware of I would've  
thought.

Otherwise, there are no relationships to follow, really... as they've  
not been initialised yet. i.e., it's a new object that's being  
initialised / inserted into a context. The fact that you see the  
attributes already populated on server when committing from the  
client is because the prePersist in 3 tier on server is really a  
second constructor (or third). i.e., in the real java constructor you  
do nothing because the object has not as yet been inserted into an  
editing context, in prePersist on client you initialise attributes/ 
relationships, in prePersist on server, you can initialise other  
stuff if needed... but you don't yet have in view the object as it  
was on the client (i.e., relationships aren't faulted).

That fulfils most general cases.

>>> * 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.
>
> Another way to go about atomic commits is to set up a manual  
> transaction that spans a request scope. I think that's an  
> appropriate solution.

Making such changes in another context (in post[Persist|Update| 
Remove]) seems like reasonable practice, the question is when will  
such changes be reflected in the former context.

>>> * postPersist() is badly named. It is really postInsert()
>>> * we need preInsert()
>
> per JPA "persist" is "insert", so the naming is correct if somewhat  
> confusing.

Hmm. Yeah I don't think it's badly named either. It's the  
counterpart, prePersist, that doesn't match conceptually (as with  
preUpdate) in terms of when it is fired. The point is that we're  
missing (logically) a callback.

i.e., there does need to be a callback that prePersist currently  
provides for when objects are initiated, but there's no complimentary  
callback to preUpdate for those new objects just prior to commit.  
Perhaps the JPA assumes you'll initiate your objects as per normal  
Java via Constructors and such whereas in Cayenne you don't touch the  
object until it's been inserted into a Context and thus the current  
prePersist is your constructor.

>> * if preUpdate() is just for existing records we still need a  
>> preInsert().
>
> I wonder if we should just call "preUpdate" for new objects in  
> addition to prePersist.

That doesn't sound like a nice fit. i.e., they're currently in nice  
pairs like:
preUpdate --> postUpdate
preRemove --> postRemove

It would seem (to me at least), then, that you'd want (fired at the  
same times as above):
prePersist --> postPersist

And replace current prePersist with something like postNew or  
postCreate or something.

So calling preUpdate would be better than nothing, if you're  
constrained by the JPA, but doesn't seem like the clean solution FWIW.

What do you think?

with regards,
--

Lachlan Deck