-->
These old forums are deprecated now and set to read-only. We are waiting for you on our new forums!
More modern, Discourse-based and with GitHub/Google/Twitter authentication built-in.

All times are UTC - 5 hours [ DST ]



Forum locked This topic is locked, you cannot edit posts or make further replies.  [ 3 posts ] 
Author Message
 Post subject: Best practice for Interceptor implementations?
PostPosted: Mon Oct 18, 2004 12:12 pm 
Beginner
Beginner

Joined: Mon Sep 27, 2004 4:28 pm
Posts: 44
The Manning book and the Hibernate documentation seem to largely ignore the Interceptor concept. I would like to make use of it in a number of places, but I wanted to know if there is a good best-practices write-up on them somewhere.

Should I take the absense of documentation about them as a warning not to use them? Or are they so simple and self-explanatory that there wasn't much concern about covering them in the official (and unofficial) docs?

Maybe there's a thorough article on them that I've missed. At any rate, if anyone has some helpful pointers (or warnings) about how to best make use of Interceptor implementations, please let me know.

Specifically, I'm hoping to use them to build a fairly in-depth audit record for some of my beans.

thanks,
Phill


Top
 Profile  
 
 Post subject:
PostPosted: Mon Oct 18, 2004 3:28 pm 
Hibernate Team
Hibernate Team

Joined: Mon Aug 25, 2003 9:11 pm
Posts: 4592
Location: Switzerland
Read chapter 8 of HiA... There are numerous examples everywhere on the Hibernate website.

_________________
JAVA PERSISTENCE WITH HIBERNATE
http://jpwh.org
Get the book, training, and consulting for your Hibernate team.


Top
 Profile  
 
 Post subject: Interceptors
PostPosted: Tue Oct 26, 2004 8:19 pm 
Newbie

Joined: Tue Oct 26, 2004 7:22 pm
Posts: 1
Yes, I have read the Interceptor chapter.

Here is what I have observed about interceptors.

You basically define an EntityInterceptor and attach it to the session.

In your interceptor, you can implement methods like

onSave()
onLoad() etc

(Look at the api docs for a full list of methods that u have to impl)

SO you can do what u want in these methods, perhaps logging, auditing etc.. One can think of several other things that can be done here.

The API docs say that u need to return true if your method changes anything in the bean or entity that is being intercepted. So make sure that u return true if u modify the entity.

However, I have noticed the following.

Say I were inserting/ creating a a new bean, the onsave() method is called, however, I have noticed that any changes that u do to the bean/entity are not applied to the bean directly when it is being inserted.

The following happens,

First a INSERT is done using the actual values on the bean/entity,
and then an UPDATE is done using the values again on the changed bean.

I am not sure why it is done like this, meaning a two step process.


WEll, I have run into problems because of this:

Here is the scenario.

Assume that u have an entity that relates to a table in the db.
Now, let us assime that there is a non null col which is Fkey.

Now say I create a new bean and then save it, and I make my interceptor
set an object for the non null col attribute on my entity, It fails to insert the bean as the two step process fails, because in the first step, we get a
NOT NULL SQL Error!

I have noticed the onsave method do the following:

private Serializable doSave(
final Object object,
Key key,
final ClassPersister persister,
final boolean replicate,
final boolean useIdentityColumn,
final Cascades.CascadingAction cascadeAction,
final Object anything)
throws HibernateException {

if ( persister.implementsValidatable() ) ( (Validatable) object ).validate();

Serializable id;
if (useIdentityColumn) {
id = null;
executeInserts();
}
else {
id = key.getIdentifier();
}

// Put a placeholder in entries, so we don't recurse back and try to save() the
// same object again. QUESTION: should this be done before onSave() is called?
// likewise, should it be done before onUpdate()?
addEntry(object, SAVING, null, id, null, LockMode.WRITE, useIdentityColumn, persister, false); //okay if id is null here

// cascade-save to many-to-one BEFORE the parent is saved
cascading++;
try {
Cascades.cascade(this, persister, object, cascadeAction, Cascades.CASCADE_BEFORE_INSERT_AFTER_DELETE, anything);
}
finally {
cascading--;
}

Object[] values = persister.getPropertyValues(object);
Type[] types = persister.getPropertyTypes();

boolean substitute = false;
if (!replicate) {

substitute = interceptor.onSave( object, id, values, persister.getPropertyNames(), types );

//keep the existing version number in the case of replicate!
if ( persister.isVersioned() ) {
substitute = Versioning.seedVersion(
values, persister.getVersionProperty(), persister.getVersionType()
) || substitute;
}
}

if ( persister.hasCollections() ) {
//TODO: make OnReplicateVisitor extend WrapVisitor
if (replicate) {
OnReplicateVisitor visitor = new OnReplicateVisitor(this, id);
visitor.processValues(values, types);
}
WrapVisitor visitor = new WrapVisitor(this);
// substitutes into values by side-effect
visitor.processValues(values, types);
substitute = substitute || visitor.isSubstitutionRequired();
}


if (substitute) persister.setPropertyValues(object, values);

TypeFactory.deepCopy(values, types, persister.getPropertyUpdateability(), values);
nullifyTransientReferences(values, types, useIdentityColumn, object);
checkNullability(values, persister, false);

if (useIdentityColumn) {
ScheduledIdentityInsertion insert = new ScheduledIdentityInsertion(values, object, persister, this);
insert.execute();
executions.add(insert);
id = insert.getGeneratedId();
persister.setIdentifier(object, id);
key = new Key(id, persister);
checkUniqueness(key, object);
}

Object version = Versioning.getVersion(values, persister);
addEntity(key, object);
addEntry(object, LOADED, values, id, version, LockMode.WRITE, useIdentityColumn, persister, replicate);
nonExists.remove(key);

if (!useIdentityColumn) {
insertions.add( new ScheduledInsertion( id, values, object, persister, this ) );
}

// cascade-save to collections AFTER the collection owner was saved
cascading++;
try {
Cascades.cascade(this, persister, object, cascadeAction, Cascades.CASCADE_AFTER_INSERT_BEFORE_DELETE, anything);
}
finally {
cascading--;
}

return id;

}


In the above method in the SessionImpl.java, we get the values and types

Object[] values = persister.getPropertyValues(object);
Type[] types = persister.getPropertyTypes();

before we call the interceptor onSave() method

substitute = interceptor.onSave( object, id, values, persister.getPropertyNames(), types );


well, say we modify the object in the onSave() method, and return true.


Later down the method..
we do the following

if (substitute) persister.setPropertyValues(object, values);

well, as I understand it, we copy the values array back on to the object, at which point in time the attribute that I have set on the object in the interceptor are nulled out!!!

Well, I am not sure if this a problem with the persister implementation because it only copies the new values in to the object!!

Please let me know if I have made any wrong assumptions about how interceptors are supposed to work. I did not want to file a bug yet, as I wanted to invoke a disussion on interceptors.

thanks,
kiran


Top
 Profile  
 
Display posts from previous:  Sort by  
Forum locked This topic is locked, you cannot edit posts or make further replies.  [ 3 posts ] 

All times are UTC - 5 hours [ DST ]


You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum

Search for:
© Copyright 2014, Red Hat Inc. All rights reserved. JBoss and Hibernate are registered trademarks and servicemarks of Red Hat, Inc.