(Sorry - premature post)

Hi David,

I've written a couple of these so let me give you some advice:

Create an Interface "HibernateAware" that your actions will implement
if they want a Hibernate Session and Transaction injected.

public interface HibernateAware
{
 void setSession(Session session);
 void setTransaction(Transaction tx);
}

Next, you only want to create a Session and Transaction if the Action
implements HibernateAware,

Object action = invocation.getAction();
if (action instanceof HibernateAware)
{
  HibernateAware ha = (HibernateAware) action;
  ha.setSession(...)
  ha.setTransaction(...)
 ...
}
else
{
return invocation.invoke();
}


Next and a bigger issue;  I think it is a really bad idea to do the
commit in the interceptor.  If the commit fails it is too late to tell
the user or do anything about it since your result and response has
already been rendered.  You need to understand how the interceptor
stack works, but the key point is the first interceptor or action that
returns a result string causes the result to be processed and the
response (jsp page) to be rendered before the interceptor stack starts
to unwind. SO if the commit fails, it's too late in the interceptor to
do anything about it, you have already rendered the everything is OK
page to the user.

What I do is to commit the transaction in the Action then if it fails
I can return a FAILURE result.

Now if you need a Transaction open in order to allow lazy loading
while rendering the jsp page what I will do is begin a second
transaction.

Then in the interceptor I will Rollback the transaction and close the
session since nothing in the page rendering should modify any
entities.

Next; your interceptor needs to close the session.

Your option instead of storing the session in the action is to store
it and the transaction in ThreadLocal storage. In fact if you copied
your HIbernateUtil from many of the examples it may already be storing
the session in ThreadLocal storage as this is very common.

One thing you need to be aware of regarding ThreadLocal storage and
web servers; most web servers use a thread pool for executing requests
and once your request is finished the thread gets put back into the
pool for use on a future request.  This can be a problem if you don't
properly clean up all ThreadLocal storage, for example if you leave a
session open and in ThreadLocal storage when the thread gets re-used
for the next request it will already have a session in it and it will
be reused.  This usually happens when an exception occurs and the
session doesn't get closed so chances are the session is corrupt or
dead which will cause this later request to fail unexpectedly.

I would put the call to invocation.action() in a try block with a
finally block that closes the session and cleans up any other
THreadLocal stuff you have so it doesn't pollute the thread pool.




On Wed, Nov 10, 2010 at 4:44 PM, Greg Lindholm <greg.lindh...@gmail.com> wrote:
> Hi David,
>
> I've written a couple of these so let me give you some advice:
>
> Create an Interface "HibernateAware" that your actions will implement
> if they want a Hibernate Session and Transaction injected.
>
> public interface HibernateAware
> {
>
> }
>
> On Wed, Nov 10, 2010 at 3:45 PM, Altenhof, David Aron
> <dalte...@iupui.edu> wrote:
>> Hello all, I'm trying to write my own interceptor, and have a question or 
>> two...
>>
>> I'd like to write a simple interceptor that will manage hibernate sessions 
>> for me. I know that there are more sophisticated ways to do this using 
>> Spring, etc. but this is mainly a learning experience.
>>
>> So, given the simple code below, my questions are:
>>
>>
>> 1)      Does it appear to be thread-safe?
>>
>> 2)      Is there any condition, other than an unhandled exception elsewhere 
>> in the app, that would cause the transaction not to be committed?
>>
>> 3)      Are there any better places to stash the session and transaction 
>> references other than the Action? I tried putting it on the value stack, but 
>> that wreaked havoc with the Params interceptor.
>>
>> Thanks!
>>
>> David
>>
>> public class HibernateInterceptor implements Interceptor {
>>
>>                public String intercept(ActionInvocation actionInvocation) 
>> throws Exception {
>>
>>                                Session sess = HibernateUtil.getSession();
>>                                Transaction tx = sess.beginTransaction();
>>
>>                                // Put sess, tx in Action
>>                                Action action = (Action) 
>> actionInvocation.getAction();
>>                                if(action instanceof MyAction ) {
>>                                                
>> ((MyAction)action).setHibSession(sess);
>>                                                
>> ((MyAction)action).setHibTransaction(tx);
>>                                }
>>
>>                                String rslt = actionInvocation.invoke();
>>
>>                                try {
>>                                                // Try to commit:
>>                                                tx.commit();
>>
>>                                } catch (Exception ex) {
>>                                                // Try to rollback and do 
>> other stuff here ...
>>                                }
>>                                return rslt;
>>                }
>>                public void destroy() {}
>>                public void init() {}
>> }
>>
>>
>

---------------------------------------------------------------------
To unsubscribe, e-mail: user-unsubscr...@struts.apache.org
For additional commands, e-mail: user-h...@struts.apache.org

Reply via email to