java-ee-7jsr352jberet

handle separate transaction in java batch (JSR-352)


I'm using jberet implementation of JSR 352 java batch specs.

Actually I need a separate transaction for doing a singular update, something like this:

class MyItemWriter implements ItemWriter

@Inject
UserTransaction transaction

void resetLastProductsUpdateDate(String uidCli) throws BusinessException {
    try {
        if (transaction.getStatus() != Status.STATUS_ACTIVE) {
            transaction.begin();
        }
        final Customer customer = dao.findById(id);
        customer.setLastUpdate(null);
        customer.persist(cliente);
        transaction.commit();
    } catch (RollbackException | HeuristicMixedException | HeuristicRollbackException | SystemException | NotSupportedException e) {
        logger.error("error while updating user products last update");
        throw new BusinessException();
    }
}

I first tried marking resetLastProductsUpdateDate methoad as @Transactional(REQUIRES_NEW), however it didn't worked.

My question is:

  1. Is there any more elegant way to achieve this singular transaction without manually handle of transaction?
  2. While does UserTransation works, EntityManager.transaction doesn't. I don't get it why.
  3. Class below, which is injected from a Batchlet, works properly; Why I can't get to make work the @Transactional annotation on resetLastProductsUpdateDate method instead?

    public class DynamicQueryDAO {
    
    @Inject
    EntityManager entityManager;
    
    @Inject
    private Logger logger;
    
    @Transactional(Transactional.TxType.REQUIRED)
    public void executeQuery(String query) {
    
        logger.info("executing query: {}", query);
    
        final int output = entityManager.createNativeQuery(query).executeUpdate();
    
        logger.info("rows updated: {}", output);
    }
    

    }

EDIT

Actually I guess neither usertransaction is a good solution, because it affects entire itemwriter transaction management. Still Don't know how to deal with transaction isolation :(


Solution

  • In general the batch application should avoid directly handling transaction. You can have your batch component to throw some business exceptions upon certain conditions, and configure your job.xml to trigger retry upon this business exception. During retry, each individual data will be processed and committed in its own chunk.