/***
* Copyright (c) 2009 Caelum - www.caelum.com.br/opensource
* All rights reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package br.com.caelum.vraptor.jpa;
import javax.enterprise.inject.spi.BeanManager;
import javax.inject.Inject;
import javax.persistence.EntityManager;
import javax.persistence.EntityTransaction;
import br.com.caelum.vraptor.AroundCall;
import br.com.caelum.vraptor.Intercepts;
import br.com.caelum.vraptor.http.MutableResponse;
import br.com.caelum.vraptor.interceptor.SimpleInterceptorStack;
import br.com.caelum.vraptor.jpa.event.AfterCommit;
import br.com.caelum.vraptor.jpa.event.AfterRollback;
import br.com.caelum.vraptor.jpa.event.BeforeCommit;
import br.com.caelum.vraptor.validator.Validator;
/**
* An interceptor that manages Entity Manager Transaction. All requests are intercepted
* and a transaction is created before execution. If the request has no erros, the transaction
* will commited, or a rollback occurs otherwise.
*
* @author Lucas Cavalcanti
*/
@Intercepts
public class JPATransactionInterceptor implements JPAInterceptor {
private final BeanManager beanManager;
private final EntityManager manager;
private final Validator validator;
private final MutableResponse response;
/**
* @deprecated CDI eyes only.
*/
protected JPATransactionInterceptor() {
this(null, null, null, null);
}
@Inject
public JPATransactionInterceptor(BeanManager beanManager, EntityManager manager, Validator validator, MutableResponse response) {
this.beanManager = beanManager;
this.manager = manager;
this.validator = validator;
this.response = response;
}
@AroundCall
public void intercept(SimpleInterceptorStack stack) {
addRedirectListener();
EntityTransaction transaction = null;
try {
transaction = manager.getTransaction();
transaction.begin();
stack.next();
commit(transaction);
} finally {
if (transaction != null && transaction.isActive()) {
transaction.rollback();
beanManager.fireEvent(new AfterRollback());
}
}
}
private void commit(EntityTransaction transaction) {
if (transaction.isActive())
beanManager.fireEvent(new BeforeCommit());
if (!validator.hasErrors() && transaction.isActive()) {
transaction.commit();
beanManager.fireEvent(new AfterCommit());
}
}
/**
* We force the commit before the redirect, this way we can abort the
* redirect if a database error occurs.
*/
private void addRedirectListener() {
response.addRedirectListener(new MutableResponse.RedirectListener() {
@Override
public void beforeRedirect() {
commit(manager.getTransaction());
}
});
}
}