Skip to main content

JSR 352: Batch Job 'unit testing' - TimerTask triggers JobSecurityException

1 reply [Last post]
jimnicolson
Offline
Joined: 2013-06-22
Points: 0

Hi

I'm actually not sure which forum (Java/GF4/JSR 352/Arquillian) to ask this question in so here goes.

SUMMARY

I'm unit testing a simple JSR 352 batch job using Eclipse/Arquillian/GF4/Java EE 7.

The question is about how to set up security on a Timer/TimerTask which is accessing a Batch Job Status from the unit test.

DETAIILS

The unit test sets up data, and then calls a test method with code similar to that below

@Test
public void testBatchJob() {
Timer batchStatusTimer = null;

String jobName = "simple-batch-job";
JobOperator jo = BatchRuntime.getJobOperator();
long jobId = jo.start(jobName, new Properties());
System.out.println("Started job: with id: " + jobId);

batchStatusTimer = new Timer();
batchStatusTimer.scheduleAtFixedRate(new BatchJobStatusTimerTask(jobId), 100, 500);
...
}

where (summarizing) ...

public class BatchJobStatusTimerTask extends TimerTask {
public void run() {
JobOperator jo = BatchRuntime.getJobOperator();
je = jo.getJobExecution(executionId);
BatchStatus batchStatus = je.getBatchStatus();

if ((batchStatus == BatchStatus.COMPLETED) ... {
cancel();
}
}
}

The test / batch job runs ok.

There was initially an issue in that the unit test was exiting before the job had run/completed and Arquillian shuts down the container really confusing the Batch Runtime :)

A crude busy wait loop demonstrated that it was necessary to put a 'wait' in the unit test until the Job Status indicates the has completed.

I wanted a better approach and created a Timer based wait.

PROBLEM:

The Batch JobOperator throws the following exception in the TimerTask run() method:

javax.batch.operations.JobSecurityException:The current user is not authorized to perform this operation

There is nothing I can find in the JSR 352 Spec, Javadoc or Java EE tutorial about Security in batch.

QUESTION:

Should what I'm doing be possible ? and if so how is security specified (for the TimerTask thread presumably) ?

Regards
Jim Nicolson

Reply viewing options

Select your preferred way to display the comments and click "Save settings" to activate your changes.
jimnicolson
Offline
Joined: 2013-06-22
Points: 0

Reached an initial solution - details below in case anyone else finds themselves travelling this path :)

CAUSES:

1. First a dumb error on my part.

In this situation, I did want a blocking wait and was thinking Timer.schedule
was a blocking call like Thread.sleep() !

2. JobOperator.getJobExecution() was throwing the security exception .
Probably a combination of timing/early termination of the test class.

CURRENT SOLUTION:

Switched to Thread.sleep() (not sure if this is a right approach) and polling JobExecution.getBatchStatus()).

public abstract class BatchJobUtil {

public static boolean isBatchJobRunning(JobExecution je) {

BatchStatus batchStatus = je.getBatchStatus();

// Not sure what STOPPED means vs COMPLETED
return !((batchStatus == BatchStatus.COMPLETED)
|| (batchStatus == BatchStatus.STOPPED)
|| (batchStatus == BatchStatus.FAILED)
|| (batchStatus == BatchStatus.ABANDONED));
}

public static final void waitForBatchJobToFinish(JobExecution je,
long sleepTimeMillis) {
while (isBatchJobRunning(je)) {
try {
Thread.sleep(sleepTimeMillis);
} catch (InterruptedException e) {
e.printStackTrace();
break;
}
}
}
}

ISSUES:

With an Embedded Glassfish / Arquillian an intermittent, non-fatal RAR7093 : Error while cleaning up ManagedConnection (see https://java.net/jira/browse/GLASSFISH-20329)

Arquillian test using a Remote Glassfish / Arquillian, no obvious errors so far.