ItEr43S09ImplantacionAplicacionItEr42S13: Using transparent proxys for wrapping interfaces methods with transactions
This commit is contained in:
parent
9a9719e7a3
commit
a5c7efe2f0
2 changed files with 93 additions and 14 deletions
|
|
@ -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();
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue