Results 1 to 10 of 10

Thread: Find the current transactionAttributes.

  1. #1
    Join Date
    Jan 2007
    Posts
    8

    Default 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. #2
    Join Date
    Sep 2006
    Location
    UK
    Posts
    8,424

    Default

    Last edited by karldmoore; Aug 29th, 2007 at 10:01 AM.
    Barracuda Networks SSL VPN Lead Developer
    http://pramatr.wordpress.com
    http://twitter.com/karldmoore
    http://www.linkedin.com/in/karldmoore
    Any postings are my own opinion, and should not be attributed to my employer or clients.

  3. #3
    Join Date
    Aug 2004
    Posts
    2,715

    Default

    Quote Originally Posted by karldmoore View Post
    That link is broken. I guess it should be http://static.springframework.org/sp...ctionSt atus()

  4. #4
    Join Date
    Sep 2006
    Location
    UK
    Posts
    8,424

    Default

    Ok, that was weird! Fixed now anyway.
    Last edited by karldmoore; Aug 29th, 2007 at 10:01 AM.
    Barracuda Networks SSL VPN Lead Developer
    http://pramatr.wordpress.com
    http://twitter.com/karldmoore
    http://www.linkedin.com/in/karldmoore
    Any postings are my own opinion, and should not be attributed to my employer or clients.

  5. #5
    Join Date
    Jan 2007
    Posts
    8

    Default

    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!

  6. #6
    Join Date
    Aug 2004
    Posts
    2,715

    Default

    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

  7. #7
    Join Date
    Jan 2007
    Posts
    8

    Default

    Casting looks easier to me... thanks Andreas.

  8. #8
    Join Date
    Sep 2006
    Location
    UK
    Posts
    8,424

    Default

    Well either way should solve the problem . Glad the information was useful.
    Last edited by karldmoore; Aug 29th, 2007 at 10:01 AM.
    Barracuda Networks SSL VPN Lead Developer
    http://pramatr.wordpress.com
    http://twitter.com/karldmoore
    http://www.linkedin.com/in/karldmoore
    Any postings are my own opinion, and should not be attributed to my employer or clients.

  9. #9
    Join Date
    Jul 2006
    Location
    SF Bay Area
    Posts
    3

    Default

    Greetings,

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

    best regards,
    Kjirsten

    Quote 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!

  10. #10
    Join Date
    Jan 2007
    Posts
    8

    Default 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.

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •