package com.mysema.luja.impl;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.mysema.luja.LuceneTransactional;
import com.mysema.luja.SessionClosedException;
import com.mysema.luja.SessionNotBoundException;
import com.mysema.luja.SessionReadOnlyException;
@Aspect
public class LuceneTransactionHandler {
private static final Logger logger = LoggerFactory.getLogger(LuceneTransactionHandler.class);
@Around("@annotation(annotation)")
public Object transactionalMethod(ProceedingJoinPoint joinPoint, LuceneTransactional annotation)
throws Throwable {
//If this is nested method, let the most outer scope deal with
//leasing and releasing
if (LuceneSessionHolder.isTransactionalScope()) {
if (logger.isDebugEnabled()) {
logger.debug("LuceneSessionHolder proceed in inner scope");
}
return joinPoint.proceed();
}
if (logger.isDebugEnabled()) {
logger.debug("LuceneSessionHolder.lease");
}
LuceneSessionHolder.lease(annotation.readOnly());
boolean rollback = false;
try {
return joinPoint.proceed();
} catch (Exception e) {
rollback = isRollback(annotation, e);
throw e;
} finally {
if (!rollback) {
if (logger.isDebugEnabled()) {
logger.debug("LuceneSessionHolder.release");
}
LuceneSessionHolder.release();
}
else {
if (logger.isDebugEnabled()) {
logger.debug("LuceneSessionHolder.rollbackAndRelease");
}
LuceneSessionHolder.rollbackAndRelease();
}
}
}
private boolean isRollback(LuceneTransactional annotation, Exception exception) {
// TODO Add annotation support for exceptions ala Hibernate
// Filter runtime exceptions which are not valid for rollback
if (exception instanceof SessionReadOnlyException
|| exception instanceof SessionNotBoundException
|| exception instanceof SessionClosedException) {
return false;
}
logger.error("Exception from transactional method, rollbacking", exception);
return true;
}
}