Notifications
Clear all

How to link multiple writes into one DB transaction

4 Posts
4 Users
5 Reactions
1,008 Views
3
Topic starter

Please provide an example of how to link two writes into a single database transaction that will rollback if one of the writes fails.

ModelList<UserViewTable> results2 = modelDataService.write(userViewTablesList, dvceCtx);

Thanks.

3 Answers
2

You can wrap ModelDataService.write() calls using TransactionSupport, and then execute the method which takes a ModelWriteRequest instance, with setRollbackAllOnError set to true:

try {
  return TransactionSupport.callWithNewTransaction(new Callable<JSONObject>() {
    @Override
    public JSONObject call() throws Exception {
      ModelDataService mds = Services.get(ModelDataService.class);

      Model model;
      ModelList<Model> modelList = new ModelList<Model>("Standard Model", "PLT.Create", Collections.singletonList(model));
      ModelWriteRequest<Model> writeRequest = new ModelWriteRequest<Model>(modelList);
      writeRequest.setRollbackAllOnError(true);               // this is important!
      mds.write(writeRequest, getPlatformUserContext());

      // another mds.write()

      return new JSONObject().put("success", true);
    }
  }
}
catch(Exception e) {
  return new JSONObject().put("success", false);
}

Note: The code above is useful for cases where the context does not automatically start within a transaction.

The following entry points are all guaranteed to already be in a transaction before they start:

  • Grid Task (and by extension, IXM Engine)
  • Anything called from inside a workflow (action- or time-based), like custom workflow code, callbacks, etc.

The following entry points do not automatically occur in a transaction, meaning the code above can be useful:

  • REST resources (unless you are using the Spring-based Transactional resource, which is the recommended method now)
  • ServerTests not marked as @TransactionalServerTest
0

That sounds strange to me. I assume that by default, in IXM engine context, for example, all writes (thru sqlservice,model dataservice, old DAO etc), going against the OracleDS associated with JDBC connection pool, are running in single EJB transaction, and this transaction is starting and ending in the trans wrapper within grid framework, when the task is picked up and starts executing.

Unless somebody forces the transaction to commit using EJB with RequiresNew attribute, we shouldn't think about transaction management in this case.

Could somebody clarify the applicability of the first answer please?

GregMerrill 2012-05-16 13:05:00

The following entry points are all guaranteed to already be in a transaction before they start:

  • Grid Task (and by extension, IXM Engine)

  • Anything called from inside a workflow (action- or time-based), like custom workflow code, callbacks, etc.

The following entry points do not automatically occur in a transaction, meaning the code above can be useful

  • REST resources (unless you are using the Spring-based Transactional resource, which is the recommended method now)

  • ServerTests not marked as @TransactionalServerTest

Thus the code above is primarily useful for REST.

0

Also, workflow management is also going thru the WorkflowExecutorBean or so, so trans. management should never happen from the workflow java activity.

Is the suggested method only correct for the Jersey case or..?