It sounds like you're digging pretty deep, and I'd recommend a peek at the TransactionUtil.java file. It's really quite simple code.

The begin() method returns false if there is already a transaction in place, and along with it the rollback(beganTransaction) method will only do the actually rollback if beganTransaction is true, otherwise it will set the rollbackOnly flag. Why does it do this? The basic idea is that a code block should never commit or rollback a transaction it didn't begin (ie that's a fundamental rule for transaction management code).

I HIGHLY recommend you find a good book on transaction management because there are lots of things you need to know about to write proper transaction demarcation code, either that or use the Service Engine's transaction handling features (that's what they are there for...).

-David


On Apr 17, 2009, at 4:27 AM, Jack Liu wrote:

I want to know Why TransactionUtil.begin() return false not true.
It doesn't support transaction?

-----Original Message-----
From: Jack Liu [mailto:[email protected]]
Sent: 2009年4月17日 16:42
To: [email protected]
Subject: RE: transaction consistency in ofbiz

Yes,I am sure because I debug step by step.

GenericEntity.set() throws IllegalArgumentException ;

I use OFBiz trunk version

________________________________

From: Scott Gray [mailto:[email protected]]
Sent: 2009年4月17日 16:28
To: [email protected]
Subject: Re: transaction consistency in ofbiz



Are you sure that a transaction rollback is actually invoked? GenericEntity.setFields() calls GenericEntity.set() which has a statement in it that logs an exception but doesn't actually throw one.



Regards

Scott



HotWax Media

http://www.hotwaxmedia.com <http://www.hotwaxmedia.com/>



On 17/04/2009, at 7:41 PM, Jack Liu wrote:





Hi, All
In OFBiz, there is a class named TransactionUtil which helps with some
common transaction tasks
I want to know how to use it, so I wrote some code below

public static Map processCustomerApprove(DispatchContext dctx, Map
context) {
             Map result = ServiceUtil.returnSuccess();
             GenericDelegator delegator = dctx.getDelegator();

             boolean beganTransaction =  false;
             try {
                    beganTransaction = TransactionUtil.begin();

                    Workflow workflow =
WorkFlowFactory.getWorkFlow(UserUtil
                                  .getUserName());
                    Long wfid = (Long) context.get("wfid");
                    int actionNum = Integer.parseInt((String)
context.get("action"));
                    Debug.logInfo("workflow=" + wfid +
",actionnumber=" + actionNum,
                                  module);

                    String opinion = (String)
context.get("opinion");
                    String conclusion = (String)
context.get("conclusion");
                    Debug.logInfo("Conclusion=" + conclusion +
"\nopinion=" + opinion,
                                  module);

                    Long id = new
Long(delegator.getNextSeqId("Opinion"));
                    Debug.logInfo("id = " + id, module);
                    GenericValue opinionValue =
delegator.makeValue("Opinion", UtilMisc
                                  .toMap("id", id));
                    opinionValue.set("wfid", wfid);
                    opinionValue.set("approver",
UserUtil.getUserName());
                    opinionValue.set("conclusion", conclusion);
                    opinionValue.set("opinion", opinion);
                    delegator.create(opinionValue);

                    Map inputs = new HashMap();
                    inputs.put("conclusion", conclusion);
                    workflow.doAction(wfid, actionNum, inputs);
                    Debug.logInfo("workflow enters next step",
module);


                    if ("Agree".equals(conclusion) && actionNum ==
2) {
                           //
                           EntityCondition wfidCondition =
EntityCondition.makeCondition(
                                         "wfid",
EntityOperator.EQUALS, wfid);
                           List customerInfoHistoryList =
delegator.findList(
                                         "CustomerinfoHistory",
wfidCondition, null, UtilMisc

.toList("id DESC"), null, false);
                           GenericValue value =
EntityUtil.getFirst(customerInfoHistoryList);
                           //copy customer info from table
customerinfohistory to customerinfo
                    //value.remove("wfid");
                           value.remove("id");

                           Long customerid =
CcbUtils.getNextSeqId(delegator, "customerinfo");
                           Debug.logInfo("id = " + customerid,
module);
                           GenericValue customerInfo =
delegator.makeValue("Customerinfo",
                                         UtilMisc.toMap("id",
id));
                           customerInfo.setFields(value);
                           delegator.create(customerInfo);

                    }

             } catch (Exception e) {
                    try {

TransactionUtil.rollback(beganTransaction, "something wrong in the
operation", e);
                    } catch (GenericTransactionException e1) {
                           e1.printStackTrace();
                    }
             }finally {
                    try {
                           TransactionUtil.commit();
                    } catch (GenericTransactionException e) {
                           e.printStackTrace();
                    }
             }

             return result;
      }
}

When I debug, TransactionUtil.begin() returns false,
And an error happens when running customerInfo.setFields(value) (I know
why),
, so jvm catches the exception, TransactionUtil.rollback is invoked.
Because beganTransaction is false, it doesn't roll back.
When program ends, transaction doesn't work eventually.

Could you tell me how I should do to keep transaction consistent?




Best Regards,

Jack Liu




Reply via email to