Announcement Announcement Module
Collapse
No announcement yet.
Configured Job works Programmatic Job doesn't Page Title Module
Move Remove Collapse
X
Conversation Detail Module
Collapse
  • Filter
  • Time
  • Show
Clear All
new posts

  • Configured Job works Programmatic Job doesn't

    Hi,
    When I configure a job and a Tasklet in the spring context and run it in a test it runs fine. But when I build a Job and Tasklet programmatically, I get a NullPointerException in TransactionTemplate.execute.

    Here is the relevant code:

    First the tests:

    This works:
    Code:
    	@Test
    	public void testConfiguredJob() throws Exception {
    		JobParameters parameters = new JobParametersBuilder(jobLauncherTestUtils.getUniqueJobParameters()).toJobParameters();
    		jobLauncherTestUtils.setJob(configuredJob);
    		JobExecution jobExecution = jobLauncherTestUtils.launchJob(parameters);
    		assertEquals(BatchStatus.COMPLETED, jobExecution.getStatus());
    	}
    This does not:
    Code:
    	@Test
    	public void testProgrammaticJob() throws Exception {
    		JobParameters parameters = new JobParametersBuilder(jobLauncherTestUtils.getUniqueJobParameters()).toJobParameters();
    		TaskletStep taskletStep = new TaskletStep(); 
    		taskletStep.setName("step1");
    		taskletStep.setJobRepository(jobRepository);
    		Tasklet tasklet = new MyTasklet();
    		taskletStep.setTasklet(tasklet);
    		SimpleJob programmaticJob = new SimpleJob("test");
    		programmaticJob.addStep(taskletStep); 
    		programmaticJob.setJobRepository(jobRepository);
    		jobLauncherTestUtils.setJob(programmaticJob);
    		JobExecution jobExecution = jobLauncherTestUtils.launchJob(parameters);
    		assertEquals(BatchStatus.COMPLETED, jobExecution.getStatus());
    	}
    The job* beans are configured so:

    Code:
    	<job id="configuredJob" xmlns="http://www.springframework.org/schema/batch">
    		<step id="myJob.step1">
    			<tasklet ref="myTasklet" />
    		</step>		
    	</job>
    	
    	<bean id="myTasklet" class = "com.xxx.adc.si.MyTasklet" />
    	
    	<bean id="jobLauncher"
    		class="org.springframework.batch.core.launch.support.SimpleJobLauncher">
    		<property name="jobRepository" ref="jobRepository" />
    	</bean>
    
    	<bean class="org.springframework.batch.core.configuration.support.JobRegistryBeanPostProcessor">
    		<property name="jobRegistry" ref="jobRegistry"/>
    	</bean>
    
    	<bean id="jobRepository"
    		class="org.springframework.batch.core.repository.support.JobRepositoryFactoryBean"
    		p:dataSource-ref="dataSource" p:transactionManager-ref="transactionManager" p:lobHandler-ref="lobHandler"/>
    
    	<bean id="mapJobRepository"
    		class="org.springframework.batch.core.repository.support.MapJobRepositoryFactoryBean"
    		lazy-init="true" autowire-candidate="false" />
    
    	<bean id="jobOperator"
    		class="org.springframework.batch.core.launch.support.SimpleJobOperator"
    		p:jobLauncher-ref="jobLauncher" p:jobExplorer-ref="jobExplorer"
    		p:jobRepository-ref="jobRepository" p:jobRegistry-ref="jobRegistry" />
    
    	<bean id="jobExplorer"
    		class="org.springframework.batch.core.explore.support.JobExplorerFactoryBean"
    		p:dataSource-ref="dataSource" />
    
    	<bean id="jobRegistry"
    		class="org.springframework.batch.core.configuration.support.MapJobRegistry" />
    
    	<bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate">
    		<property name="dataSource" ref="dataSource" />
    	</bean>

    MyTasklet is stubbed out for now with a simple message for testing:
    Code:
       public RepeatStatus execute(StepContribution contribution, 
                                    ChunkContext chunkContext) throws Exception {
        	System.out.println("In tasklet!");   	
            return RepeatStatus.FINISHED;
       }
    The exception I get when I run testProgrammaticJob is:

    Code:
    	2011-07-19 15:08:10,557 [main] DEBUG org.springframework.batch.core.job.AbstractJob  #### Job execution complete: JobExecution: id=0, version=1, startTime=Tue Jul 19 15:08:10 EDT 2011, endTime=null, lastUpdated=Tue Jul 19 15:08:10 EDT 2011, status=FAILED, exitStatus=exitCode=FAILED;exitDescription=java.lang.NullPointerException
    		at org.springframework.transaction.support.TransactionTemplate.execute(TransactionTemplate.java:127)
    		at org.springframework.batch.core.step.tasklet.TaskletStep$2.doInChunkContext(TaskletStep.java:264)
    		at org.springframework.batch.core.scope.context.StepContextRepeatCallback.doInIteration(StepContextRepeatCallback.java:76)
    		at org.springframework.batch.repeat.support.RepeatTemplate.getNextResult(RepeatTemplate.java:367)
    		at org.springframework.batch.repeat.support.RepeatTemplate.executeInternal(RepeatTemplate.java:214)
    		at org.springframework.batch.repeat.support.RepeatTemplate.iterate(RepeatTemplate.java:143)
    		at org.springframework.batch.core.step.tasklet.TaskletStep.doExecute(TaskletStep.java:250)
    		at org.springframework.batch.core.step.AbstractStep.execute(AbstractStep.java:195)
    		at org.springframework.batch.core.job.SimpleStepHandler.handleStep(SimpleStepHandler.java:135)
    		at org.springframework.batch.core.job.AbstractJob.handleStep(AbstractJob.java:356)
    		at org.springframework.batch.core.job.SimpleJob.doExecute(SimpleJob.java:121)
    		at org.springframework.batch.core.job.AbstractJob.execute(AbstractJob.java:281)
    		at org.springframework.batch.core.launch.support.SimpleJobLauncher$1.run(SimpleJobLauncher.java:120)
    		at org.springframework.core.task.SyncTaskExecutor.execute(SyncTaskExecutor.java:48)
    		at org.springframework.batch.core.launch.support.SimpleJobLauncher.run(SimpleJobLauncher.java:114)
    		at org.springframework.batch.test.JobLauncherTestUtils.launchJob(JobLauncherTestUtils.java:151)
    		at com.xxx.adc.si.test.BatchTests.testProgramaticJob(BatchTests.java:121)
    		at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    		at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
    		at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
    		at java.lang.reflect.Method.invoke(Method.java:597)
    		at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:44)
    		at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:15)
    		at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:41)
    		at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:20)
    		at org.springframework.test.context.junit4.statements.RunBeforeTestMethodCallbacks.evaluate(RunBeforeTestMethodCallbacks.java:74)
    		at org.springframework.test.context.junit4.statements.RunAfterTestMethodCallbacks.evaluate(RunAfterTestMethodCallbacks.java:82)
    		at org.springframework.test.context.junit4.statements.SpringRepeat.evaluate(SpringRepeat.java:72)
    		at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.runChild(SpringJUnit4ClassRunner.java:240)
    		at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:50)
    		at org.junit.runners.ParentRunner$3.run(ParentRunner.java:193)
    		at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:52)
    		at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:191)
    		at org.junit.runners.ParentRunner.access$000(ParentRunner.java:42)
    		at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:184)
    		at org.springframework.test.context.junit4.statements.RunBeforeTestClassCallbacks.evaluate(RunBeforeTestClassCallbacks.java:61)
    		at org.springframework.test.context.junit4.statements.RunAfterTestClassCallbacks.evaluate(RunAfterTestClassCallbacks.java:70)
    		at org.junit.runners.ParentRunner.run(ParentRunner.java:236)
    		at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.run(SpringJUnit4ClassRunner.java:180)
    		at org.eclipse.jdt.internal.junit4.runner.JUnit4TestReference.run(JUnit4TestReference.java:46)
    		at org.eclipse.jdt.internal.junit.runner.TestExecution.run(TestExecution.java:38)
    		at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:467)
    		at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:683)
    		at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.run(RemoteTestRunner.java:390)
    		at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.main(RemoteTestRunner.java:197)
    , job=[JobInstance: id=0, version=0, JobParameters=[{timestamp=1311102490432}], Job=[test]]
    When I remove the explicit setting of the jobRepository on the job and step, I get a
    Code:
    java.lang.NullPointerException
    	at org.springframework.batch.core.job.AbstractJob.execute(AbstractJob.java:329)
    ...

    Can anyone suggest what's the correct way to code a Job programatically. Eventually I will want to run it using jobLauncher.run(job, params) instead of the jobLauncherTestUtils.launchJobs(...) api.



    Thanks!

  • #2
    Configured Job works Programmatic Job doesn't

    Hi,
    I've looked everywhere but I cannot find a way to CREATE (not run) a job programmatically.

    It would seem that SimpleJob job = new SimpleJob() would do the trick.

    But there's some magic going on when a job is created via the namespace that is more than just that simple line.
    There are several objects that are injected into that job before the app context gives it to me via a context.getBean("myJob") call (or injected via @Resource in my Test class)

    When I create a job using the plain ctor and even assign a jobRepository to it, I get a NullPointerException in the TransactionTemplate that suggests that a transactionManager is not available to it.

    Can someone please speak up and suggest how to create a job programmatically?

    Or suggest a way to inspect the classes that read the namespace to produce the fully configured bean?

    I'm losing the optimistic approach that I felt about Spring Batch in the beginning.. and judging from the responses (or lack thereof) on this forum I'm really wondering if this ready for showtime yet.

    Comment


    • #3
      Configured Job works Programmatic Job doesn't

      Ok, I got it. A transactionManager needed to be set.

      Code:
      	@Test
      	public void testProgramaticJob() throws Exception {
      	
      		JobParameters parameters = new JobParametersBuilder(jobLauncherTestUtils.getUniqueJobParameters()).toJobParameters();
      		
      		TaskletStep taskletStep = new TaskletStep(); 
      		taskletStep.setName("step1");
      		taskletStep.setJobRepository(jobRepository);
      		taskletStep.setTransactionManager(transactionManager);
      		Tasklet tasklet = new SplitFilesTasklet();
      		taskletStep.setTasklet(tasklet);
      		
      		SimpleJob job = new SimpleJob("test");
      		job.addStep(taskletStep); 
      		job.setJobRepository(jobRepository);
      
      		jobLauncherTestUtils.setJob(job);
      		JobExecution jobExecution = jobLauncherTestUtils.launchJob(parameters);
      		assertEquals(BatchStatus.COMPLETED, jobExecution.getStatus());
      	}
      Hope this helps someone.

      Comment

      Working...
      X