/* * Copyright (c) 2012-2013 Red Hat, Inc. and/or its affiliates. * * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * Cheng Fang - Initial API and implementation */ package org.jberet.se.test; import java.io.BufferedWriter; import java.io.File; import java.io.FileWriter; import java.io.IOException; import java.util.Properties; import java.util.concurrent.TimeUnit; import javax.batch.operations.JobOperator; import javax.batch.runtime.BatchRuntime; import javax.batch.runtime.BatchStatus; import org.jberet.runtime.JobExecutionImpl; import org.jberet.runtime.StepExecutionImpl; import org.junit.Assert; import org.junit.Test; public class Batchlet1Test { static final String tmpdir = System.getProperty("jberet.tmp.dir"); static final String jobName = "org.jberet.se.test.batchlet1"; static final String jobName2 = "org-jberet-se-test-batchlet2"; static final String jobName3 = "org.jberet.se.test.batchlet3"; static final String jobName4 = "org.jberet.se.test.batchlet4"; static final File jobName2ExecutionIdSaveTo = new File(tmpdir, jobName2 + ".executionId"); static final File jobName3ExecutionIdSaveTo = new File(tmpdir, jobName3 + ".executionId"); private final JobOperator jobOperator = BatchRuntime.getJobOperator(); static final int waitTimeoutMinutes = 0; @Test public void testBatchlet1() throws Exception { long jobExecutionId; jobExecutionId = startJobMatchEnd(); jobExecutionId = startJobMatchOther(); jobExecutionId = startJobMatchFail(); jobExecutionId = restartJobMatchStop(jobExecutionId); } /** * The stopped job execution in this test will be restarted in test * {@link JobDataTest#testRestartPositionFromBatchlet2Test()} * @throws Exception * * @see JobDataTest#testRestartPositionFromBatchlet2Test() */ @Test public void testStopWithRestartPoint() throws Exception { final Properties params = Batchlet1Test.createParams(Batchlet1.ACTION, Batchlet1.ACTION_STOP); System.out.printf("Start with params %s%n", params); final long jobExecutionId = jobOperator.start(jobName2, params); final JobExecutionImpl jobExecution = (JobExecutionImpl) jobOperator.getJobExecution(jobExecutionId); jobExecution.awaitTermination(waitTimeoutMinutes, TimeUnit.MINUTES); System.out.printf("JobExecution id: %s%n", jobExecution.getExecutionId()); Assert.assertEquals(BatchStatus.STOPPED, jobExecution.getBatchStatus()); Assert.assertEquals(Batchlet1.ACTION_STOP, jobExecution.getExitStatus()); Assert.assertEquals(5, jobExecution.getStepExecutions().size()); Assert.assertEquals(BatchStatus.COMPLETED, jobExecution.getStepExecutions().get(0).getBatchStatus()); Assert.assertEquals(BatchStatus.COMPLETED, jobExecution.getStepExecutions().get(1).getBatchStatus()); Assert.assertEquals(BatchStatus.COMPLETED, jobExecution.getStepExecutions().get(2).getBatchStatus()); Assert.assertEquals(BatchStatus.COMPLETED, jobExecution.getStepExecutions().get(3).getBatchStatus()); Assert.assertEquals(BatchStatus.COMPLETED, jobExecution.getStepExecutions().get(4).getBatchStatus()); writeOutExecutionId(jobExecutionId, jobName2ExecutionIdSaveTo); } // the failed job execution in this test will be restarted in test // org.jberet.se.test.JobDataTest.testRestartWithLimit() @Test public void testStepFail3Times() throws Exception { final JobExecutionImpl[] jobExecutions = new JobExecutionImpl[3]; final Properties params = Batchlet1Test.createParams(Batchlet1.ACTION, Batchlet1.ACTION_EXCEPTION); { System.out.printf("Start with params %s%n", params); long jobExecutionId = jobOperator.start(jobName3, params); JobExecutionImpl jobExecution = (JobExecutionImpl) jobOperator.getJobExecution(jobExecutionId); jobExecution.awaitTermination(waitTimeoutMinutes, TimeUnit.MINUTES); jobExecutions[0] = jobExecution; System.out.printf("Restart with params %s%n", params); jobExecutionId = jobOperator.restart(jobExecutionId, params); jobExecution = (JobExecutionImpl) jobOperator.getJobExecution(jobExecutionId); jobExecution.awaitTermination(waitTimeoutMinutes, TimeUnit.MINUTES); jobExecutions[1] = jobExecution; System.out.printf("Restart with params %s%n", params); jobExecutionId = jobOperator.restart(jobExecutionId, params); jobExecution = (JobExecutionImpl) jobOperator.getJobExecution(jobExecutionId); jobExecution.awaitTermination(waitTimeoutMinutes, TimeUnit.MINUTES); jobExecutions[2] = jobExecution; } for (final JobExecutionImpl e : jobExecutions) { System.out.printf("JobExecution id: %s%n", e.getExecutionId()); Assert.assertEquals(BatchStatus.FAILED, e.getBatchStatus()); Assert.assertEquals(BatchStatus.FAILED.name(), e.getExitStatus()); Assert.assertEquals(1, e.getStepExecutions().size()); Assert.assertEquals(BatchStatus.FAILED, e.getStepExecutions().get(0).getBatchStatus()); Assert.assertEquals(Batchlet1.ACTION_EXCEPTION, e.getStepExecutions().get(0).getExitStatus()); } writeOutExecutionId(jobExecutions[2].getExecutionId(), jobName3ExecutionIdSaveTo); } /** * stepFailWithLongException will throw an exception with very long message, and the exception should be truncated * and stored in job repository STEP_EXECUTION table without causing database error. * * @throws Exception */ @Test public void testStepFailWithLongException() throws Exception { final Properties params = Batchlet1Test.createParams(Batchlet1.ACTION, Batchlet1.ACTION_LONG_EXCEPTION); System.out.printf("Start with params %s%n", params); final long jobExecutionId = jobOperator.start(jobName4, params); final JobExecutionImpl jobExecution = (JobExecutionImpl) jobOperator.getJobExecution(jobExecutionId); jobExecution.awaitTermination(waitTimeoutMinutes, TimeUnit.MINUTES); Assert.assertEquals(BatchStatus.FAILED, jobExecution.getBatchStatus()); final StepExecutionImpl stepExecution = (StepExecutionImpl) jobExecution.getStepExecutions().get(0); Assert.assertEquals(BatchStatus.FAILED, stepExecution.getBatchStatus()); Assert.assertEquals(Batchlet1.ACTION_LONG_EXCEPTION, stepExecution.getExitStatus()); final Exception exception = stepExecution.getException(); Assert.assertNotNull(exception); final String message = exception.getMessage(); //System.out.printf("Step exception message: %s%n", message.substring(0, Math.min(message.length(), 1000))); Assert.assertEquals(true, message.startsWith(Batchlet1.ACTION_LONG_EXCEPTION)); } static Properties createParams(final String key, final String val) { final Properties params = new Properties(); if (key != null) { params.setProperty(key, val); } return params; } private long startJobMatchOther() throws Exception { final Properties params = createParams(Batchlet1.ACTION, Batchlet1.ACTION_OTHER); //start the job and complete step1 and step2, not matching any transition element in step2 System.out.printf("Start with params %s%n", params); final long jobExecutionId = jobOperator.start(jobName, params); final JobExecutionImpl jobExecution = (JobExecutionImpl) jobOperator.getJobExecution(jobExecutionId); jobExecution.awaitTermination(waitTimeoutMinutes, TimeUnit.MINUTES); System.out.printf("JobExecution id: %s%n", jobExecution.getExecutionId()); Assert.assertEquals(BatchStatus.COMPLETED, jobExecution.getBatchStatus()); Assert.assertEquals(BatchStatus.COMPLETED.name(), jobExecution.getExitStatus()); Assert.assertEquals(2, jobExecution.getStepExecutions().size()); Assert.assertEquals(BatchStatus.COMPLETED, jobExecution.getStepExecutions().get(0).getBatchStatus()); Assert.assertEquals(BatchStatus.COMPLETED.name(), jobExecution.getStepExecutions().get(0).getExitStatus()); Assert.assertEquals(BatchStatus.COMPLETED, jobExecution.getStepExecutions().get(1).getBatchStatus()); Assert.assertEquals(Batchlet1.ACTION_OTHER, jobExecution.getStepExecutions().get(1).getExitStatus()); return jobExecutionId; } private long startJobMatchEnd() throws Exception { //start the job and complete step1 and step2, matching <end> element in step2 final Properties params = createParams(Batchlet1.ACTION, Batchlet1.ACTION_END); System.out.printf("Start with params %s%n", params); final long jobExecutionId = jobOperator.start(jobName, params); final JobExecutionImpl jobExecution = (JobExecutionImpl) jobOperator.getJobExecution(jobExecutionId); jobExecution.awaitTermination(waitTimeoutMinutes, TimeUnit.MINUTES); System.out.printf("JobExecution id: %s%n", jobExecution.getExecutionId()); Assert.assertEquals(BatchStatus.COMPLETED, jobExecution.getBatchStatus()); Assert.assertEquals(Batchlet1.ACTION_END, jobExecution.getExitStatus()); Assert.assertEquals(2, jobExecution.getStepExecutions().size()); Assert.assertEquals(BatchStatus.COMPLETED, jobExecution.getStepExecutions().get(0).getBatchStatus()); Assert.assertEquals(BatchStatus.COMPLETED.name(), jobExecution.getStepExecutions().get(0).getExitStatus()); Assert.assertEquals(BatchStatus.COMPLETED, jobExecution.getStepExecutions().get(1).getBatchStatus()); Assert.assertEquals(Batchlet1.ACTION_END, jobExecution.getStepExecutions().get(1).getExitStatus()); return jobExecutionId; } private long startJobMatchFail() throws Exception { //start the job and fail at the end of step2, matching <fail> element in step2 final Properties params = createParams(Batchlet1.ACTION, Batchlet1.ACTION_FAIL); System.out.printf("Start with params %s%n", params); final long jobExecutionId = jobOperator.start(jobName, params); final JobExecutionImpl jobExecution = (JobExecutionImpl) jobOperator.getJobExecution(jobExecutionId); jobExecution.awaitTermination(waitTimeoutMinutes, TimeUnit.MINUTES); System.out.printf("JobExecution id: %s%n", jobExecution.getExecutionId()); Assert.assertEquals(BatchStatus.FAILED, jobExecution.getBatchStatus()); Assert.assertEquals(Batchlet1.ACTION_FAIL, jobExecution.getExitStatus()); //set by <fail> element Assert.assertEquals(2, jobExecution.getStepExecutions().size()); Assert.assertEquals(BatchStatus.COMPLETED, jobExecution.getStepExecutions().get(0).getBatchStatus()); Assert.assertEquals(BatchStatus.COMPLETED.name(), jobExecution.getStepExecutions().get(0).getExitStatus()); // <fail> element does not affect the already-completed step batchlet execution. // Although the job FAILED, but step2 still COMPLETED Assert.assertEquals(BatchStatus.COMPLETED, jobExecution.getStepExecutions().get(1).getBatchStatus()); // step2 exit status from batchlet1.process method return value, not from <fail exit-status> element Assert.assertEquals(Batchlet1.ACTION_FAIL, jobExecution.getStepExecutions().get(1).getExitStatus()); return jobExecutionId; } private long restartJobMatchStop(final long previousJobExecutionId) throws Exception { //restart the job and stop at the end of step2, matching <stop> element in step2. //next time this job execution is restarted, it should restart from restart-point step2 final Properties params = createParams(Batchlet1.ACTION, Batchlet1.ACTION_STOP); System.out.printf("Restart with params %s%n", params); final long jobExecutionId = jobOperator.restart(previousJobExecutionId, params); final JobExecutionImpl jobExecution = (JobExecutionImpl) jobOperator.getJobExecution(jobExecutionId); jobExecution.awaitTermination(waitTimeoutMinutes, TimeUnit.MINUTES); System.out.printf("JobExecution id: %s%n", jobExecution.getExecutionId()); Assert.assertEquals(BatchStatus.STOPPED, jobExecution.getBatchStatus()); Assert.assertEquals(Batchlet1.ACTION_STOP, jobExecution.getExitStatus()); Assert.assertEquals(1, jobExecution.getStepExecutions().size()); // <stop> element does not affect the already-completed step batchlet execution. // Although the job STOPPED, but step2 still COMPLETED Assert.assertEquals(BatchStatus.COMPLETED, jobExecution.getStepExecutions().get(0).getBatchStatus()); // step2 exit status from batchlet1.process method return value, not from <stop exit-status> element Assert.assertEquals(Batchlet1.ACTION_STOP, jobExecution.getStepExecutions().get(0).getExitStatus()); return jobExecutionId; } static void writeOutExecutionId(final long executionId, final File file) throws IOException { final BufferedWriter bw = new BufferedWriter(new FileWriter(file)); final String s = String.valueOf(executionId); try { bw.write(s, 0, s.length()); System.out.printf("Wrote out job execution id to: %s%n", file.getPath()); } finally { try { bw.close(); } catch (IOException e) { //ignore } } } }