es.davy.ai

Preguntas y respuestas de programación confiables

¿Tienes una pregunta?

Si tienes alguna pregunta, puedes hacerla a continuación o ingresar lo que estás buscando.

Cómo registrar los nombres de archivos que se procesaron exitosamente.

Tengo una aplicación de Spring Batch donde estoy procesando múltiples archivos .txt en paralelo. Mi configuración de trabajo simple se ve de la siguiente manera:

@Value("file:input/*.txt")
private Resource[] inputResources;

@Bean("partitioner")
@StepScope
public Partitioner partitioner() {
    log.info("En Partitioner");
    MultiResourcePartitioner partitioner = new MultiResourcePartitioner();
    partitioner.setResources(inputResources);
    partitioner.partition(10);
    return partitioner;
}

@Bean
@StepScope
@Qualifier("nodeItemReader")
@DependsOn("partitioner")
public FlatFileItemReader NodeItemReader(@Value("#{stepExecutionContext['fileName']}") String filename)
        throws MalformedURLException {
    return new FlatFileItemReaderBuilder().name("NodeItemReader").delimited().delimiter("<##>")
            .names(new String[] { "id" }).fieldSetMapper(new BeanWrapperFieldSetMapper() {
                {
                    setTargetType(FolderNodePojo.class);
                }
            }).linesToSkip(0).resource(new UrlResource(filename)).build();
}

Hay miles de archivos .txt con miles de líneas que se están procesando. Algunos archivos tienen datos corruptos y el trabajo falla. Necesito generar y enviar un informe sobre los nombres de los archivos que tienen datos corruptos.

¿Qué debo hacer para registrar el nombre de los archivos que se procesaron correctamente para todas sus líneas, o, si es posible, si puedo registrar los que no fueron exitosos, eso también será de ayuda? Para poder generar un informe basado en eso y también cuando vuelva a comenzar el trabajo, pueda eliminar aquellos que fueron exitosos del directorio input. Cualquier sugerencia/solución será muy apreciada.

Tags:  , ,

Answer

  1. Avatar for davy.ai

    Para registrar el nombre de los archivos que se procesaron correctamente, puedes escribir un ItemWriteListener y un StepExecutionListener personalizados.

    El ItemWriteListener tendrá dos métodos:

    1. onWriteError – Este método se llamará cuando ocurra un error al escribir un elemento. En este método, puedes registrar el nombre del archivo y cualquier otra información relevante que desees incluir en el informe.
    2. afterWrite – Este método se llamará después de una escritura exitosa. En este método, puedes registrar el nombre del archivo y cualquier otra información relevante que desees incluir en el informe.

    El StepExecutionListener tendrá dos métodos:

    1. beforeStep – Este método se llamará antes de que comience el paso. En este método, puedes usar el ExecutionContext para almacenar los nombres de los archivos procesados.
  2. afterStep – Este método se llamará después de que finalice el paso. En este método, puedes recuperar los nombres de los archivos procesados del ExecutionContext y eliminarlos del directorio de entrada.

  3. Aquí tienes un código de ejemplo que muestra cómo implementar el ItemWriteListener y el StepExecutionListener:

    public class FileProcessingListener implements ItemWriteListener<foldernodepojo>, StepExecutionListener {
    
        private List<string> processedFiles = new ArrayList<>();
    
        @Override
        public void beforeStep(StepExecution stepExecution) {
            ExecutionContext executionContext = stepExecution.getExecutionContext();
            executionContext.put("processedFiles", processedFiles);
        }
    
        @Override
        public ExitStatus afterStep(StepExecution stepExecution) {
            ExecutionContext executionContext = stepExecution.getExecutionContext();
            List<string> processedFiles = (List<string>) executionContext.get("processedFiles");
            for (String filename : processedFiles) {
                // Eliminar el archivo procesado del directorio de entrada
                // Código aquí
            }
            return stepExecution.getExitStatus();
        }
    
        @Override
        public void afterWrite(List<? extends FolderNodePojo> items) {
            for(FolderNodePojo item : items) {
                processedFiles.add(item.getFilename());
                // Registrar el nombre del archivo exitoso
                // Código aquí
            }
        }
    
        @Override
        public void onWriteError(Exception exception, List<? extends FolderNodePojo> items) {
            for(FolderNodePojo item : items) {
                // Registrar el nombre del archivo fallido
                // Código aquí
            }
        }
    
    }
    

    Debes registrar el listener en tu paso. Así es cómo puedes agregar el listener a tu paso:

    @Bean
    public Step step1() {
        return stepBuilderFactory.get("step1")
                .<foldernodepojo, foldernodepojo="">chunk(10)
                .reader(NodeItemReader(null))
                .writer( /* tu escritor */)
                .listener(new FileProcessingListener())
                .build();
    }
    

    Con esta implementación, tendrás una lista de archivos procesados que podrás utilizar para generar el informe y eliminar los archivos que se procesaron correctamente.</foldernodepojo,>

Comments are closed.