The problem has bothered me for several days.
Who can help me?
Thank you.
-----Original Message-----
From: Jack Liu [mailto:[email protected]]
Sent: 2009年4月19日 19:36
To: [email protected]
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:[email protected]]
Sent: 2009年4月18日 2:25
To: [email protected]
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:[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
>
>
>