Necesito poder acceder al nombre del archivo plano del que proviene la línea actual que se lee. Estamos portando una aplicación y algunos procesos que están actualmente en marcha requieren esta información.
Aquí está mi configuración actual:
private FlatFileItemReader<Invoice> invoiceFlatFileItemReader() throws Exception { FlatFileItemReader<Invoice> reader = new FlatFileItemReader<>(); reader.setLinesToSkip(1); // header row reader.setLineMapper(new InvoiceLineMapper()); reader.afterPropertiesSet(); return reader; }
Asignador de línea de factura:
public class InvoiceLineMapper implements LineMapper<Invoice> { @Override public Invoice mapLine(String line, int lineNumber) throws Exception { String[] fields = line.split(","); ArrayList<String> fieldList = new ArrayList<>(); for (int i = 0; i < fields.length; i++) { fieldList.add(fields[i].replaceAll("\"", ""); } Invoice invoice = new Invoice(); invoice.setCustomerNumber(Integer.parseInt(fieldList.get(0)); invoice.setCustomerName(fieldList.get(1)); // set other things and stuff... //Need to be able to set the file name on the model here invoice.setFileName(theFileName); } }
Estoy delegando a la invoiceFlatFileItemReader()
a través de un MultiResourceItemReader
:
@Bean public ItemReader<Invoice> invoiceItemReader() throws Exception { ResourcePatternResolver resolver = new PathMatchingResourcePatterResolver(this.getClass().getClassLoader()); // currently being loaded from the classpath, eventually will be read from S3...that comes later Resource[] resources = resolver.getResources("classpath*:**/InvoiceList*.csv*"); MultiResourceItemReader<Invoice> reader = new MultiResourceItemReader<>(); reader.setResources(resources); reader.setDelegate(invoiceFlatFileItemReader()); return reader; }
¿Cómo puedo pasar el nombre del recurso por la cadena hasta donde puedo acceder a él en la clase InvoiceLineMapper
y agregarlo al modelo (que luego se conserva con un RepositoryItemWriter
)?
Hay una interfaz ResourceAware
que su artículo puede implementar. Si implementa esa interfaz, al usar MultiResourceItemReader
, el recurso se inyectará automáticamente. Puede leer más sobre la interfaz de ResourceAware
en la documentación aquí: http://docs.spring.io/spring-batch/apidocs/org/springframework/batch/item/ResourceAware.html
Esto es lo que terminé haciendo, simplemente pasando el MultiItemResourceReader
por la cadena para poder llamar a getCurrentResource()
en el mapeador de líneas:
@Bean public ItemReader<Invoice> invoiceItemReader() throws Exception { ResourcePatternResolver resolver = new PathMatchingResourcePatterResolver(this.getClass().getClassLoader()); // currently being loaded from the classpath, eventually will be read from S3...that comes later Resource[] resources = resolver.getResources("classpath*:**/InvoiceList*.csv*"); MultiResourceItemReader<Invoice> reader = new MultiResourceItemReader<>(); reader.setResources(resources); reader.setDelegate(invoiceFlatFileItemReader(reader)); return reader; } private FlatFileItemReader<Invoice> invoiceFlatFileItemReader(MultiResourceItemReader delegator) throws Exception { FlatFileItemReader<Invoice> reader = new FlatFileItemReader<>(); reader.setLinesToSkip(1); // header row reader.setLineMapper(new InvoiceLineMapper(delegator)); reader.afterPropertiesSet(); return reader; }
Y luego en InvoiceLineMapper
:
public class InvoiceLineMapper implements LineMapper<Invoice> { private MultiResourceItemReader delegator; public InvoiceLineMapper(MultiResourceItemReader delegator) { this.delegator = delegator; } @Override public Invoice mapLine(String line, int lineNumber) throws Exception { String[] fields = line.split(","); ArrayList<String> fieldList = new ArrayList<>(); for (int i = 0; i < fields.length; i++) { fieldList.add(fields[i].replaceAll("\"", ""); } Invoice invoice = new Invoice(); invoice.setCustomerNumber(Integer.parseInt(fieldList.get(0)); invoice.setCustomerName(fieldList.get(1)); // set other things and stuff... Resource currentResource = delegator.getCurrentResource(); String[] fileName = currentResource.getFilename().split("/"); invoice.setFileName(filename[filename.length - 1]); return invoice; } }