not name job_name job_key job_instance_id invalid initialize from exist example does batch_job_instance batch and java spring spring-batch

java - name - ¿Spring-Batch sin metadatos persistentes en la base de datos?



spring batch example (9)

Quiero crear un trabajo por spring-batch , pero quiero ejecutarlo sin ninguna persistencia de base de datos. Desafortunadamente, Spring-batch requiere escribir metadata los ciclos de trabajo en una base de datos de alguna manera, procurando así proporcionar al menos algún tipo de base de datos con el administrador de transacciones y el administrador de entidades.

¿Es posible evitar los metadatos y ejecutarse independientemente de txmanagers y bases de datos?

Actualizar:

ERROR org.springframework.batch.core.job.AbstractJob: Encountered fatal error executing job java.lang.NullPointerException at org.springframework.batch.core.repository.dao.MapJobExecutionDao.synchronizeStatus(MapJobExecutionDao.java:158) ~[spring-batch-core-3.0.1.RELEASE.jar:3.0.1.RELEASE] at org.springframework.batch.core.repository.support.SimpleJobRepository.update(SimpleJobRepository.java:161) ~[spring-batch-core-3.0.1.RELEASE.jar:3.0.1.RELEASE] at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) ~[?:1.7.0_51] at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57) ~[?:1.7.0_51] at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) ~[?:1.7.0_51] at java.lang.reflect.Method.invoke(Method.java:606) ~[?:1.7.0_51] at org.springframework.aop.support.AopUtils.invokeJoinpointUsingReflection(AopUtils.java:317) ~[spring-aop-4.0.6.RELEASE.jar:4.0.6.RELEASE] at org.springframework.aop.framework.ReflectiveMethodInvocation.invokeJoinpoint(ReflectiveMethodInvocation.java:190) ~[spring-aop-4.0.6.RELEASE.jar:4.0.6.RELEASE] at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:157) ~[spring-aop-4.0.6.RELEASE.jar:4.0.6.RELEASE] at org.springframework.transaction.interceptor.TransactionInterceptor$1.proceedWithInvocation(TransactionInterceptor.java:98) ~[spring-tx-4.0.6.RELEASE.jar:4.0.6.RELEASE] at org.springframework.transaction.interceptor.TransactionAspectSupport.invokeWithinTransaction(TransactionAspectSupport.java:262) ~[spring-tx-4.0.6.RELEASE.jar:4.0.6.RELEASE] at org.springframework.transaction.interceptor.TransactionInterceptor.invoke(TransactionInterceptor.java:95) ~[spring-tx-4.0.6.RELEASE.jar:4.0.6.RELEASE] at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:179) ~[spring-aop-4.0.6.RELEASE.jar:4.0.6.RELEASE] at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:207) ~[spring-aop-4.0.6.RELEASE.jar:4.0.6.RELEASE] at com.sun.proxy.$Proxy134.update(Unknown Source) ~[?:?] at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) ~[?:1.7.0_51] at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57) ~[?:1.7.0_51] at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) ~[?:1.7.0_51] at java.lang.reflect.Method.invoke(Method.java:606) ~[?:1.7.0_51] at org.springframework.aop.support.AopUtils.invokeJoinpointUsingReflection(AopUtils.java:317) ~[spring-aop-4.0.6.RELEASE.jar:4.0.6.RELEASE] at org.springframework.aop.framework.ReflectiveMethodInvocation.invokeJoinpoint(ReflectiveMethodInvocation.java:190) ~[spring-aop-4.0.6.RELEASE.jar:4.0.6.RELEASE] at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:157) ~[spring-aop-4.0.6.RELEASE.jar:4.0.6.RELEASE] at org.springframework.batch.core.configuration.annotation.SimpleBatchConfiguration$PassthruAdvice.invoke(SimpleBatchConfiguration.java:127) ~[spring-batch-core-3.0.1.RELEASE.jar:3.0.1.RELEASE] at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:179) ~[spring-aop-4.0.6.RELEASE.jar:4.0.6.RELEASE] at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:207) ~[spring-aop-4.0.6.RELEASE.jar:4.0.6.RELEASE] at com.sun.proxy.$Proxy134.update(Unknown Source) ~[?:?] at org.springframework.batch.core.job.AbstractJob.updateStatus(AbstractJob.java:416) ~[spring-batch-core-3.0.1.RELEASE.jar:3.0.1.RELEASE] at org.springframework.batch.core.job.AbstractJob.execute(AbstractJob.java:299) [spring-batch-core-3.0.1.RELEASE.jar:3.0.1.RELEASE] at org.springframework.batch.core.launch.support.SimpleJobLauncher$1.run(SimpleJobLauncher.java:135) [spring-batch-core-3.0.1.RELEASE.jar:3.0.1.RELEASE] at org.springframework.core.task.SyncTaskExecutor.execute(SyncTaskExecutor.java:50) [spring-core-4.0.6.RELEASE.jar:4.0.6.RELEASE] at org.springframework.batch.core.launch.support.SimpleJobLauncher.run(SimpleJobLauncher.java:128) [spring-batch-core-3.0.1.RELEASE.jar:3.0.1.RELEASE] at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) ~[?:1.7.0_51] at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57) ~[?:1.7.0_51] at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) ~[?:1.7.0_51] at java.lang.reflect.Method.invoke(Method.java:606) ~[?:1.7.0_51] at org.springframework.aop.support.AopUtils.invokeJoinpointUsingReflection(AopUtils.java:317) [spring-aop-4.0.6.RELEASE.jar:4.0.6.RELEASE] at org.springframework.aop.framework.ReflectiveMethodInvocation.invokeJoinpoint(ReflectiveMethodInvocation.java:190) [spring-aop-4.0.6.RELEASE.jar:4.0.6.RELEASE] at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:157) [spring-aop-4.0.6.RELEASE.jar:4.0.6.RELEASE] at org.springframework.batch.core.configuration.annotation.SimpleBatchConfiguration$PassthruAdvice.invoke(SimpleBatchConfiguration.java:127) [spring-batch-core-3.0.1.RELEASE.jar:3.0.1.RELEASE] at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:179) [spring-aop-4.0.6.RELEASE.jar:4.0.6.RELEASE] at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:207) [spring-aop-4.0.6.RELEASE.jar:4.0.6.RELEASE] at com.sun.proxy.$Proxy50.run(Unknown Source) [?:?]


Quiero ejecutarlo sin ninguna persistencia en la base de datos.

Puede usar MapJobRepositoryFactoryBean y ResourcelessTransactionManager

configuración de muestra:

<bean id="transactionManager" class="org.springframework.batch.support.transaction.ResourcelessTransactionManager" /> <bean id="jobRepository" class="org.springframework.batch.core.repository.support.MapJobRepositoryFactoryBean"> <property name="transactionManager" ref="transactionManager" /> </bean> <bean id="jobLauncher" class="org.springframework.batch.core.launch.support.SimpleJobLauncher"> <property name="jobRepository" ref="jobRepository" /> </bean>

Para Spring 4.X, la configuración basada en anotaciones sería la siguiente:

@Bean public PlatformTransactionManager getTransactionManager() { return new ResourcelessTransactionManager(); } @Bean public JobRepository getJobRepo() { return new MapJobRepositoryFactoryBean(getTransactionManager()).getObject(); }


Además de la respuesta de @ Braj-s tuve que excluir la configuración automática de lotes: @SpringBootApplication(exclude = {BatchAutoConfiguration.class})

No estaba funcionando de otra manera. Esto incluye la aplicación Spring Boot.


Después de ajustar la respuesta de @ Braj, mi configuración de trabajo es la siguiente:

@Bean public ResourcelessTransactionManager transactionManager() { return new ResourcelessTransactionManager(); } @Bean public JobRepository jobRepository(ResourcelessTransactionManager transactionManager) throws Exception { MapJobRepositoryFactoryBean mapJobRepositoryFactoryBean = new MapJobRepositoryFactoryBean(transactionManager); mapJobRepositoryFactoryBean.setTransactionManager(transactionManager); return mapJobRepositoryFactoryBean.getObject(); } @Bean public SimpleJobLauncher jobLauncher(JobRepository jobRepository) { SimpleJobLauncher simpleJobLauncher = new SimpleJobLauncher(); simpleJobLauncher.setJobRepository(jobRepository); return simpleJobLauncher; }


Después de leer todas las respuestas proporcionadas, lo puse funcionando. Utilicé la mezcla de membersound y la solución Aure77. Descubrí que no era necesario anular el método setDataSource. DefaultBatchConfigurer se encarga automáticamente de PlatformTransactionManager y no se requiere DataSource. Tenga en cuenta que estoy usando Spring boot 2.0.3.RELEASE. A continuación se muestra el método que utilicé.

@SpringBootApplication(exclude = { DataSourceAutoConfiguration.class }) @EnableBatchProcessing public class DemoApplication extends DefaultBatchConfigurer { @Autowired private JobBuilderFactory jobs; @Autowired private StepBuilderFactory steps; @Bean protected Tasklet tasklet() { return new Tasklet() { @Override public RepeatStatus execute(StepContribution contribution, ChunkContext context) { return RepeatStatus.FINISHED; } }; } @Bean public Job job() throws Exception { return this.jobs.get("job").start(step1()).build(); } @Bean protected Step step1() throws Exception { return this.steps.get("step1").tasklet(tasklet()).build(); } public static void main(String[] args) throws Exception { //System.exit(SpringApplication.exit(SpringApplication.run(DemoApplication.class, args))); SpringApplication.run(DemoApplication.class, args); } }


El más simple de todos es agregar una base de datos incrustada a classpath. Naturalmente, no se recomienda en producción, pero si lo está utilizando para aprender, ahorre tiempo.

Agregue a su pom.xml la dependencia de la base de datos H2 incrustada:

<dependency> <groupId>com.h2database</groupId> <artifactId>h2</artifactId> <scope>runtime</scope> </dependency>

Eso es todo.


Intenté todas las soluciones anteriores, pero no funciona con mi escenario particular porque mi trabajo por lotes de primavera tiene características avanzadas como multihilo. Necesita una base de datos. Así que aquí está lo que hice para resolver el problema:

@Autowired private DataSource dataSource;


Si no desea almacenar los metadatos del trabajo en la base de datos, la configuración es la siguiente:

@Configuration public class FakeBatchConfig implements BatchConfigurer { PlatformTransactionManager transactionManager; JobRepository jobRepository; JobLauncher jobLauncher; JobExplorer jobExplorer; @Override public JobRepository getJobRepository() { return jobRepository; } @Override public PlatformTransactionManager getTransactionManager() { return transactionManager; } @Override public JobLauncher getJobLauncher() { return jobLauncher; } @Override public JobExplorer getJobExplorer() { return jobExplorer; } @PostConstruct void initialize() throws Exception { if (this.transactionManager == null) { this.transactionManager = new ResourcelessTransactionManager(); } MapJobRepositoryFactoryBean jobRepositoryFactory = new MapJobRepositoryFactoryBean(this.transactionManager); jobRepositoryFactory.afterPropertiesSet(); this.jobRepository = jobRepositoryFactory.getObject(); MapJobExplorerFactoryBean jobExplorerFactory = new MapJobExplorerFactoryBean(jobRepositoryFactory); jobExplorerFactory.afterPropertiesSet(); this.jobExplorer = jobExplorerFactory.getObject(); this.jobLauncher = createJobLauncher(); } private JobLauncher createJobLauncher() throws Exception { SimpleJobLauncher jobLauncher = new SimpleJobLauncher(); jobLauncher.setJobRepository(jobRepository); jobLauncher.afterPropertiesSet(); return jobLauncher; } }

Si el trabajo necesita leer / escribir datos comerciales en la base de datos y la fuente de datos se configura de la siguiente manera.

@Configuration public class InMemoryJobRepositoryConfiguration { @Bean public ResourcelessTransactionManager transactionManager() { return new ResourcelessTransactionManager(); } @Bean public MapJobRepositoryFactoryBean mapJobRepositoryFactory(ResourcelessTransactionManager transactionManager) throws Exception { MapJobRepositoryFactoryBean factory = new MapJobRepositoryFactoryBean(transactionManager); factory.afterPropertiesSet(); return factory; } @Bean public JobRepository jobRepository(MapJobRepositoryFactoryBean repositoryFactory) throws Exception { return repositoryFactory.getObject(); } @Bean public JobExplorer jobExplorer(MapJobRepositoryFactoryBean repositoryFactory) { return new SimpleJobExplorer(repositoryFactory.getJobInstanceDao(), repositoryFactory.getJobExecutionDao(), repositoryFactory.getStepExecutionDao(), repositoryFactory.getExecutionContextDao()); } @Bean public SimpleJobLauncher jobLauncher(JobRepository jobRepository) { SimpleJobLauncher launcher = new SimpleJobLauncher(); launcher.setJobRepository(jobRepository); return launcher; } }

spring batch crea un esquema interno (BATCH_ * tablas y secuencias) usando esa fuente de datos. Para evitar que esto suceda, establezca el indicador spring.batch.initializer.enabled=false en application.properties.


Simplemente cree una configuración sin fuente de datos para la configuración por lotes:

@Configuration @EnableAutoConfiguration @EnableBatchProcessing public class BatchConfiguration extends DefaultBatchConfigurer { @Override public void setDataSource(DataSource dataSource) { // override to do not set datasource even if a datasource exist. // initialize will use a Map based JobRepository (instead of database) } }

Inicializará JobRepository y JobExplorer con una implementación basada en mapas de memoria. https://github.com/spring-projects/spring-batch/blob/342d27bc1ed83312bdcd9c0cb30510f4c469e47d/spring-batch-core/src/main/java/org/springframework/batch/core/configuration/annotation/DefaultBatchConfigurer.java#L84

y también puede usar su fuente de datos de producción incluso si se configura automáticamente con Spring Boot.


Volví a mi propia pregunta, ya que la solución ya no funcionaba. A partir de spring-batch-1.5.3 usar de la siguiente manera:

@SpringBootApplication(exclude = {DataSourceAutoConfiguration.class}) ... @Bean public PlatformTransactionManager transactionManager() { return new ResourcelessTransactionManager(); } }