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    public void advise(final MethodInvocation invocation)
036    {
037        
038        if (invocation.hasAnnotation(CommitAfter.class))
039        {
040        
041                        final PersistenceContext annotation = invocation.getAnnotation(PersistenceContext.class);
042                final EntityTransaction transaction = getTransaction(annotation);
043        
044                if (transaction != null && !transaction.isActive())
045                {
046                    transaction.begin();
047                }
048        
049                try
050                {
051                    invocation.proceed();
052                } catch (final RuntimeException e)
053                {
054                    if (transaction != null && transaction.isActive())
055                    {
056                        rollbackTransaction(transaction);
057                    }
058        
059                    throw e;
060                }
061        
062                // Success or checked exception:
063        
064                if (transaction != null && transaction.isActive())
065                {
066                    transaction.commit();
067                }
068                
069        }
070        else
071        {
072                invocation.proceed();
073        }
074
075    }
076
077    private void rollbackTransaction(EntityTransaction transaction)
078    {
079        try
080        {
081            transaction.rollback();
082        } catch (Exception e)
083        { // Ignore
084        }
085    }
086
087    private EntityTransaction getTransaction(PersistenceContext annotation)
088    {
089        EntityManager em = JpaInternalUtils.getEntityManager(manager, annotation);
090
091        if (em == null)
092            return null;
093
094        return em.getTransaction();
095    }
096
097}