
001package ca.uhn.fhir.jpa.bulk.imprt.job; 002 003/*- 004 * #%L 005 * HAPI FHIR JPA Server 006 * %% 007 * Copyright (C) 2014 - 2022 Smile CDR, Inc. 008 * %% 009 * Licensed under the Apache License, Version 2.0 (the "License"); 010 * you may not use this file except in compliance with the License. 011 * You may obtain a copy of the License at 012 * 013 * http://www.apache.org/licenses/LICENSE-2.0 014 * 015 * Unless required by applicable law or agreed to in writing, software 016 * distributed under the License is distributed on an "AS IS" BASIS, 017 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 018 * See the License for the specific language governing permissions and 019 * limitations under the License. 020 * #L% 021 */ 022 023import ca.uhn.fhir.jpa.batch.config.BatchConstants; 024import ca.uhn.fhir.jpa.bulk.imprt.api.IBulkDataImportSvc; 025import ca.uhn.fhir.jpa.bulk.imprt.model.BulkImportJobStatusEnum; 026import org.springframework.batch.core.ExitStatus; 027import org.springframework.batch.core.StepExecution; 028import org.springframework.batch.core.StepExecutionListener; 029import org.springframework.batch.core.jsr.RetryListener; 030import org.springframework.beans.factory.annotation.Autowired; 031import org.springframework.retry.ExhaustedRetryException; 032 033import javax.annotation.Nonnull; 034 035import static org.apache.commons.lang3.StringUtils.isNotBlank; 036 037/** 038 * This class sets the job status to ERROR if any failures occur while actually 039 * generating the export files. 040 */ 041public class BulkImportStepListener implements StepExecutionListener, RetryListener { 042 043 @Autowired 044 private IBulkDataImportSvc myBulkDataImportSvc; 045 046 @Override 047 public void beforeStep(@Nonnull StepExecution stepExecution) { 048 // nothing 049 } 050 051 @Override 052 public ExitStatus afterStep(StepExecution theStepExecution) { 053 if (theStepExecution.getExitStatus().getExitCode().equals(ExitStatus.FAILED.getExitCode())) { 054 //Try to fetch it from the parameters first, and if it doesn't exist, fetch it from the context. 055 String jobUuid = theStepExecution.getJobExecution().getJobParameters().getString(BatchConstants.JOB_UUID_PARAMETER); 056 if (jobUuid == null) { 057 jobUuid = theStepExecution.getJobExecution().getExecutionContext().getString(BatchConstants.JOB_UUID_PARAMETER); 058 } 059 assert isNotBlank(jobUuid); 060 061 StringBuilder message = new StringBuilder(); 062 message.append("Job: ").append(theStepExecution.getExecutionContext().getString(BulkImportPartitioner.JOB_DESCRIPTION)).append("\n"); 063 message.append("File: ").append(theStepExecution.getExecutionContext().getString(BulkImportPartitioner.FILE_DESCRIPTION)).append("\n"); 064 for (Throwable next : theStepExecution.getFailureExceptions()) { 065 if (next instanceof ExhaustedRetryException) { 066 next = next.getCause(); // ExhaustedRetryException is a spring exception that wraps the real one 067 } 068 String nextErrorMessage = next.toString(); 069 message.append("Error: ").append(nextErrorMessage).append("\n"); 070 } 071 072 theStepExecution.addFailureException(new RuntimeException(message.toString())); 073 074 myBulkDataImportSvc.setJobToStatus(jobUuid, BulkImportJobStatusEnum.ERROR, message.toString()); 075 076 ExitStatus exitStatus = ExitStatus.FAILED.addExitDescription(message.toString()); 077 theStepExecution.setExitStatus(exitStatus); 078 079 // Replace the built-in error message with a better one 080 return exitStatus; 081 } 082 083 return theStepExecution.getExitStatus(); 084 } 085}