ItEr43S09ImplantacionAplicacionItEr42S13: Using transparent proxys for wrapping interfaces methods with transactions

This commit is contained in:
Óscar González Fernández 2010-01-13 18:22:13 +01:00
parent 9a9719e7a3
commit a5c7efe2f0
2 changed files with 93 additions and 14 deletions

View file

@ -20,6 +20,10 @@
package org.navalplanner.business.common;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;
@ -27,7 +31,80 @@ import org.springframework.transaction.annotation.Transactional;
@Service
public class AdHocTransactionService implements IAdHocTransactionService {
@Override
private static <T> T proxy(IAdHocTransactionService transactionService,
boolean readOnly,
Class<T> interfaceClass,
T interfaceObject) {
Class<?>[] interfaces = { interfaceClass };
return interfaceClass.cast(Proxy.newProxyInstance(interfaceClass
.getClassLoader(), interfaces, createHandler(interfaceObject,
transactionService, readOnly)));
}
/**
* Returns a new object implementing the same interface but with its calls
* wrapped on read only transactions
* @param transactionService
* @param interfaceClass
* @param interfaceObject
* @return
*/
public static <T> T readOnlyProxy(IAdHocTransactionService transactionService,
Class<T> interfaceClass, T interfaceObject) {
return proxy(transactionService, true, interfaceClass, interfaceObject);
}
/**
* Returns a new object implementing the same interface but with its calls
* wrapped on transactions
* @param transactionService
* @param interfaceClass
* @param interfaceObject
* @return
*/
public static <T> T proxy(IAdHocTransactionService transactionService,
Class<T> interfaceClass, T interfaceObject) {
return proxy(transactionService, false, interfaceClass, interfaceObject);
}
private static InvocationHandler createHandler(final Object originalObject,
final IAdHocTransactionService transactionService,
final boolean readOnly) {
return new InvocationHandler() {
@Override
public Object invoke(final Object proxy, final Method method,
final Object[] args) throws Throwable {
IOnTransaction<Object> onTransaction = createOnTransaction(originalObject, method, args);
try {
if (readOnly) {
return transactionService
.runOnReadOnlyTransaction(onTransaction);
} else {
return transactionService.runOnTransaction(onTransaction);
}
} catch (RuntimeException e) {
throw e.getCause();
}
}
};
}
private static IOnTransaction<Object> createOnTransaction(
final Object originalObject, final Method method,
final Object[] args) {
return new IOnTransaction<Object>() {
@Override
public Object execute() {
try {
return method.invoke(originalObject, args);
} catch (Exception e) {
throw new RuntimeException(e);
}
}
};
}
@Transactional
public <T> T runOnTransaction(IOnTransaction<T> onTransaction) {
return onTransaction.execute();

View file

@ -20,6 +20,7 @@
package org.navalplanner.web.planner.order;
import static org.navalplanner.business.common.AdHocTransactionService.readOnlyProxy;
import static org.navalplanner.web.I18nHelper._;
import java.math.BigDecimal;
@ -495,19 +496,20 @@ public abstract class OrderPlanningModel implements IOrderPlanningModel {
ISaveCommand saveCommand, final Chart loadChart) {
planner.getTimeTracker().addZoomListener(fillOnZoomChange(loadChart));
saveCommand.addListener(fillChartOnSave(loadChart));
taskElementAdapter.addListener(new IOnMoveListener() {
@Override
public void moved(TaskElement taskElement) {
loadChart.fillChart();
}
});
configuration.addReloadChartListener(new IReloadChartListener() {
@Override
public void reloadChart() {
loadChart.fillChart();
}
});
taskElementAdapter.addListener(readOnlyProxy(transactionService,
IOnMoveListener.class, new IOnMoveListener() {
@Override
public void moved(TaskElement taskElement) {
loadChart.fillChart();
}
}));
configuration.addReloadChartListener(readOnlyProxy(transactionService,
IReloadChartListener.class, new IReloadChartListener() {
@Override
public void reloadChart() {
loadChart.fillChart();
}
}));
}
private void addAdditional(List<ICommand<TaskElement>> additional,