You are viewing a plain text version of this content. The canonical link for it is here.
Posted to user@struts.apache.org by "Altenhof, David Aron" <da...@iupui.edu> on 2010/11/10 21:45:49 UTC

Interceptor attempt

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() {}
}


Re: Interceptor attempt

Posted by Marcus Bond <ma...@marcusbond.me.uk>.
Generally knowledge of success / failure will be via exception throw / 
catch - you will expect certain exceptions under certain conditions and 
report an appropriate error to the user.

As for tutorial, a while ago I found a book download.. apparently a 
search in Google for "free practical apache struts2" will produce a 
handy link.. The book seems to do an ok job all around the Struts2 
landscape and introduces Spring and hibernate too.. Can't say I've 
followed it word for word  but I have used it for the odd tidbit of 
information here and there.
Marcus


On 11/11/2010 16:20, Altenhof, David Aron wrote:
> No problem,  but we're starting to veer off topic here.
>
> Of course, you'll delegate the data access to service or dao's, but ultimately your Action is going to have to know if the transaction commit succeeded if it's going to send an appropriate response (success/error) to the user. I'm sure Spring must give your action access to this through some kind of injection or AOP, but that's for another day.
>
> BTY, does anyone have a favorite Struts2/Spring/Hibernate integration tutorial that they've tested with a recent versions of the frameworks. I've tried a couple with limited success.
>
> -David
>
>
>
> -----Original Message-----
> From: Marcus Bond [mailto:marcus@marcusbond.me.uk]
> Sent: Thursday, November 11, 2010 11:01 AM
> To: user@struts.apache.org
> Subject: Re: Interceptor attempt
>
> Sorry to jump the thread David..
>
> Looks like the ThreadLocal (unique per thread) session using HibernateUtil or equivalent would be the better bet. I'd question why you need direct access to the session from within your actions anyway as you're likely to be calling methods on some service class to do any updating / querying anyway and to be simply using the action class to 'control' where to go next, so it is in these service classes that you will be trying to get hold of the session and current transaction.
> Assuming you're not requiring new transactions (equivalent of propagation="REQUIRES_NEW" in Spring AOP) for the work that goes on in your action then your interceptor could simply initiate a current transaction and then in a finally block commit or rollback as required (i.e when detecting errors) before rendering the view.
>
> Once you're done with having a go at this then I'd say, depending upon the complexity of your app, to let Spring do the mundane work for you - injecting the required service beans into your Actions and declaring the transactional stuff so your code can simply worry about the business logic and application flow and not the intricacies of getting hold of sessions and beginning / ending transactions etc.
>
> Regards,
> Marcus.
>
> On 11/11/2010 14:33, Altenhof, David Aron wrote:
>> Greg-
>>
>> Thanks for bumping my memory on when the page gets rendered. I remember reading that somewhere, but forgot when writing this. Committing the transaction in the action for save/delete seems to be the way to go.
>>
>> Regarding ThreadLocal, I'm a bit new to Java and still struggling a bit with the concept. You can simply simply call a sf.getCurrentSession().beginTransaction(); to begin and  sf.getCurrentSession().getTransaction().commit(); to commit it from anywhere in your app?
>>
>> Thanks,
>>
>> David
>>
>>
>>
>> -----Original Message-----
>> From: Greg Lindholm [mailto:greg.lindholm@gmail.com]
>> Sent: Wednesday, November 10, 2010 5:15 PM
>> To: Struts Users Mailing List
>> Subject: Re: Interceptor attempt
>>
>> (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<gr...@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
>>> <da...@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-unsubscribe@struts.apache.org
>> For additional commands, e-mail: user-help@struts.apache.org
>>
>>
>> ---------------------------------------------------------------------
>> To unsubscribe, e-mail: user-unsubscribe@struts.apache.org
>> For additional commands, e-mail: user-help@struts.apache.org
>>
>>
>>
>> __________ NOD32 5611 (20101111) Information __________
>>
>> This message was checked by NOD32 antivirus system.
>> http://www.eset.com
>>
>>
>>
>
> ---------------------------------------------------------------------
> To unsubscribe, e-mail: user-unsubscribe@struts.apache.org
> For additional commands, e-mail: user-help@struts.apache.org
>
>
> ---------------------------------------------------------------------
> To unsubscribe, e-mail: user-unsubscribe@struts.apache.org
> For additional commands, e-mail: user-help@struts.apache.org
>
>
>


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


RE: Interceptor attempt

Posted by "Altenhof, David Aron" <da...@iupui.edu>.
No problem,  but we're starting to veer off topic here.

Of course, you'll delegate the data access to service or dao's, but ultimately your Action is going to have to know if the transaction commit succeeded if it's going to send an appropriate response (success/error) to the user. I'm sure Spring must give your action access to this through some kind of injection or AOP, but that's for another day.

BTY, does anyone have a favorite Struts2/Spring/Hibernate integration tutorial that they've tested with a recent versions of the frameworks. I've tried a couple with limited success.

-David



-----Original Message-----
From: Marcus Bond [mailto:marcus@marcusbond.me.uk] 
Sent: Thursday, November 11, 2010 11:01 AM
To: user@struts.apache.org
Subject: Re: Interceptor attempt

Sorry to jump the thread David..

Looks like the ThreadLocal (unique per thread) session using HibernateUtil or equivalent would be the better bet. I'd question why you need direct access to the session from within your actions anyway as you're likely to be calling methods on some service class to do any updating / querying anyway and to be simply using the action class to 'control' where to go next, so it is in these service classes that you will be trying to get hold of the session and current transaction. 
Assuming you're not requiring new transactions (equivalent of propagation="REQUIRES_NEW" in Spring AOP) for the work that goes on in your action then your interceptor could simply initiate a current transaction and then in a finally block commit or rollback as required (i.e when detecting errors) before rendering the view.

Once you're done with having a go at this then I'd say, depending upon the complexity of your app, to let Spring do the mundane work for you - injecting the required service beans into your Actions and declaring the transactional stuff so your code can simply worry about the business logic and application flow and not the intricacies of getting hold of sessions and beginning / ending transactions etc.

Regards,
Marcus.

On 11/11/2010 14:33, Altenhof, David Aron wrote:
> Greg-
>
> Thanks for bumping my memory on when the page gets rendered. I remember reading that somewhere, but forgot when writing this. Committing the transaction in the action for save/delete seems to be the way to go.
>
> Regarding ThreadLocal, I'm a bit new to Java and still struggling a bit with the concept. You can simply simply call a sf.getCurrentSession().beginTransaction(); to begin and  sf.getCurrentSession().getTransaction().commit(); to commit it from anywhere in your app?
>
> Thanks,
>
> David
>
>
>
> -----Original Message-----
> From: Greg Lindholm [mailto:greg.lindholm@gmail.com]
> Sent: Wednesday, November 10, 2010 5:15 PM
> To: Struts Users Mailing List
> Subject: Re: Interceptor attempt
>
> (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<gr...@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 
>> <da...@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-unsubscribe@struts.apache.org
> For additional commands, e-mail: user-help@struts.apache.org
>
>
> ---------------------------------------------------------------------
> To unsubscribe, e-mail: user-unsubscribe@struts.apache.org
> For additional commands, e-mail: user-help@struts.apache.org
>
>
>
> __________ NOD32 5611 (20101111) Information __________
>
> This message was checked by NOD32 antivirus system.
> http://www.eset.com
>
>
>


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


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


Re: Interceptor attempt

Posted by Marcus Bond <ma...@marcusbond.me.uk>.
Sorry to jump the thread David..

Looks like the ThreadLocal (unique per thread) session using 
HibernateUtil or equivalent would be the better bet. I'd question why 
you need direct access to the session from within your actions anyway as 
you're likely to be calling methods on some service class to do any 
updating / querying anyway and to be simply using the action class to 
'control' where to go next, so it is in these service classes that you 
will be trying to get hold of the session and current transaction. 
Assuming you're not requiring new transactions (equivalent of 
propagation="REQUIRES_NEW" in Spring AOP) for the work that goes on in 
your action then your interceptor could simply initiate a current 
transaction and then in a finally block commit or rollback as required 
(i.e when detecting errors) before rendering the view.

Once you're done with having a go at this then I'd say, depending upon 
the complexity of your app, to let Spring do the mundane work for you - 
injecting the required service beans into your Actions and declaring the 
transactional stuff so your code can simply worry about the business 
logic and application flow and not the intricacies of getting hold of 
sessions and beginning / ending transactions etc.

Regards,
Marcus.

On 11/11/2010 14:33, Altenhof, David Aron wrote:
> Greg-
>
> Thanks for bumping my memory on when the page gets rendered. I remember reading that somewhere, but forgot when writing this. Committing the transaction in the action for save/delete seems to be the way to go.
>
> Regarding ThreadLocal, I'm a bit new to Java and still struggling a bit with the concept. You can simply simply call a sf.getCurrentSession().beginTransaction(); to begin and  sf.getCurrentSession().getTransaction().commit(); to commit it from anywhere in your app?
>
> Thanks,
>
> David
>
>
>
> -----Original Message-----
> From: Greg Lindholm [mailto:greg.lindholm@gmail.com]
> Sent: Wednesday, November 10, 2010 5:15 PM
> To: Struts Users Mailing List
> Subject: Re: Interceptor attempt
>
> (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<gr...@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
>> <da...@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-unsubscribe@struts.apache.org
> For additional commands, e-mail: user-help@struts.apache.org
>
>
> ---------------------------------------------------------------------
> To unsubscribe, e-mail: user-unsubscribe@struts.apache.org
> For additional commands, e-mail: user-help@struts.apache.org
>
>
>
> __________ NOD32 5611 (20101111) Information __________
>
> This message was checked by NOD32 antivirus system.
> http://www.eset.com
>
>
>


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


Re: Interceptor attempt

Posted by Dave Newton <da...@gmail.com>.
On Thu, Nov 11, 2010 at 9:44 AM, Martin Gainty <mg...@hotmail.com> wrote:
> i would strongly advise against issuing a commit until your app knows your DML
> has successfully completed committing the transaction before DML has completed will
> put in the line of fire from the DBA

"Don't issue a commit until DML has committed"? Is that what you're saying?

Dave

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


RE: Interceptor attempt

Posted by Martin Gainty <mg...@hotmail.com>.
i would strongly advise against issuing a commit until your app knows your DML has successfully completed
committing the transaction before DML has completed will put in the line of fire from the DBA
 
http://download.oracle.com/javase/tutorial/jdbc/basics/transactions.html
 
*feel free to ping me offline as this topic is O/T for struts*
Martin 
______________________________________________ 
Verzicht und Vertraulichkeitanmerkung/Note de déni et de confidentialité
 
Diese Nachricht ist vertraulich. Sollten Sie nicht der vorgesehene Empfaenger sein, so bitten wir hoeflich um eine Mitteilung. Jede unbefugte Weiterleitung oder Fertigung einer Kopie ist unzulaessig. Diese Nachricht dient lediglich dem Austausch von Informationen und entfaltet keine rechtliche Bindungswirkung. Aufgrund der leichten Manipulierbarkeit von E-Mails koennen wir keine Haftung fuer den Inhalt uebernehmen.
Ce message est confidentiel et peut être privilégié. Si vous n'êtes pas le destinataire prévu, nous te demandons avec bonté que pour satisfaire informez l'expéditeur. N'importe quelle diffusion non autorisée ou la copie de ceci est interdite. Ce message sert à l'information seulement et n'aura pas n'importe quel effet légalement obligatoire. Étant donné que les email peuvent facilement être sujets à la manipulation, nous ne pouvons accepter aucune responsabilité pour le contenu fourni.



 

> From: daltenho@iupui.edu
> To: user@struts.apache.org
> Subject: RE: Interceptor attempt
> Date: Thu, 11 Nov 2010 14:33:46 +0000
> 
> Greg-
> 
> Thanks for bumping my memory on when the page gets rendered. I remember reading that somewhere, but forgot when writing this. Committing the transaction in the action for save/delete seems to be the way to go. 
> 
> Regarding ThreadLocal, I'm a bit new to Java and still struggling a bit with the concept. You can simply simply call a sf.getCurrentSession().beginTransaction(); to begin and sf.getCurrentSession().getTransaction().commit(); to commit it from anywhere in your app?
> 
> Thanks,
> 
> David
> 
> 
> 
> -----Original Message-----
> From: Greg Lindholm [mailto:greg.lindholm@gmail.com] 
> Sent: Wednesday, November 10, 2010 5:15 PM
> To: Struts Users Mailing List
> Subject: Re: Interceptor attempt
> 
> (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 <gr...@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 
> > <da...@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-unsubscribe@struts.apache.org
> For additional commands, e-mail: user-help@struts.apache.org
> 
> 
> ---------------------------------------------------------------------
> To unsubscribe, e-mail: user-unsubscribe@struts.apache.org
> For additional commands, e-mail: user-help@struts.apache.org
> 
 		 	   		  

RE: Interceptor attempt

Posted by "Altenhof, David Aron" <da...@iupui.edu>.
Greg-

Thanks for bumping my memory on when the page gets rendered. I remember reading that somewhere, but forgot when writing this. Committing the transaction in the action for save/delete seems to be the way to go.  

Regarding ThreadLocal, I'm a bit new to Java and still struggling a bit with the concept. You can simply simply call a sf.getCurrentSession().beginTransaction(); to begin and  sf.getCurrentSession().getTransaction().commit(); to commit it from anywhere in your app?

Thanks,

David



-----Original Message-----
From: Greg Lindholm [mailto:greg.lindholm@gmail.com] 
Sent: Wednesday, November 10, 2010 5:15 PM
To: Struts Users Mailing List
Subject: Re: Interceptor attempt

(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 <gr...@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 
> <da...@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-unsubscribe@struts.apache.org
For additional commands, e-mail: user-help@struts.apache.org


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


Re: Interceptor attempt

Posted by Greg Lindholm <gr...@gmail.com>.
(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 <gr...@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
> <da...@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-unsubscribe@struts.apache.org
For additional commands, e-mail: user-help@struts.apache.org


Re: Interceptor attempt

Posted by Greg Lindholm <gr...@gmail.com>.
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
<da...@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-unsubscribe@struts.apache.org
For additional commands, e-mail: user-help@struts.apache.org