FR [ 2080217 ] Implement TrxRunnable
This commit is contained in:
parent
aabad61689
commit
b27cf2b2e5
|
@ -28,6 +28,7 @@ import java.util.Date;
|
|||
import java.util.UUID;
|
||||
import java.util.logging.Level;
|
||||
|
||||
import org.adempiere.exceptions.AdempiereException;
|
||||
import org.compiere.db.CConnection;
|
||||
import org.compiere.db.ServerConnection;
|
||||
import org.compiere.interfaces.Server;
|
||||
|
@ -46,7 +47,8 @@ import org.compiere.interfaces.Server;
|
|||
* - added rollback(boolean) and commit(boolean) [20070105]
|
||||
* - remove unnecessary use of savepoint
|
||||
* - use UUID for safer transaction name generation
|
||||
* @version $Id$
|
||||
* @author Teo Sarca, http://www.arhipac.ro
|
||||
* <li>FR [ 2080217 ] Implement TrxRunnable
|
||||
*/
|
||||
public class Trx implements VetoableChangeListener
|
||||
{
|
||||
|
@ -676,4 +678,80 @@ public class Trx implements VetoableChangeListener
|
|||
return trxs;
|
||||
}
|
||||
|
||||
/**
|
||||
* @see #run(String, TrxRunnable)
|
||||
*/
|
||||
public static void run(TrxRunnable r)
|
||||
{
|
||||
run(null, r);
|
||||
}
|
||||
|
||||
/**
|
||||
* Execute runnable object using provided transaction.
|
||||
* If execution fails, database operations will be rolled back.
|
||||
* <p>
|
||||
* Example: <pre>
|
||||
* Trx.run(null, new {@link TrxRunnable}() {
|
||||
* public void run(String trxName) {
|
||||
* // do something using trxName
|
||||
* }
|
||||
* )};
|
||||
* </pre>
|
||||
*
|
||||
* @param trxName transaction name (if null, a new transaction will be created)
|
||||
* @param r runnable object
|
||||
*/
|
||||
public static void run(String trxName, TrxRunnable r)
|
||||
{
|
||||
boolean localTrx = false;
|
||||
if (trxName == null) {
|
||||
trxName = Trx.createTrxName("TrxRun");
|
||||
localTrx = true;
|
||||
}
|
||||
Trx trx = Trx.get(trxName, true);
|
||||
Savepoint savepoint = null;
|
||||
try
|
||||
{
|
||||
if (!localTrx)
|
||||
savepoint = trx.setSavepoint(null);
|
||||
|
||||
r.run(trxName);
|
||||
|
||||
if (localTrx)
|
||||
trx.commit(true);
|
||||
}
|
||||
catch (Throwable e)
|
||||
{
|
||||
// Rollback transaction
|
||||
if (localTrx)
|
||||
{
|
||||
trx.rollback();
|
||||
}
|
||||
else if (savepoint != null)
|
||||
{
|
||||
try {
|
||||
trx.rollback(savepoint);
|
||||
}
|
||||
catch (SQLException e2) {;}
|
||||
}
|
||||
trx = null;
|
||||
// Throw exception
|
||||
if (e instanceof RuntimeException)
|
||||
{
|
||||
throw (RuntimeException)e;
|
||||
}
|
||||
else
|
||||
{
|
||||
throw new AdempiereException(e);
|
||||
}
|
||||
}
|
||||
finally {
|
||||
if (localTrx && trx != null)
|
||||
{
|
||||
trx.close();
|
||||
trx = null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
} // Trx
|
||||
|
|
|
@ -0,0 +1,25 @@
|
|||
/******************************************************************************
|
||||
* Product: Adempiere ERP & CRM Smart Business Solution *
|
||||
* Copyright (C) 2008 SC ARHIPAC SERVICE SRL. All Rights Reserved. *
|
||||
* This program is free software; you can redistribute it and/or modify it *
|
||||
* under the terms version 2 of the GNU General Public License as published *
|
||||
* by the Free Software Foundation. This program is distributed in the hope *
|
||||
* that it will be useful, but WITHOUT ANY WARRANTY; without even the implied *
|
||||
* warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. *
|
||||
* See the GNU General Public License for more details. *
|
||||
* You should have received a copy of the GNU General Public License along *
|
||||
* with this program; if not, write to the Free Software Foundation, Inc., *
|
||||
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. *
|
||||
*****************************************************************************/
|
||||
package org.compiere.util;
|
||||
|
||||
/**
|
||||
* Defines an object that can be ran into an transaction,
|
||||
* using {@link Trx#run(TrxRunnable)} or {@link Trx#run(String, TrxRunnable)} methods.
|
||||
*
|
||||
* @author Teo Sarca, http://www.arhipac.ro
|
||||
*/
|
||||
public interface TrxRunnable
|
||||
{
|
||||
public void run(String trxName);
|
||||
}
|
|
@ -18,6 +18,7 @@ public class FunctionalTestSuite {
|
|||
suite.addTestSuite(MStorageTest.class);
|
||||
suite.addTestSuite(MSysConfigTest.class);
|
||||
suite.addTestSuite(QueryTest.class);
|
||||
suite.addTestSuite(TrxTest.class);
|
||||
suite.addTestSuite(MRefListTest.class);
|
||||
suite.addTestSuite(MUOMTest.class);
|
||||
//$JUnit-END$
|
||||
|
|
|
@ -0,0 +1,114 @@
|
|||
/******************************************************************************
|
||||
* Product: Adempiere ERP & CRM Smart Business Solution *
|
||||
* Copyright (C) 2008 SC ARHIPAC SERVICE SRL. All Rights Reserved. *
|
||||
* This program is free software; you can redistribute it and/or modify it *
|
||||
* under the terms version 2 of the GNU General Public License as published *
|
||||
* by the Free Software Foundation. This program is distributed in the hope *
|
||||
* that it will be useful, but WITHOUT ANY WARRANTY; without even the implied *
|
||||
* warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. *
|
||||
* See the GNU General Public License for more details. *
|
||||
* You should have received a copy of the GNU General Public License along *
|
||||
* with this program; if not, write to the Free Software Foundation, Inc., *
|
||||
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. *
|
||||
*****************************************************************************/
|
||||
package test.functional;
|
||||
|
||||
import org.adempiere.exceptions.AdempiereException;
|
||||
import org.compiere.model.MTest;
|
||||
import org.compiere.model.Query;
|
||||
import org.compiere.util.Trx;
|
||||
import org.compiere.util.TrxRunnable;
|
||||
|
||||
import test.AdempiereTestCase;
|
||||
|
||||
/**
|
||||
* Test {@link Trx} class
|
||||
* @author Teo Sarca, http://www.arhipac.ro
|
||||
*/
|
||||
public class TrxTest extends AdempiereTestCase {
|
||||
private int m_id2 = -1;
|
||||
|
||||
/**
|
||||
* Test {@link Trx#run(TrxRunnable)} and {@link Trx#run(String, TrxRunnable)} methods
|
||||
*/
|
||||
public void testRunTrxRunnable() throws Exception
|
||||
{
|
||||
//
|
||||
// Create test outside trx - success
|
||||
m_id2 = -1;
|
||||
Trx.run(new TrxRunnable() {
|
||||
public void run(String trxName) {
|
||||
m_id2 = createTest(trxName).get_ID();
|
||||
}
|
||||
});
|
||||
assertTestExists(m_id2, true, null);
|
||||
new MTest(getCtx(), m_id2, null).deleteEx(true);
|
||||
|
||||
//
|
||||
// Create test outside trx - fail
|
||||
m_id2 = -1;
|
||||
try {
|
||||
Trx.run(new TrxRunnable() {
|
||||
public void run(String trxName) {
|
||||
m_id2 = createTest(trxName).get_ID();
|
||||
throw new AdempiereException("FORCE");
|
||||
}
|
||||
});
|
||||
//
|
||||
assertTrue("Should not happen because previous code is throwing exception", false);
|
||||
}
|
||||
catch (AdempiereException e) {
|
||||
}
|
||||
assertTestExists(m_id2, false, null);
|
||||
|
||||
//
|
||||
// Create test1
|
||||
String trxName = getTrxName();
|
||||
MTest test1 = createTest(trxName);
|
||||
|
||||
//
|
||||
// Fail creating test2
|
||||
m_id2 = -1;
|
||||
try {
|
||||
Trx.run(trxName, new TrxRunnable() {
|
||||
public void run(String trxName) {
|
||||
m_id2 = createTest(trxName).get_ID();
|
||||
throw new AdempiereException("FORCE");
|
||||
}
|
||||
});
|
||||
//
|
||||
assertTrue("Should not happen because previous code is throwing exception", false);
|
||||
}
|
||||
catch (AdempiereException e) {
|
||||
}
|
||||
assertTestExists(m_id2, false, trxName);
|
||||
assertTestExists(test1.get_ID(), true, trxName);
|
||||
|
||||
//
|
||||
// Success creating test2
|
||||
m_id2 = -1;
|
||||
Trx.run(trxName, new TrxRunnable() {
|
||||
public void run(String trxName) {
|
||||
m_id2 = createTest(trxName).get_ID();
|
||||
}
|
||||
});
|
||||
assertTestExists(m_id2, true, trxName);
|
||||
assertTestExists(test1.get_ID(), true, trxName);
|
||||
}
|
||||
|
||||
private final MTest createTest(String trxName) {
|
||||
MTest test = new MTest (getCtx(), "test-"+getClass(), 10);
|
||||
test.set_TrxName(trxName);
|
||||
test.saveEx();
|
||||
return test;
|
||||
}
|
||||
|
||||
private final void assertTestExists(int test_id, boolean existsTarget, String trxName)
|
||||
{
|
||||
String whereClause = MTest.COLUMNNAME_Test_ID+"=?";
|
||||
boolean exists = new Query(getCtx(), MTest.Table_Name, whereClause, trxName)
|
||||
.setParameters(new Object[]{test_id})
|
||||
.match();
|
||||
assertEquals("Test "+test_id+" [trxName="+trxName+"] - existance issue", existsTarget, exists);
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue