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 |
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 On 17/04/2009, at 7:41 PM, Jack Liu wrote:
smime.p7s (3K) Download Attachment |
Yes,I am sure because I debug step by step.
GenericEntity.set() throws IllegalArgumentException ; I use OFBiz trunk version ________________________________ From: Scott Gray [mailto:[hidden email]] Sent: 2009年4月17日 16:28 To: [hidden email] 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 |
In reply to this post by Jack Liu-2
I want to know Why TransactionUtil.begin() return false not true.
It doesn't support transaction? -----Original Message----- From: Jack Liu [mailto:[hidden email]] Sent: 2009年4月17日 16:42 To: [hidden email] 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:[hidden email]] Sent: 2009年4月17日 16:28 To: [hidden email] 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 |
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:[hidden email]] > Sent: 2009年4月17日 16:42 > To: [hidden email] > 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:[hidden email]] > Sent: 2009年4月17日 16:28 > To: [hidden email] > 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 > > > |
Thank you for your response.
Yes, you are totally right, I know little JTA and transaction management. To my question, the begin() method returns false so rollback(false) will not rollback transaction but set rollbackOnly flag. Since rollbackOnly is set, the current thread's transaction will be rolled back at last. Am I right? -----Original Message----- From: David E Jones [mailto:[hidden email]] Sent: 2009年4月18日 2:25 To: [hidden email] Subject: Re: transaction consistency in ofbiz 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:[hidden email]] > Sent: 2009年4月17日 16:42 > To: [hidden email] > 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:[hidden email]] > Sent: 2009年4月17日 16:28 > To: [hidden email] > 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 > > > |
In reply to this post by David E Jones-3
I am still using service engine's transaction.
<service name="processCustomerApprove" engine="java" location="task.Task" invoke="processCustomerApprove"> <attribute name="wfid" mode="IN" type="Long" optional="false" /> <attribute name="action" mode="IN" type="String" optional="true" /> <attribute name="conclusion" mode="IN" type="String" optional="false" /> <attribute name="opinion" mode="IN" type="String" optional="true" /> </service> Attribute use-transaction is set default to be true, which is defined in Services.xsd In task.Task.java, if the method shows like below,then transaction fails public static Map processCustomerApprove(DispatchContext dctx, Map context) { Map result = ServiceUtil.returnSuccess(); GenericDelegator delegator = dctx.getDelegator(); try { 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 test = new HashMap(); Test.put("kid",new Long(111)); Long customerid = CcbUtils.getNextSeqId(delegator, "customerinfo"); GenericValue customerInfo = delegator.makeValue("Customerinfo", UtilMisc.toMap("id", id)); customerInfo.setFields(); delegator.create(customerInfo); return result; }catch (GenericEntityException e) { e.printStackTrace(); return ServiceUtil.returnError(e.getMessage()); } So how is service engine's transaction used? But If I add TransactionUtil.begin(),commit() and rollback() in the above method, then transaction works. This is not the end. When I add some more code to invoke OSWorkflow which uses another datasource also configured in entityengine.xml and use the same instance of GenericDelegator, transaction fails again........ So my question is how I should do to implement transaction consistency in OFBiz when processing multiple datasources. Thank you in advance. -----Original Message----- From: David E Jones [mailto:[hidden email]] Sent: 2009年4月18日 2:25 To: [hidden email] Subject: Re: transaction consistency in ofbiz 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:[hidden email]] > Sent: 2009年4月17日 16:42 > To: [hidden email] > 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:[hidden email]] > Sent: 2009年4月17日 16:28 > To: [hidden email] > 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 > > > |
The problem has bothered me for several days.
Who can help me? Thank you. -----Original Message----- From: Jack Liu [mailto:[hidden email]] Sent: 2009年4月19日 19:36 To: [hidden email] Subject: RE: transaction consistency in ofbiz I am still using service engine's transaction. <service name="processCustomerApprove" engine="java" location="task.Task" invoke="processCustomerApprove"> <attribute name="wfid" mode="IN" type="Long" optional="false" /> <attribute name="action" mode="IN" type="String" optional="true" /> <attribute name="conclusion" mode="IN" type="String" optional="false" /> <attribute name="opinion" mode="IN" type="String" optional="true" /> </service> Attribute use-transaction is set default to be true, which is defined in Services.xsd In task.Task.java, if the method shows like below,then transaction fails public static Map processCustomerApprove(DispatchContext dctx, Map context) { Map result = ServiceUtil.returnSuccess(); GenericDelegator delegator = dctx.getDelegator(); try { 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 test = new HashMap(); Test.put("kid",new Long(111)); Long customerid = CcbUtils.getNextSeqId(delegator, "customerinfo"); GenericValue customerInfo = delegator.makeValue("Customerinfo", UtilMisc.toMap("id", id)); customerInfo.setFields(); delegator.create(customerInfo); return result; }catch (GenericEntityException e) { e.printStackTrace(); return ServiceUtil.returnError(e.getMessage()); } So how is service engine's transaction used? But If I add TransactionUtil.begin(),commit() and rollback() in the above method, then transaction works. This is not the end. When I add some more code to invoke OSWorkflow which uses another datasource also configured in entityengine.xml and use the same instance of GenericDelegator, transaction fails again........ So my question is how I should do to implement transaction consistency in OFBiz when processing multiple datasources. Thank you in advance. -----Original Message----- From: David E Jones [mailto:[hidden email]] Sent: 2009年4月18日 2:25 To: [hidden email] Subject: Re: transaction consistency in ofbiz 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:[hidden email]] > Sent: 2009年4月17日 16:42 > To: [hidden email] > 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:[hidden email]] > Sent: 2009年4月17日 16:28 > To: [hidden email] > 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 > > > |
This is a community driven project
the people here, are volunteers. so unless someone is interested in your problem, it will be you that comes up with a fix. if you have a bug, then put in a jira. http://docs.ofbiz.org/display/OFBADMIN/OFBiz+Contributors+Best+Practices Jack Liu sent the following on 4/19/2009 7:50 PM: > The problem has bothered me for several days. > Who can help me? > Thank you. > > -----Original Message----- > From: Jack Liu [mailto:[hidden email]] > Sent: 2009年4月19日 19:36 > To: [hidden email] > Subject: RE: transaction consistency in ofbiz > > I am still using service engine's transaction. > <service name="processCustomerApprove" engine="java" location="task.Task" invoke="processCustomerApprove"> > <attribute name="wfid" mode="IN" type="Long" > optional="false" /> > <attribute name="action" mode="IN" type="String" > optional="true" /> > <attribute name="conclusion" mode="IN" type="String" > optional="false" /> > <attribute name="opinion" mode="IN" type="String" > optional="true" /> > </service> > Attribute use-transaction is set default to be true, which is defined in Services.xsd > In task.Task.java, if the method shows like below,then transaction fails > > public static Map processCustomerApprove(DispatchContext dctx, Map context) { > Map result = ServiceUtil.returnSuccess(); > GenericDelegator delegator = dctx.getDelegator(); > try { > 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 test = new HashMap(); > Test.put("kid",new Long(111)); > Long customerid = CcbUtils.getNextSeqId(delegator, > "customerinfo"); > GenericValue customerInfo = delegator.makeValue("Customerinfo", > UtilMisc.toMap("id", id)); > customerInfo.setFields(); > delegator.create(customerInfo); > return result; > }catch (GenericEntityException e) { > e.printStackTrace(); > return ServiceUtil.returnError(e.getMessage()); > } > > So how is service engine's transaction used? > But If I add TransactionUtil.begin(),commit() and rollback() in the above method, then transaction works. > This is not the end. When I add some more code to invoke OSWorkflow which uses another datasource also configured in entityengine.xml and use the same instance of GenericDelegator, transaction fails again........ > So my question is how I should do to implement transaction consistency in OFBiz when processing multiple datasources. > > Thank you in advance. > > -----Original Message----- > From: David E Jones [mailto:[hidden email]] > Sent: 2009年4月18日 2:25 > To: [hidden email] > Subject: Re: transaction consistency in ofbiz > > > 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:[hidden email]] >> Sent: 2009年4月17日 16:42 >> To: [hidden email] >> 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:[hidden email]] >> Sent: 2009年4月17日 16:28 >> To: [hidden email] >> 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 >> >> >> > > > |
Yes, I know.
But I am not sure if this is a bug or not because there are no documents to describe how to use local transaction or global transaction in OFBiz. -----Original Message----- From: BJ Freeman [mailto:[hidden email]] Sent: 2009年4月20日 11:35 To: [hidden email] Subject: Re: transaction consistency in ofbiz This is a community driven project the people here, are volunteers. so unless someone is interested in your problem, it will be you that comes up with a fix. if you have a bug, then put in a jira. http://docs.ofbiz.org/display/OFBADMIN/OFBiz+Contributors+Best+Practices Jack Liu sent the following on 4/19/2009 7:50 PM: > The problem has bothered me for several days. > Who can help me? > Thank you. > > -----Original Message----- > From: Jack Liu [mailto:[hidden email]] > Sent: 2009年4月19日 19:36 > To: [hidden email] > Subject: RE: transaction consistency in ofbiz > > I am still using service engine's transaction. > <service name="processCustomerApprove" engine="java" location="task.Task" invoke="processCustomerApprove"> > <attribute name="wfid" mode="IN" type="Long" > optional="false" /> > <attribute name="action" mode="IN" type="String" > optional="true" /> > <attribute name="conclusion" mode="IN" type="String" > optional="false" /> > <attribute name="opinion" mode="IN" type="String" > optional="true" /> > </service> > Attribute use-transaction is set default to be true, which is defined in Services.xsd > In task.Task.java, if the method shows like below,then transaction fails > > public static Map processCustomerApprove(DispatchContext dctx, Map context) { > Map result = ServiceUtil.returnSuccess(); > GenericDelegator delegator = dctx.getDelegator(); > try { > 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 test = new HashMap(); > Test.put("kid",new Long(111)); > Long customerid = CcbUtils.getNextSeqId(delegator, > "customerinfo"); > GenericValue customerInfo = delegator.makeValue("Customerinfo", > UtilMisc.toMap("id", id)); > customerInfo.setFields(); > delegator.create(customerInfo); > return result; > }catch (GenericEntityException e) { > e.printStackTrace(); > return ServiceUtil.returnError(e.getMessage()); > } > > So how is service engine's transaction used? > But If I add TransactionUtil.begin(),commit() and rollback() in the above method, then transaction works. > This is not the end. When I add some more code to invoke OSWorkflow which uses another datasource also configured in entityengine.xml and use the same instance of GenericDelegator, transaction fails again........ > So my question is how I should do to implement transaction consistency in OFBiz when processing multiple datasources. > > Thank you in advance. > > -----Original Message----- > From: David E Jones [mailto:[hidden email]] > Sent: 2009年4月18日 2:25 > To: [hidden email] > Subject: Re: transaction consistency in ofbiz > > > 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:[hidden email]] >> Sent: 2009年4月17日 16:42 >> To: [hidden email] >> 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:[hidden email]] >> Sent: 2009年4月17日 16:28 >> To: [hidden email] >> 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 >> >> >> > > > |
if your not losing data in the database,
or your not seeing errors about transactions aborted. it is probably not a bug. the way to verify this is to watch what a transaction does and then see if it is put in the db. if you can verify that the data in not being put in the db and can give the steps to reproduce this, then others can take a look. :D Jack Liu sent the following on 4/19/2009 8:41 PM: > Yes, I know. > But I am not sure if this is a bug or not because there are no documents to describe how to use local transaction or global transaction in OFBiz. > > -----Original Message----- > From: BJ Freeman [mailto:[hidden email]] > Sent: 2009年4月20日 11:35 > To: [hidden email] > Subject: Re: transaction consistency in ofbiz > > This is a community driven project > the people here, are volunteers. > so unless someone is interested in your problem, it will be you that > comes up with a fix. > if you have a bug, then put in a jira. > http://docs.ofbiz.org/display/OFBADMIN/OFBiz+Contributors+Best+Practices > > Jack Liu sent the following on 4/19/2009 7:50 PM: >> The problem has bothered me for several days. >> Who can help me? >> Thank you. >> >> -----Original Message----- >> From: Jack Liu [mailto:[hidden email]] >> Sent: 2009年4月19日 19:36 >> To: [hidden email] >> Subject: RE: transaction consistency in ofbiz >> >> I am still using service engine's transaction. >> <service name="processCustomerApprove" engine="java" location="task.Task" invoke="processCustomerApprove"> >> <attribute name="wfid" mode="IN" type="Long" >> optional="false" /> >> <attribute name="action" mode="IN" type="String" >> optional="true" /> >> <attribute name="conclusion" mode="IN" type="String" >> optional="false" /> >> <attribute name="opinion" mode="IN" type="String" >> optional="true" /> >> </service> >> Attribute use-transaction is set default to be true, which is defined in Services.xsd >> In task.Task.java, if the method shows like below,then transaction fails >> >> public static Map processCustomerApprove(DispatchContext dctx, Map context) { >> Map result = ServiceUtil.returnSuccess(); >> GenericDelegator delegator = dctx.getDelegator(); >> try { >> 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 test = new HashMap(); >> Test.put("kid",new Long(111)); >> Long customerid = CcbUtils.getNextSeqId(delegator, >> "customerinfo"); >> GenericValue customerInfo = delegator.makeValue("Customerinfo", >> UtilMisc.toMap("id", id)); >> customerInfo.setFields(); >> delegator.create(customerInfo); >> return result; >> }catch (GenericEntityException e) { >> e.printStackTrace(); >> return ServiceUtil.returnError(e.getMessage()); >> } >> >> So how is service engine's transaction used? >> But If I add TransactionUtil.begin(),commit() and rollback() in the above method, then transaction works. >> This is not the end. When I add some more code to invoke OSWorkflow which uses another datasource also configured in entityengine.xml and use the same instance of GenericDelegator, transaction fails again........ >> So my question is how I should do to implement transaction consistency in OFBiz when processing multiple datasources. >> >> Thank you in advance. >> >> -----Original Message----- >> From: David E Jones [mailto:[hidden email]] >> Sent: 2009年4月18日 2:25 >> To: [hidden email] >> Subject: Re: transaction consistency in ofbiz >> >> >> 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:[hidden email]] >>> Sent: 2009年4月17日 16:42 >>> To: [hidden email] >>> 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:[hidden email]] >>> Sent: 2009年4月17日 16:28 >>> To: [hidden email] >>> 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 >>> >>> >>> >> >> > > |
Free forum by Nabble | Edit this page |