Announcement Announcement Module
Collapse
No announcement yet.
Find the current transactionAttributes. Page Title Module
Move Remove Collapse
X
Conversation Detail Module
Collapse
  • Filter
  • Time
  • Show
Clear All
new posts

  • Find the current transactionAttributes.

    Hello all,

    I am am using a TransactionProxyFactoryBean on my business objects to provide transactional support of course. I am using 2 data sources: Oracle database with hibernate 3.0 and Oracle Content Management SDK (CMSDK).

    CMSDK will not participate in JTA transactions so I am currently begin amd complete the CMSDK transactions using a postInterceptor. (I know this is not perfect as if hibernate fails to commit......)

    My issue is that I am beginning a CMSDK transaction for every business method call even if it is read only which is a bit of an overhead, what I would like to to is only begin a CMSDK transaction if the TransactionProxyFactoryBean's transaction attribute on the given method is not readOnly. So is it possible to find if the current transaction context is readOnly or not from my postInterceptor?

    Thanks for reading!

  • #2
    Would this do the trick?
    http://www.springframework.org/docs/...actionStatus()
    Last edited by karldmoore; Aug 29th, 2007, 11:01 AM.

    Comment


    • #3
      Originally posted by karldmoore View Post
      That link is broken. I guess it should be http://static.springframework.org/sp...sactionStatus()

      Comment


      • #4
        Ok, that was weird! Fixed now anyway.
        Last edited by karldmoore; Aug 29th, 2007, 11:01 AM.

        Comment


        • #5
          Thanks karldmoore, TransactionAspectSupport looks like just what I need. The currentTransactionInfo() is protected so I extended it to expose getTransactionAttribute().isReadOnly():

          public class MyTransactionAspectSupport extends org.springframework.transaction.interceptor.Transa ctionAspectSupport
          {
          public static boolean isCurrentTransactionReadOnly()
          {
          return currentTransactionInfo() == null || currentTransactionInfo().getTransactionAttribute() .isReadOnly();
          }
          }

          I have done some testing and it seems to work fine, thanks for your help!

          Comment


          • #6
            You can just use the public static currentTransactionStatus() method and cast the result to DefaultTransactionStatus. That is usually safe for Spring-provided transaction managers. It also provides a isReadOnly() method.

            Regards,
            Andreas

            Comment


            • #7
              Casting looks easier to me... thanks Andreas.

              Comment


              • #8
                Well either way should solve the problem . Glad the information was useful.
                Last edited by karldmoore; Aug 29th, 2007, 11:01 AM.

                Comment


                • #9
                  Greetings,

                  Would you be willing to post details of the CMSDK datasource and the postInterceptor you've built?

                  best regards,
                  Kjirsten

                  Originally posted by jimmyjones View Post
                  Hello all,

                  I am am using a TransactionProxyFactoryBean on my business objects to provide transactional support of course. I am using 2 data sources: Oracle database with hibernate 3.0 and Oracle Content Management SDK (CMSDK).

                  CMSDK will not participate in JTA transactions so I am currently begin amd complete the CMSDK transactions using a postInterceptor. (I know this is not perfect as if hibernate fails to commit......)

                  My issue is that I am beginning a CMSDK transaction for every business method call even if it is read only which is a bit of an overhead, what I would like to to is only begin a CMSDK transaction if the TransactionProxyFactoryBean's transaction attribute on the given method is not readOnly. So is it possible to find if the current transaction context is readOnly or not from my postInterceptor?

                  Thanks for reading!

                  Comment


                  • #10
                    CMSDK Interceptor

                    Here is the interceptor (before I added the read only stuff):

                    Code:
                    public class CMSDKTransactionInterceptor implements MethodInterceptor
                    {
                        private Log _log = LogFactory.getLog(this.getClass());
                    
                        private static ThreadLocal _threadLocal = new ThreadLocal();
                    
                        /**
                         * Check if this interceptor has already been applied
                         * @return true if already applied
                         */
                        private boolean interceptorAlreadyInProgress()
                        {
                            return _threadLocal.get() != null;
                        }
                    
                        /**
                         * Set the interceptor to in progress for this thread so it is not applied twice
                         */
                        private void setInterceptorInProgress()
                        {
                            _threadLocal.set(Boolean.TRUE);
                        }
                    
                        /**
                         * Unset interceptor to in progress for this thread 
                         */
                        private void unsetInterceptorInProgress()
                        {
                            _threadLocal.set(null);
                        }
                    
                        /**
                         * Begin a cmsdk transaction 
                         * @param methodInvocation methodInvocation object
                         * @return whatever the underlying method returns
                         * @throws Throwable excption here on in uderlying method
                         */
                        public Object invoke(MethodInvocation methodInvocation) throws Throwable
                        {
                            if (interceptorAlreadyInProgress())
                            {
                                _log.debug(" Aspect has already been applied... nothing to do");
                                Object ret = methodInvocation.proceed();
                    
                                return ret;
                            }
                            else
                            {
                                try
                                {
                                    //set a thread local to indicate that this interceptor has been applied
                                    setInterceptorInProgress();
                    
                                    //get the LibrarySession ascosiated with the current request
                                    LibrarySession ls = LibrarySessionHelper.getCurrentLibrarySession();
                                    Transaction transaction = null;
                    
                                    //if there is a library session acsosiated with this request, 
                                    //begin a transaction
                                    if (ls != null)
                                    {
                                        transaction = ls.beginTransaction();
                                    }
                                    else
                                    {
                                        _log.warn("No Libary Session found for this request... " + 
                                                  "this request will not be transactional");
                                    }
                    
                                    try
                                    {
                                        Object retVal = methodInvocation.proceed();
                    
                                        if (ls != null && transaction != null)
                                        {
                                            if (transaction.isCompleteable())
                                            {
                                                _log.debug("Completing transaction " + transaction);
                                                ls.completeTransaction(transaction);
                                            }
                                            else
                                            {
                                                _log.warn("Unable to complete transaction: Transaction.isCompleteable() is false");
                                            }
                                        }
                    
                                        return retVal;
                                    }
                                    catch (Exception e)
                                    {
                                        if (ls != null && transaction != null)
                                        {
                                            try
                                            {
                                                ls.abortTransaction(transaction);
                                            }
                                            catch (IfsException ifse)
                                            {
                                                //dont rethrow this exception as the causing exception will be lost, 
                                                _log.info("Transaction Rollback failed", ifse);
                                            }
                                        }
                                        throw e;
                                    }
                                }
                                finally
                                {
                                    //always unset the thread local as this interceptor is complete
                                    unsetInterceptorInProgress();
                                }
                            }
                        }
                    }
                    I use ThreadLocal again to associate the users library session with the thread serving the current request.

                    Code:
                    public class LibrarySessionHelper
                    {
                        /**
                         * Thread local to hold the library session reference
                         */
                        private static ThreadLocal _threadLocal = new ThreadLocal();
                    
                    
                        /**
                         * Private constructor to prevent instantiation
                         */
                        private LibrarySessionHelper()
                        {
                        }
                    
                        /**
                         * Set the LibrarySession to be available for the remainder of the request 
                         * @param ls the LibrarySession
                         */
                        public static void setLibrarySession(LibrarySession ls)
                        {
                            _threadLocal.set(ls);
                        }
                    
                        /**
                         * remove the LibrarySession as the current request is complete.  
                         */
                        public static void removeLibrarySession()
                        {
                            _threadLocal.set(null);
                        }
                    
                        /**
                         * get the LibrarySession ascosiated with this request
                         * @return the LibrarySession
                         */
                        public static LibrarySession getCurrentLibrarySession()
                        {
                            return (LibrarySession)_threadLocal.get();
                        }
                    }
                    And a servlet filter to get the library session from the http session and call LibrarySessionHelper.setLibrarySession():

                    Code:
                    public class CMSDKTransactionFilter implements Filter
                    {
                        /**
                         * does nothing
                         * @param filterConfig the FilterConfig object
                         */
                        public void init(FilterConfig filterConfig)
                        { 
                        }
                        
                        /**
                         * does nothing
                         */
                        public void destroy()
                        {
                        }
                        
                        /**
                         * The doFilter() method is called on every request, this implementation<br>
                         * 1: Gets the LibrarySession object out of the session and ascosiates it with the current thread<br>
                         * 2: Processes the remainder of the request <br>
                         * 3: Removes the LibrarySession from the current thread
                         * 
                         * @param servletRequest The ServletRequest object
                         * @param servletResponse The ServletResponse object
                         * @param filterChain Object representing the remainder of the filter chain
                         * @throws IOException exception thrown elsewhere in the chain
                         * @throws ServletException exception thrown elsewhere in the chain
                         */
                        public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, 
                                             FilterChain filterChain) throws IOException, ServletException
                        {
                    		try
                    		{
                    	        //if this is a http servlet request, get the LibrarySession out of the 
                    	        //Session and ascosiate it with the request
                    	        if( servletRequest instanceof HttpServletRequest )
                    	        {
                    	            HttpServletRequest httpServletRequest = ( HttpServletRequest ) servletRequest;
                    	            
                    	            //get the current session but dont create one if it doesnt already exist
                    	            HttpSession session = httpServletRequest.getSession( false );
                    	            
                    	            LibrarySession librarySession = null;
                    	            if( session != null )
                    	            {
                    	                librarySession = ( LibrarySession ) session.getAttribute( LibrarySession.class.getName() );
                    	            }
                    	            
                    	            //set the library session to make it available for the remainder of the request
                    	            LibrarySessionHelper.setLibrarySession( librarySession );
                    	        }
                    	        
                    			
                    	        filterChain.doFilter( servletRequest, servletResponse );
                    		}
                    		finally
                    		{
                    			//always remove the libary session from the current thread at the end of the request
                    	        LibrarySessionHelper.removeLibrarySession();
                    		}
                        }
                    }
                    I hope this is of some use!
                    Feel free to message me if you need any more info or i missed anything.

                    Comment

                    Working...
                    X