001// Copyright 2011, 2012, 2014 The Apache Software Foundation
002//
003// Licensed under the Apache License, Version 2.0 (the "License");
004// you may not use this file except in compliance with the License.
005// You may obtain a copy of the License at
006//
007// http://www.apache.org/licenses/LICENSE-2.0
008//
009// Unless required by applicable law or agreed to in writing, software
010// distributed under the License is distributed on an "AS IS" BASIS,
011// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
012// See the License for the specific language governing permissions and
013// limitations under the License.
014
015package org.apache.tapestry5.internal.jpa;
016
017import javax.persistence.EntityManager;
018import javax.persistence.EntityTransaction;
019import javax.persistence.PersistenceContext;
020
021import org.apache.tapestry5.jpa.EntityManagerManager;
022import org.apache.tapestry5.jpa.annotations.CommitAfter;
023import org.apache.tapestry5.plastic.MethodAdvice;
024import org.apache.tapestry5.plastic.MethodInvocation;
025
026public class CommitAfterMethodAdvice implements MethodAdvice
027{
028    private final EntityManagerManager manager;
029
030    public CommitAfterMethodAdvice(final EntityManagerManager manager)
031    {
032        this.manager = manager;
033    }
034
035    @Override
036    public void advise(final MethodInvocation invocation)
037    {
038        
039        if (invocation.hasAnnotation(CommitAfter.class))
040        {
041        
042                        final PersistenceContext annotation = invocation.getAnnotation(PersistenceContext.class);
043                final EntityTransaction transaction = getTransaction(annotation);
044        
045                if (transaction != null && !transaction.isActive())
046                {
047                    transaction.begin();
048                }
049        
050                try
051                {
052                    invocation.proceed();
053                } catch (final RuntimeException e)
054                {
055                    if (transaction != null && transaction.isActive())
056                    {
057                        rollbackTransaction(transaction);
058                    }
059        
060                    throw e;
061                }
062        
063                // Success or checked exception:
064        
065                if (transaction != null && transaction.isActive())
066                {
067                    transaction.commit();
068                }
069                
070        }
071        else
072        {
073                invocation.proceed();
074        }
075
076    }
077
078    private void rollbackTransaction(EntityTransaction transaction)
079    {
080        try
081        {
082            transaction.rollback();
083        } catch (Exception e)
084        { // Ignore
085        }
086    }
087
088    private EntityTransaction getTransaction(PersistenceContext annotation)
089    {
090        EntityManager em = JpaInternalUtils.getEntityManager(manager, annotation);
091
092        if (em == null)
093            return null;
094
095        return em.getTransaction();
096    }
097
098}