3

I am trying to create a simple batch application using JSR 352 with Websphere Liberty Profile 17.0.0.2. Everything seems to be working fine until getting into exception handling. I am under the assumption that exceptions thrown by the application specified in the 'skippable-exception-classes' node in the job.xml will be somewhat ignored/skipped and will allow the job to proceed on the next items/steps.

The problem that I encounter occurs whenever an exception is thrown from an injected bean (via @Inject) when calling one of its methods. The job just stops on the current item/step where the exception was thrown.

The weird thing is whenever I manually/explicitly throw the exact same exception, let's say RecordNotFoundException, the job continues which is what I expected. The problem only occurs when the exception is triggered from the injected bean. I have added @ApplicationException to the exception class so the exception wrapping/unwrapping is in place.

Am I missing something? Is this a bug with Websphere Liberty?

EDIT: Added simplified code

SampleSharedLibrary - Dependency from other project/jar

package sample;

import javax.ejb.ApplicationException;
import javax.ejb.Stateless;

@Stateless
public class SampleSharedLibrary {

    public String someMethod(String object) {
        String result = null;

        if(object != null) {
            result = "OK";
        } else {
            throw new MyException();
        }

        return result;
    }

    @ApplicationException(rollback = true)
    public static class MyException extends RuntimeException {
        public MyException() {}
    }
}

BatchExample application

SampleWriter import sample.SampleSharedLibrary;

import javax.batch.api.chunk.AbstractItemWriter;
import javax.enterprise.context.Dependent;
import javax.inject.Inject;
import javax.inject.Named;
import java.util.List;

@Dependent
@Named("SampleWriter")
public class SampleWriter extends AbstractItemWriter{

    @Inject
    SampleSharedLibrary sharedLibrary;

    public void writeItems(List<Object> list) throws Exception {
        for(Object item : list) {
            sharedLibrary.someMethod(item.toString());
        }
    }
}

SampleReader

import javax.batch.api.chunk.AbstractItemReader;
import javax.enterprise.context.Dependent;
import javax.inject.Named;
import java.io.Serializable;

@Dependent
@Named("SampleReader")
public class SampleReader extends AbstractItemReader {

    String[] sample;
    int index;
    @Override
    public void open(Serializable checkpoint) throws Exception {
        sample = new String[]{"S1", null, "S3"};
        index = 0;
    }

    public Object readItem() throws Exception {
        Object item = null;

        if(index < sample.length) {
            item = sample[index];
            index++;
        }

        return item;
    }
}

job.xml

<job id="myJob" xmlns="http://xmlns.jcp.org/xml/ns/javaee" version="1.0">
    <step id="myStep" >
        <chunk item-count="1" skip-limit="50">
            <reader ref="SampleReader"/>
            <writer ref="SampleWriter"/>
            <skippable-exception-classes>
                <include class="java.lang.Exception"/>
                <include class="sample.SampleSharedLibrary$MyException"/>
            </skippable-exception-classes>
        </chunk>
    </step>
</job>

As for the server.xml, not too much configuration added but I have enabled the following features: cdi-1.2, ejbLite-3.2, jaxrs-2.0, jpa-2.0, jsf-2.2, managedBeans-1.0, servlet-3.1, localConnector-1.0, batch-1.0 and json-1.0

When encountering the error from the actual application, I get logs like something below (had to change some values to asterisks):

[02-11-17 21:38:12:323 CST] 000000d1 com.ibm.ws.logging.internal.impl.IncidentImpl                I FFDC1015I: An FFDC Incident has been created: "*******.**********.*******.batchflows.service.writer.ErrorWhileUpdating: *******.**********.*******.infrastructure.*****.commands.OurCommand$RecordNotFound: recordId=31AA69FAE017D21F com.ibm.jbatch.container.controller.impl.ChunkStepControllerImpl 485" at ffdc_17.11.02_21.38.12.0.log
[02-11-17 21:38:12:352 CST] 000000d1 com.ibm.ws.logging.internal.impl.IncidentImpl                I FFDC1015I: An FFDC Incident has been created: "com.ibm.jbatch.container.exception.BatchContainerRuntimeException: *******.**********.*******.batchflows.service.writer.ErrorWhileUpdating: *******.**********.*******.infrastructure.*****.commands.OurCommand$RecordNotFound: recordId=31AA69FAE017D21F com.ibm.jbatch.container.controller.impl.ChunkStepControllerImpl 1041" at ffdc_17.11.02_21.38.12.1.log
[02-11-17 21:38:12:363 CST] 000000d1 com.ibm.ws.logging.internal.impl.IncidentImpl                I FFDC1015I: An FFDC Incident has been created: "javax.transaction.RollbackException com.ibm.jbatch.container.transaction.impl.JTAUserTransactionAdapter 107" at ffdc_17.11.02_21.38.12.2.log
[02-11-17 21:38:12:385 CST] 000000d1 com.ibm.ws.logging.internal.impl.IncidentImpl                I FFDC1015I: An FFDC Incident has been created: "com.ibm.jbatch.container.exception.TransactionManagementException: javax.transaction.RollbackException com.ibm.jbatch.container.controller.impl.ChunkStepControllerImpl 680" at ffdc_17.11.02_21.38.12.3.log
joe777baba
  • 33
  • 4
  • Welcome to Stackoverflow. Please read https://stackoverflow.com/help/mcve on how to create a Minimal, Complete, and Verifiable example. – Aedvald Tseh Nov 02 '17 at 09:07
  • It does sound like it could be an issue with exception wrapping of your **RecordNotFoundException**. The batch container code looks at the exception it gets to see if it's included in the skippable list. It doesn't try to unwrap what is thrown back to it. Can you please include more detail including maybe a code snippet showing the bean throwing the exception? Is this an EJB or just a CDI bean? Can you share your server config (server.xml)? – Scott Kurz Nov 02 '17 at 11:01
  • I will try to provide the code and some additional details, have to omit some details from the code first – joe777baba Nov 02 '17 at 11:09
  • @ScottKurz - Added a simplified version of the code and some error logs, hope it's understandable – joe777baba Nov 02 '17 at 13:47

1 Answers1

1

The EJB container can still rollback the batch chunk transaction, even if the batch container skips a given exception

Configuring your job XML to skip a given exception will only prevent the batch container from marking the chunk transaction for rollback. It won't prevent someone else from marking the transaction for rollback.

This means the EJB container could itself rollback the transaction. So in your case you would need to use:

@ApplicationException(rollback = false)
public static class MyException extends RuntimeException {

or, in the pre-annotation style, you would need to use a checked exception rather than an unchecked exception in order to prevent the EJB container from rolling back the transaction.

Community
  • 1
  • 1
Scott Kurz
  • 4,985
  • 1
  • 18
  • 40