2016-11-02 7 views
0

Ich bin neu in Spring Batch und versuche, mit einer einfachen Spring Batch-Anwendung (http://spring.io/guides/gs/batch-processing/) zu arbeiten und versuche, es zu konvertieren, um Oracle als Speichermechanismus zu verwenden.Spring Batch - Ressource darf nicht null sein

Das Problem, das ich renne, ist unten;

INFO 22152 --- [   main] o.s.b.c.l.support.SimpleJobLauncher  : Job: [FlowJob: [name=importUserJob]] failed unexpectedly and fatally with the following parameters: [{run.id=7, -spring.output.ansi.enabled=always}] 

java.lang.IllegalStateException: Failed to execute CommandLineRunner 
at org.springframework.boot.SpringApplication.callRunner(SpringApplication.java:803) [spring-boot-1.4.1.RELEASE.jar:1.4.1.RELEASE] 
at org.springframework.boot.SpringApplication.callRunners(SpringApplication.java:784) [spring-boot-1.4.1.RELEASE.jar:1.4.1.RELEASE] 
at org.springframework.boot.SpringApplication.afterRefresh(SpringApplication.java:771) [spring-boot-1.4.1.RELEASE.jar:1.4.1.RELEASE] 
at org.springframework.boot.SpringApplication.run(SpringApplication.java:316) [spring-boot-1.4.1.RELEASE.jar:1.4.1.RELEASE] 
at org.springframework.boot.SpringApplication.run(SpringApplication.java:1186) [spring-boot-1.4.1.RELEASE.jar:1.4.1.RELEASE] 
at org.springframework.boot.SpringApplication.run(SpringApplication.java:1175) [spring-boot-1.4.1.RELEASE.jar:1.4.1.RELEASE] 
at hello.Application.main(Application.java:10) [classes/:na] 
Caused by: java.lang.IllegalArgumentException: Resource must not be null 
at org.springframework.util.Assert.notNull(Assert.java:115) ~[spring-core-4.3.3.RELEASE.jar:4.3.3.RELEASE] 
at org.springframework.transaction.support.TransactionSynchronizationUtils.unwrapResourceIfNecessary(TransactionSynchronizationUtils.java:62) ~[spring-tx-4.3.3.RELEASE.jar:4.3.3.RELEASE] 
at org.springframework.transaction.support.TransactionSynchronizationManager.getResource(TransactionSynchronizationManager.java:137) ~[spring-tx-4.3.3.RELEASE.jar:4.3.3.RELEASE] 
at org.springframework.jdbc.datasource.DataSourceTransactionManager.doGetTransaction(DataSourceTransactionManager.java:182) ~[spring-jdbc-4.3.3.RELEASE.jar:4.3.3.RELEASE] 
at org.springframework.transaction.support.AbstractPlatformTransactionManager.getTransaction(AbstractPlatformTransactionManager.java:337) ~[spring-tx-4.3.3.RELEASE.jar:4.3.3.RELEASE] 
at org.springframework.transaction.interceptor.TransactionAspectSupport.createTransactionIfNecessary(TransactionAspectSupport.java:430) ~[spring-tx-4.3.3.RELEASE.jar:4.3.3.RELEASE] 
at org.springframework.transaction.interceptor.TransactionAspectSupport.invokeWithinTransaction(TransactionAspectSupport.java:276) ~[spring-tx-4.3.3.RELEASE.jar:4.3.3.RELEASE] 
at org.springframework.transaction.interceptor.TransactionInterceptor.invoke(TransactionInterceptor.java:96) ~[spring-tx-4.3.3.RELEASE.jar:4.3.3.RELEASE] 
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:179) ~[spring-aop-4.3.3.RELEASE.jar:4.3.3.RELEASE] 
at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:213) ~[spring-aop-4.3.3.RELEASE.jar:4.3.3.RELEASE] 
at com.sun.proxy.$Proxy42.update(Unknown Source) ~[na:na] 
at org.springframework.batch.core.job.AbstractJob.execute(AbstractJob.java:357) ~[spring-batch-core-3.0.7.RELEASE.jar:3.0.7.RELEASE] 
at org.springframework.batch.core.launch.support.SimpleJobLauncher$1.run(SimpleJobLauncher.java:135) ~[spring-batch-core-3.0.7.RELEASE.jar:3.0.7.RELEASE] 
at org.springframework.core.task.SyncTaskExecutor.execute(SyncTaskExecutor.java:50) ~[spring-core-4.3.3.RELEASE.jar:4.3.3.RELEASE] 
at org.springframework.batch.core.launch.support.SimpleJobLauncher.run(SimpleJobLauncher.java:128) ~[spring-batch-core-3.0.7.RELEASE.jar:3.0.7.RELEASE] 
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) ~[na:1.8.0_102] 
at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source) ~[na:1.8.0_102] 
at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source) ~[na:1.8.0_102] 
at java.lang.reflect.Method.invoke(Unknown Source) ~[na:1.8.0_102] 
at org.springframework.aop.support.AopUtils.invokeJoinpointUsingReflection(AopUtils.java:333) ~[spring-aop-4.3.3.RELEASE.jar:4.3.3.RELEASE] 
at org.springframework.aop.framework.ReflectiveMethodInvocation.invokeJoinpoint(ReflectiveMethodInvocation.java:190) ~[spring-aop-4.3.3.RELEASE.jar:4.3.3.RELEASE] 
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:157) ~[spring-aop-4.3.3.RELEASE.jar:4.3.3.RELEASE] 
at org.springframework.batch.core.configuration.annotation.SimpleBatchConfiguration$PassthruAdvice.invoke(SimpleBatchConfiguration.java:127) ~[spring-batch-core-3.0.7.RELEASE.jar:3.0.7.RELEASE] 
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:179) ~[spring-aop-4.3.3.RELEASE.jar:4.3.3.RELEASE] 
at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:213) ~[spring-aop-4.3.3.RELEASE.jar:4.3.3.RELEASE] 
at com.sun.proxy.$Proxy47.run(Unknown Source) ~[na:na] 
at org.springframework.boot.autoconfigure.batch.JobLauncherCommandLineRunner.execute(JobLauncherCommandLineRunner.java:216) ~[spring-boot-autoconfigure-1.4.1.RELEASE.jar:1.4.1.RELEASE] 
at org.springframework.boot.autoconfigure.batch.JobLauncherCommandLineRunner.executeLocalJobs(JobLauncherCommandLineRunner.java:233) ~[spring-boot-autoconfigure-1.4.1.RELEASE.jar:1.4.1.RELEASE] 
at org.springframework.boot.autoconfigure.batch.JobLauncherCommandLineRunner.launchJobFromProperties(JobLauncherCommandLineRunner.java:125) ~[spring-boot-autoconfigure-1.4.1.RELEASE.jar:1.4.1.RELEASE] 
at org.springframework.boot.autoconfigure.batch.JobLauncherCommandLineRunner.run(JobLauncherCommandLineRunner.java:119) ~[spring-boot-autoconfigure-1.4.1.RELEASE.jar:1.4.1.RELEASE] 
at org.springframework.boot.SpringApplication.callRunner(SpringApplication.java:800) [spring-boot-1.4.1.RELEASE.jar:1.4.1.RELEASE] 

Das Problem ist, ich kann nicht herausfinden, welche Ressource null ist und wie man es löst.

Der Code für meine Charge ist unten;

@Configuration 
@EnableBatchProcessing 
public class BatchConfiguration { 

@Autowired 
public JobBuilderFactory jobBuilderFactory; 

@Autowired 
public StepBuilderFactory stepBuilderFactory; 

@Bean 
public JobRepository jobRepository(){  
    JobRepositoryFactoryBean jReposFact = new JobRepositoryFactoryBean(); 
    jReposFact.setDataSource(dataSource()); 
    jReposFact.setTransactionManager(new DataSourceTransactionManager()); 
    jReposFact.setIsolationLevelForCreate("ISOLATION_REPEATABLE_READ"); 

    JobRepository jRepos = null; 

    try{ 
     jRepos = jReposFact.getObject(); 
    }catch(Exception e){ 
     e.printStackTrace(); 
    } 

    return jRepos; 
} 

@Bean 
public DataSource dataSource(){ 
    return DataSourceBuilder.create() 
      .url("jdbc:oracle:thin:@localhost:1521:curamdb") 
      .driverClassName("oracle.jdbc.OracleDriver") 
      .username("springbatch") 
      .password("password") 
      .build();   
} 

@Bean 
public FlatFileItemReader<Person> reader() { 
    FlatFileItemReader<Person> reader = new FlatFileItemReader<Person>(); 
    reader.setResource(new ClassPathResource("sample-data.csv")); 
    reader.setLineMapper(new DefaultLineMapper<Person>() {{ 
     setLineTokenizer(new DelimitedLineTokenizer() {{ 
      setNames(new String[] { "firstName", "lastName" }); 
     }}); 
     setFieldSetMapper(new BeanWrapperFieldSetMapper<Person>() {{ 
      setTargetType(Person.class); 
     }}); 
    }}); 
    return reader; 
} 

@Bean 
public PersonItemProcessor processor() { 
    return new PersonItemProcessor(); 
} 

@Bean 
public JdbcBatchItemWriter<Person> writer() { 
    JdbcBatchItemWriter<Person> writer = new JdbcBatchItemWriter<Person>(); 
    writer.setItemSqlParameterSourceProvider(new BeanPropertyItemSqlParameterSourceProvider<Person>()); 
    writer.setSql("INSERT INTO people (first_name, last_name) VALUES (:firstName, :lastName)"); 
    writer.setDataSource(dataSource()); 
    return writer; 
} 

@Bean 
public Job importUserJob(JobCompletionNotificationListener listener) { 
    return jobBuilderFactory.get("importUserJob") 
      .incrementer(new RunIdIncrementer()) 
      .listener(listener) 
      .flow(step1()) 
      .end() 
      .build(); 
} 

@Bean 
public Step step1() { 
    return stepBuilderFactory.get("step1") 
      .<Person, Person> chunk(10) 
      .reader(reader()) 
      .processor(processor()) 
      .writer(writer()) 
      .build(); 
} 
} 

Ich habe einen Verdacht, könnte mit meiner JobRepository Definition zu tun, und vielleicht mit der Transaction aber bin nicht vertraut genug mit Spring Batch um herauszufinden, was das Problem ist.

Vielen Dank im Voraus!

Bic

Antwort

1

Ihre Datenquelle ist null, wenn der Job beginnt. (Überprüfen Sie den StackTrace für DataSourceTransactionManager.doGetTransaction -> diese Methode ruft TransactionSynchronizationManager.getResource mit einer Datenquelle als Parameter auf).

Ich kann nur raten, aber das Problem ist die Reihenfolge, in der sein könnte, die Bohnen

In Ihrer Konfiguration Klasse erstellt werden, können Sie auch die Datenquelle definieren. Es besteht jedoch die Möglichkeit, dass die Datenquelle nicht vollständig initialisiert wurde, wenn die gesamten "startenden Bohnen von Springbatch" erstellt werden.

Soweit ich verstanden habe, funktioniert der Code, wenn Sie die DataSource- und die JobRepository-Erstellung aus Ihrer Konfigurationsklasse entfernen. In diesem Fall wird springboot eine Standardinmemorydb-Datenquelle und ein entsprechendes Jobrepository bereitstellen. Ich würde vorschlagen, dass Sie diese zwei Einträge aus Ihrer Konfigurationsdatei entfernen und sehen, ob der Code funktioniert (ich erwarte es). Hinweis: Sie müssen "@Autowired DataSource dataSource" hinzufügen.

Als nächstes schreiben Sie Ihre eigene Konfigurationsklasse (mit '@Configuration' annotiert) und fügen Sie nur Ihre DataSource-Definition hinzu.

@Bean 
public DataSource dataSource(){ 
    return DataSourceBuilder.create() 
      .url("jdbc:oracle:thin:@localhost:1521:curamdb") 
      .driverClassName("oracle.jdbc.OracleDriver") 
      .username("springbatch") 
      .password("password") 
      .build();   
} 

Verwenden Sie die Anweisung "@Import", um diese Konfiguration zu Ihrer Klasse hinzuzufügen.

@Configuration 
@EnableBatchProcessing 
@Import(YourDataSourceConfiguration.class) 
public class BatchConfiguration { 
    @Autowired 
    private DataSource dataSource; 
    .... 
+0

Danke, das Teilen der Konfiguration in eine separate Datei hat den Trick für mich - danke! – bicster

Verwandte Themen