Skip to Content.
Sympa Menu

grouper-dev - hibernate versioning

Subject: Grouper Developers Forum

List archive

hibernate versioning


Chronological Thread 
  • From: Chris Hyzer <>
  • To: "" <>
  • Subject: hibernate versioning
  • Date: Tue, 24 Mar 2009 13:36:36 -0400
  • Accept-language: en-US
  • Acceptlanguage: en-US

Hibernate row level locking is now implemented in Grouper 1.5. This is also
referred to as optimistic locking (since you are optimistic that no one else
is editing the same row you are). How it works is when you retrieve a
record, there is an incrementing integer id (for that row), and when you
update or delete that row, it will use that id in the where clause and
increment it. So if someone else has edited it before you commit, you will
get a GrouperStaleObjectStateException.

https://bugs.internet2.edu/jira/browse/GRP-255

This is generally a good thing, so you dont have two processes stepping on
toes, but it can also be a little painful to turn on when we have an
installed base not using it. So there is a global property in the
grouper.properties where you can disable optimistic locking if you are having
too many problems:

dao.optimisticLocking = true

I was hoping to do the mappings and some core data layer changes to make this
work and be done, but like most things, it wasnt that simple. Hooks is the
main problem. Now, anytime we have a hook which edits the registry, we need
to make sure we are doing so with the exact object instance that the calling
context is using. e.g. if you are in a group type hook (someone adds a type
to a group), and you want to turn the group into a composite (yes, I did have
this issue with the auto-include/exclude hook), then you have a reference to
the GroupTypeTuple, and you need a reference to the group. Before, you would
just use a GroupFinder.findById(groupTypeTuple.getGroupUUID()), but that will
throw stale state exceptions since it is a different instance. So now you
just call groupTypeTuple.retrieveGroup(). I dont have all instances
available to all instances in hooks, but I will be adding them as I think of
it or as we need it. Let me know.

Another major rub was group attributes. We have been in denial that group
attributes are separate from groups, and we have been treating the group and
attributes as one object. So on an insert or update (or delete) of group, it
would automatically sync up the local map of attributes with the DB. Its
hard to explain why this doesnt work anymore, but basically while syncing up
the attributes, an attribute hook can save the group, which syncs up the
attributes, and when it finally returns to the caller (in the middle of
syncing attributes), and an insert of an attribute is now an update or an
overwrite etc. It is complicated. So now group attributes are separate
entities (like adding a type or membership to a group), and we dont have this
problem. However, things are different.

You no longer need to call group.store() after editing attributes. Each
attribute set or delete will cause DB queries to go across the wire. the
group.dbVersion fields dont have attributes (non core attributes...
name/description/etc are still in there). If we need a hook which looks at
multiple non core attributes at once we can make a higher level hook. Let me
know if you have a need. Most of the group attribute methods do not fit with
the new exception handling or new group/attribute architecture, so they are
deprecated, and you will see new and better methods there.

All unit tests pass.

Here are the change log instructions:

https://wiki.internet2.edu/confluence/display/GrouperWG/Grouper+change+log+v1.5

# 2009/03/24: v1.5 HEAD: Group attributes changed a bit.

* If you use them in custom code, make sure your code still compiles, and
if you can remove deprecated calls (each deprecated method is overloaded with
a new method).
* You do not need to call group.store() for an attribute change anymore,
it is only needed for Group fields (name, displayName, description, etc).
* If you are making changes to the registry in a hook, you need to not
use a finder to find the object you are updating, but rather use the object
model provided to you. This will prevent stale state exception, might want
to send your hook code to the email list (or just the core grouper
developers) for review.
* If you are using attributes to access core fields
(group.getAttributes().get("name")), please refactor so just call
group.getName()
* Non core group fields are not in the
group.dbVersionDifferentFields()... you should use an AttributeHook if you
need to trigger based on non group core fields (or we can add a high level
hook for group edits, discuss with the core team)

# 2009/03/24: v1.5 HEAD: Merge grouper.properties with
grouper.example.properties:

* 2009/03/24: Add in the optimistic locking setting:
dao.optimisticLocking = true. If you get stale state object exceptions, you
can set this to false, and let the grouper team know (might be due to a
custom hook we can advise on tweaking)


Regards,
Chris


  • hibernate versioning, Chris Hyzer, 03/24/2009

Archive powered by MHonArc 2.6.16.

Top of Page