Announcement Announcement Module
Collapse
No announcement yet.
Passing Job Parameters to ItemWriter with Late Binding Page Title Module
Move Remove Collapse
X
Conversation Detail Module
Collapse
  • Filter
  • Time
  • Show
Clear All
new posts

  • Passing Job Parameters to ItemWriter with Late Binding

    I have recently started using spring-batch. I am trying to get the file name from Job Parameters that I can use for writer. So I am defining my bean definition for writer as scope="test".

    Code:
    	<bean id="itemWriter" class="org.springframework.batch.item.file.FlatFileItemWriter" scope="step">
    	    <property name="resource" value="#{jobParameters['OUTFILE']}" />
    	    <property name="lineAggregator">
    	        <bean class="org.springframework.batch.item.file.transform.DelimitedLineAggregator">
    	            <property name="delimiter" value=","/>
    	            <property name="fieldExtractor">
    	                <bean class="org.springframework.batch.item.file.transform.BeanWrapperFieldExtractor">
    	                    <property name="names" value="policyId,version,vehicleNumber,coverageGroup"/>
    	                </bean>
    	            </property>
    	        </bean>
    	    </property>
    	</bean>
    The code for launcher is
    Code:
    	public void testLaunchJob() throws Exception {
    		JobParameters jobParameters = new JobParametersBuilder().addString("owner","NAME").addDate("currentTime", new Date()).addString("OUTFILE", "file:target/test-outputs/output2.txt").toJobParameters();
    		sampleJobLauncher.run(job, jobParameters);
    	}
    I made these changes based on few threads in the spring-batch forum and chapter-5 of spring-batch documentation. But when I run the job, I get the following errors

    Code:
    Caused by: java.io.FileNotFoundException: class path resource [#{jobParameters['OUTFILE']}] cannot be resolved to URL because it does not exist
    	at org.springframework.core.io.ClassPathResource.getURL(ClassPathResource.java:162)
    	at org.springframework.core.io.AbstractFileResolvingResource.getFile(AbstractFileResolvingResource.java:47)
    	at org.springframework.batch.item.file.FlatFileItemWriter.getOutputState(FlatFileItemWriter.java:337)
    	... 55 more
    Any insights regarding this issue would be of great help.

    Thanks,
    Praveen

  • #2
    Hi, try to remove the apostrophes when referency the parameter

    value="#{jobParameters[OUTFILE]}"

    You can look the format in the docs

    Comment


    • #3
      I tried with and without quotes. But it yeilds same result. I am using Spring 3.0 and Spring batch 2.1.

      Comment


      • #4
        you need the quotes. How do you load your job?

        Comment


        • #5
          If I understand your question correctly, I am loading it using job launcher.

          Comment


          • #6
            I am loading the spring context/ jobs from Junit testcase. The following is the code which does that
            Code:
            @ContextConfiguration(locations={"/launch-context.xml"})
            @RunWith(SpringJUnit4ClassRunner.class)
            public class ExampleJobConfigurationTests {
            	..........

            launch-context.xml has the job launcher configuration and it also imports few other spring configuration files where batch repository and other job definitions are defined.

            Code:
            	<import resource="classpath:batchframework-context.xml" />
            	<import resource="classpath:FL-batchjobs-context.xml" />
                
                
            	<bean id="jobLauncher"
            		class="org.springframework.batch.core.launch.support.SimpleJobLauncher">
            		<property name="jobRepository" ref="batchJobRepository" />
            	</bean>

            Comment


            • #7
              From the exception, you can see ClassPathResource was used to load your file. As your file is not in the classpath, an exception was thrown.

              To solve the issue, you should define the resource and add parameter as follow.
              <property name="resource" value="file:#{jobParameters['OUTFILE']}" />

              addString("OUTFILE", "target/test-outputs/output2.txt")

              Comment


              • #8
                There is a "file:" prefix on the job parameter in the original post.

                We haven't seen the complete configuration yet, nor have we see the complete stack trace. There has to be something missing that is important.

                Comment


                • #9
                  Victor / Dave,
                  I am still having problems with job params. Actually snicoll had few suggestions regarding my problem. I think I am following documentation / samples for most part. But I guess there is something that is still missing. Just to recap, I am using Batch 2.1.1, Spring 3.0, Java 5.0, STS 2.3.1. To simply things, I created a Simple Batch Job(different from original post) from STS template. My Module context looks like this
                  Code:
                  <?xml version="1.0" encoding="UTF-8"?>
                  <beans xmlns="http://www.springframework.org/schema/beans"
                  	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:batch="http://www.springframework.org/schema/batch"
                  	xsi:schemaLocation="http://www.springframework.org/schema/batch http://www.springframework.org/schema/batch/spring-batch-2.1.xsd
                  		http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
                  
                  	<description>Example job to get you started. It provides a
                  		skeleton for a typical batch application.</description>
                  
                  	<job id="job1" xmlns="http://www.springframework.org/schema/batch">
                  		<step id="step1" parent="simpleStep">
                  			<tasklet>
                  				<chunk reader="reader" writer="writer"/>
                  			</tasklet>
                  		</step>
                  	</job>
                  	
                      <bean class="org.springframework.batch.core.scope.StepScope" />
                  	<bean id="reader" class="org.springframework.sample.batch.example.ExampleItemReader" scope="step">
                  	   <property name="secondInput" value="#{jobParameters['User']}"/>
                  	</bean>
                  	<bean id="writer" class="org.springframework.sample.batch.example.ExampleItemWriter" />
                  
                  	<bean id="simpleStep"
                  		class="org.springframework.batch.core.step.item.SimpleStepFactoryBean"
                  		abstract="true">
                  		<property name="transactionManager" ref="transactionManager" />
                  		<property name="jobRepository" ref="jobRepository" />
                  		<property name="startLimit" value="100" />
                  		<property name="commitInterval" value="1" />
                  	</bean>
                  
                  </beans>
                  As seen in config above reader needs to be passed a job variable for secondInput property.

                  The read method of Example ItemReader

                  Code:
                  	public String read() throws Exception {
                  
                  		System.out.println("Second Input :" + secondInput);
                                  ...
                  		
                  	}
                  My launch-context looks like this

                  Code:
                  <?xml version="1.0" encoding="UTF-8"?>
                  <beans xmlns="http://www.springframework.org/schema/beans"
                  	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:batch="http://www.springframework.org/schema/batch"
                  	xsi:schemaLocation="http://www.springframework.org/schema/batch http://www.springframework.org/schema/batch/spring-batch-2.1.xsd
                  		http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
                  
                  	<import resource="classpath:/META-INF/spring/module-context.xml" />
                  
                  	<bean id="jobLauncher"
                  		class="org.springframework.batch.core.launch.support.SimpleJobLauncher">
                  		<property name="jobRepository" ref="jobRepository" />
                  	</bean>
                  
                  	<batch:job-repository id="jobRepository" />
                  
                  	<bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource">
                  		<property name="driverClassName" value="${batch.jdbc.driver}" />
                  		<property name="url" value="${batch.jdbc.url}" />
                  		<property name="username" value="${batch.jdbc.user}" />
                  		<property name="password" value="${batch.jdbc.password}" />
                  	</bean>
                  
                  	<bean id="transactionManager"
                  		class="org.springframework.jdbc.datasource.DataSourceTransactionManager"
                  		lazy-init="true">
                  		<property name="dataSource" ref="dataSource" />
                  	</bean>
                  
                  	<bean id="placeholderProperties"
                  		class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
                  		<property name="location" value="classpath:batch.properties" />
                  		<property name="systemPropertiesModeName" value="SYSTEM_PROPERTIES_MODE_OVERRIDE" />
                  		<property name="ignoreUnresolvablePlaceholders" value="true" />
                  		<property name="order" value="1" />
                  	</bean>
                  
                  </beans>
                  My Test Class for testing launcher is

                  Code:
                  @ContextConfiguration(locations={"/launch-context.xml"})
                  @RunWith(SpringJUnit4ClassRunner.class)
                  public class ExampleJobConfigurationTests {
                  	@Autowired
                  	JobLauncher jobLauncher;
                  	@Autowired
                  	Job job;
                  	@Test
                  	public void testLaunchJob() throws Exception {
                  		JobParametersBuilder jpBuilder = new JobParametersBuilder();
                  		jpBuilder.addDate("currentTime", new Date());
                  		jpBuilder.addString("User", "Sample");
                  		jobLauncher.run(job, jpBuilder.toJobParameters());
                  	}
                  }
                  I see the stack trace as follows (part of it)

                  Code:
                  ...
                  2010-04-28 17:11:12,327 DEBUG [org.springframework.batch.core.step.AbstractStep] - <Executing: id=28>
                  2010-04-28 17:11:12,405 DEBUG [org.springframework.batch.repeat.support.RepeatTemplate] - <Starting repeat context.>
                  2010-04-28 17:11:12,405 DEBUG [org.springframework.batch.repeat.support.RepeatTemplate] - <Repeat operation about to start at count=1>
                  2010-04-28 17:11:12,405 DEBUG [org.springframework.batch.core.scope.context.StepContextRepeatCallback] - <Preparing chunk execution for StepContext: org.springframework.batch.core.scope.context.StepContext@1e67e6a>
                  2010-04-28 17:11:12,405 DEBUG [org.springframework.batch.core.scope.context.StepContextRepeatCallback] - <Chunk execution starting: queue size=0>
                  2010-04-28 17:11:12,405 DEBUG [org.springframework.batch.repeat.support.RepeatTemplate] - <Starting repeat context.>
                  2010-04-28 17:11:12,405 DEBUG [org.springframework.batch.repeat.support.RepeatTemplate] - <Repeat operation about to start at count=1>
                  2010-04-28 17:11:12,405 DEBUG [org.springframework.batch.core.scope.StepScope] - <Creating object in scope=step, name=scopedTarget.scopedTarget.reader>
                  Second Input :#{jobParameters['User']}
                  2010-04-28 17:11:12,405 DEBUG [org.springframework.batch.repeat.support.RepeatTemplate] - <Repeat is complete according to policy and result value.>
                  ######[Hello World!#{jobParameters['User']}]-null
                  ...
                  Even though I have not been spending all my time on this, I have had this issue for sometime. Any help to fix my problem would be helpful. I am sure I am overseeing something little detail.

                  Thanks

                  Comment


                  • #10
                    Hi praveens,
                    I did a test and it does work fine. I just added the follow code and modified the config.

                    private String secondInput;

                    public String getSecondInput() {
                    return secondInput;
                    }
                    public void setSecondInput(String secondInput) {
                    this.secondInput = secondInput;
                    }

                    <bean id="reader" class="org.springframework.sample.batch.example.Ex ampleItemReader" scope="step">
                    <property name="secondInput" value="#{jobParameters['User']}" />
                    </bean>

                    JobParametersBuilder jpBuilder
                    = new JobParametersBuilder()
                    .addString("User", "--->This is a test of Victor");
                    launcher.run(job, jpBuilder.toJobParameters());

                    In the log, I found:
                    06:34:58.540[DEBUG] [main] [e.util.PlaceholderTargetSource( 328)]-Resolved %{jobParameters['User']} to obtain [--->This is a test of Victor]

                    As you didn't give out your source code, I just guess your code has something wrong.
                    Last edited by victor_jan; Apr 29th, 2010, 06:39 PM.

                    Comment


                    • #11
                      From the currently posted content, there is no 'file:' and the exception is 'Caused by: java.io.FileNotFoundException: class path resource ', that is why I thought the problem was caused by it.

                      Comment


                      • #12
                        Victor,
                        I already have get/set methods for secondInput. I am enclosing my project. Let me know if you find something odd in the code.


                        Thanks,
                        Praveen

                        Comment


                        • #13
                          You have a mixture of Spring 2.5.6 and Spring 3.0 in there. If you add an explicit dependency on spring-context and spring-aop I think it will work. (The sample project is fixed in trunk by the way, it just didn't make it to STS yet.)

                          Comment


                          • #14
                            Dave,
                            It worked after adding explicit dependency. I did not pay attention to the indirect dependency. I just checked spring-core and spring-beans versions and thought everything was OK. I was looking more at job initialization and job config files. Thanks for pointing out. I can move forward now.

                            Thanks

                            Comment


                            • #15
                              Dave,
                              Is there any examples for using late-binding, especially for files. Maybe I missed something, but I didn't find a real helpful example. I also spent a lot of time to make it work for me.

                              Comment

                              Working...
                              X