/// <summary> /// Logic launched after the step. Will launch the postprocessor. /// @see IStepExecutionListener#AfterStep /// </summary> /// <param name="stepExecution"></param> /// <returns></returns> public virtual ExitStatus AfterStep(StepExecution stepExecution) { ExitStatus returnStatus = stepExecution.ExitStatus; if (!"FAILED".Equals(returnStatus.ExitCode)) { MethodInfo post = this.GetType().GetMethod("Postprocess", BindingFlags.Instance | BindingFlags.NonPublic); if (post.DeclaringType != typeof(AbstractExecutionListener)) { using (var scope = TransactionScopeManager.CreateScope()) { try { returnStatus = Postprocess(); } catch (Exception e) { // Need to catch exception to log and set status to FAILED, while // Spring batch would only log and keep the status COMPLETED Logger.Error(e, "Exception during postprocessor"); stepExecution.UpgradeStatus(BatchStatus.Failed); throw; } scope.Complete(); } } } return(returnStatus); }
public void FlatFileTestTransactionalTest() { var writer = new FlatFileItemWriter <Person> { Resource = new FileSystemResource(_testPath2), LineAggregator = new LineAggregator(), HeaderWriter = new HeaderWriter() }; var reader = new FlatFileItemReader <Person> { Resource = new FileSystemResource(_testPath2), LinesToSkip = 2, LineMapper = new LineMapper() }; var executionContext = new ExecutionContext(); writer.Open(executionContext); try { for (int i = 0; i < CountTransactions; i++) { using (TransactionScope scope = TransactionScopeManager.CreateScope()) { writer.Write(GetPersons(i)); if (i == CountTransactions - 1) //SIMULATE FAILURE { throw new Exception("Bailing out ... should rollback ..."); } scope.Complete(); } } } catch (Exception e) { Logger.Error(e, "An unexpected exception occured :"); } writer.Close(); var persons = new List <Person>(); reader.Open(executionContext); Person person; while ((person = reader.Read()) != null) { persons.Add(person); } reader.Close(); Assert.AreEqual((CountTransactions - 1) * CountObjects, persons.Count); for (var i = 0; i < persons.Count; i++) { Assert.AreEqual(i % CountObjects, persons[i].Id); Assert.IsTrue(persons[i].Name.StartsWith("Person" + i % CountObjects)); } }
/// <summary> /// Actual taskletstep execution. /// </summary> /// <param name="stepExecution"></param> /// <exception cref="Exception"> </exception> protected override void DoExecute(StepExecution stepExecution) { stepExecution.ExecutionContext.Put(TaskletTypeKey, _tasklet.GetType().Name); stepExecution.ExecutionContext.Put(StepConstants.StepTypeKey, GetType().Name); _stream.Update(stepExecution.ExecutionContext); JobRepository.UpdateExecutionContext(stepExecution); JobRepository.UpdateExecutionContext(stepExecution.JobExecution); // Shared semaphore per step execution, so other step executions can run // in parallel without needing the lock Semaphore semaphore = CreateSemaphore(); _stepOperations.Iterate(StepContextRepeatCallback.GetRepeatCallback(stepExecution, (context, chunkContext) => { StepExecution lStepExecution = chunkContext.StepContext.StepExecution; _interruptionPolicy.CheckInterrupted(lStepExecution); ChunkTransactionCallback callback = new ChunkTransactionCallback(chunkContext, semaphore, this); RepeatStatus result; using (var scope = TransactionScopeManager.CreateScope()) { TransactionScopeManager.RegisterTransactionSynchronization(scope, callback); try { result = callback.DoInTransaction(); } catch (Exception e) { //Log and rethrow Logger.Error(e, "Transaction will be rollbacked because of an unexpected exception."); throw; // throw to ensure rollback will occur (no complete) } scope.Complete(); } // Release connections since the transaction has ended ConnectionUtil.ReleaseConnections(); Thread.Sleep(stepExecution.DelayConfig); _interruptionPolicy.CheckInterrupted(stepExecution); return(result); } )); }
/// <summary> /// Logic launched after the step. Will launch the postprocessor. /// @see IStepExecutionListener#AfterStep /// </summary> /// <param name="stepExecution"></param> /// <returns></returns> public virtual ExitStatus AfterStep(StepExecution stepExecution) { ExitStatus returnStatus = stepExecution.ExitStatus; if (!"FAILED".Equals(returnStatus.ExitCode)) { MethodInfo post = GetType().GetMethod("Postprocess", BindingFlags.Instance | BindingFlags.NonPublic); // determine worker / master mode for step if (stepExecution.remoteChunking != null) { TimeSpan RemoteChunkingTimoutSecond = stepExecution.remoteChunking.RemoteChunkingTimoutSecond; // master part if (stepExecution.remoteChunking._master) { // wait for Master method send back signal if (!stepExecution.remoteChunking.threadWait.WaitOne(-1)) { Exception e = new JobExecutionException("Master step failed"); Logger.Error(e, "Clean message in the Queue."); throw e; } // some worker failed master need to fail if ("FAILED".Equals(stepExecution.ExitStatus.ExitCode)) { Exception e = new JobExecutionException("Master step failed"); Logger.Error(e, "Clean message in the Queue."); throw e; } // clean all message queues when master completed Logger.Info("Master is completed."); Logger.Info("Clean message in the Queue."); stepExecution.remoteChunking.CleanAllQueue(); } else { if (!stepExecution.remoteChunking.threadWait.WaitOne(-1)) { returnStatus = stepExecution.ExitStatus; throw new JobExecutionException("Worker step failed"); } Logger.Info("Worker is completed."); } } if (post.DeclaringType != typeof(AbstractExecutionListener)) { using (var scope = TransactionScopeManager.CreateScope()) { try { returnStatus = Postprocess(); } catch (Exception e) { // Need to catch exception to log and set status to FAILED, while // Spring batch would only log and keep the status COMPLETED Logger.Error(e, "Exception during postprocessor"); stepExecution.UpgradeStatus(BatchStatus.Failed); throw; } scope.Complete(); } } } // batch failed need to join the thread else if (stepExecution.remoteChunking != null) { stepExecution.remoteChunking.controlThread.Join(); } return(returnStatus); }
public void EbcdicFileTestTransactionalWrite() { // local resources IResource fileResource = new FileSystemResource(new FileInfo("C:/temp/outputs/PersonWritten.txt")); var executionContext = new ExecutionContext(); FileInfo fileInfo = new FileInfo("Ebcdic/Resources/copybooks/Person.fileformat"); IResource copybookResource = new FileSystemResource(fileInfo); //1. WRITE EbcdicWriterMapper writerMapper = new EbcdicWriterMapper(); writerMapper.AfterPropertiesSet(); var writer = new EbcdicFileWriter <Ebcdic.Test.Person> { AppendAllowed = false, WriteRdw = false, Name = "PersonWriter", Resource = fileResource, EbcdicWriterMapper = writerMapper, DefaultValue = EbcdicEncoder.DefaultValue.LowValue, Copybooks = new List <IResource> { new FileSystemResource(fileInfo) } }; writer.AfterPropertiesSet(); writer.Open(executionContext); try { for (int i = 0; i < CountTransactions; i++) { using (TransactionScope scope = TransactionScopeManager.CreateScope()) { writer.Write(GetPersons(i)); if (i == CountTransactions - 1) //SIMULATE FAILURE { throw new Exception("Bailing out ... should rollback ..."); } scope.Complete(); } } } catch (Exception) { // DISCARDED (JUST TO AVOID UNIT TEST FAILURE ...) } writer.Close(); Assert.IsTrue(System.IO.File.Exists("C:/temp/outputs/PersonWritten.txt")); Assert.IsTrue(new FileInfo("C:/temp/outputs/PersonWritten.txt").Length > 0); //2.READ WHAT WAS WRITTEN var reader = new EbcdicFileReader <Ebcdic.Test.Person> { EbcdicReaderMapper = new PersonMapper(), Rdw = false, Resource = fileResource, Name = "PersonReader", SaveState = false, Copybook = copybookResource }; reader.AfterPropertiesSet(); var persons = new List <Ebcdic.Test.Person>(); reader.Open(executionContext); Ebcdic.Test.Person person; while ((person = reader.Read()) != null) { persons.Add(person); } reader.Close(); Assert.AreEqual(CountObject * (CountTransactions - 1), persons.Count); foreach (Ebcdic.Test.Person p in persons) { Assert.AreEqual(p.Id, p.Value); Assert.IsTrue(p.Name.StartsWith("Name_" + p.Id)); } }