Results 1 to 7 of 7

Thread: FlatFileHeaderCallback

  1. #1

    Default FlatFileHeaderCallback

    Hi all,

    I've a callback class for printing header on file:
    Code:
    public class HeaderCallback implements FlatFileHeaderCallback{
    
    	private String header = null;
    		
    	public void writeHeader(Writer writer) throws IOException {
    		if( header != null &&  (! header.isEmpty()) )
    			writer.write(header);
    	}
    
    	public void setHeader(String header) {
    		this.header = header;
    	}
    
    	public String getHeader() {
    		return header;
    	}
    
    }
    The private property is the header line I want to print (specified in an external job properties file used in the xml file: ${header.line} ) .

    The problem is that a "line.separator" is always generated when registering a FlatFileHeaderCallback onto corresponding FlatFileItemWriter.

    The only way for not printing "line.separator" is letting inject a null object in headerCallback property of FlatFileItemWriter. But I get a NullPointerException during context start up phase.

    I just need something like:

    Code:
    <bean id="csvWriter" class="org....FlatFileItemWriter">
    	....some other stuff.....	
        <property name="headerCallback" >
    	<bean factory-bean="headerFactory" >
        </bean>
    </property>
    		
    </bean>
    where headerFactory returns null if no ${header.line} is specified in properties file.

    How can I allow Spring to inject null object into bean properties?
    Otherwise, how can I provide a kind of conditional injection?

    Thanks,
    Luigi

  2. #2
    Join Date
    Jun 2005
    Posts
    4,230

    Default

    I didn't really understand the question yet. You want a header callback, but you don't want to emit the line separator between the header and the main fail, or you don't want to emit the line separator at all ever? I don't think there are any restrictions on the value of the line separator, so I assume you want the former? If so it sounds a bit strange - it doesn't really fit the definition of a header. But I didn't understand the bit about "conditional injection" so I'm probably missing something. There is nothing to stop you injecting null into a bean definition, but I don't understand why you want to do that.

  3. #3

    Default

    Thank you for reply! Well I try to explain better.

    I would configure my header line from a properties file without add and remove the header callback property in the FlatFileItemWriter of my XML configuration.

    header.line=MY CUSTOM HEADER LINE

    I would have no header line in case of empty property ( header.line= ). I don't want a blank line with the carriage return to be printed on top.

    Below the snippet of FlatFileItemWriter where checking headerCallback. So I would header callback to be null on demand (with a FactoryBean). But Spring gives me NullPointerException when trying to inject a null FlatFileHeaderCallback
    Code:
    if (headerCallback != null) {	
    try { 
        headerCallback.writeHeader(outputState.outputBufferedWriter);
        outputState.write(lineSeparator);
    }
    I hope is more clear

    thanks again

  4. #4
    Join Date
    Jun 2005
    Posts
    4,230

    Default

    I'm not sure why you wouldn't be able to inject null. If that's the issue how are you doing it and what is the error?

  5. #5

    Default

    Well that's all:

    Code:
    <property name="headerCallback"> //Property of FlatFileItemWriter
        <bean class="com.primeur.listener.HeaderCallback" 
             factory-method="createHeaderCallback">
                   <constructor-arg value=""></constructor-arg>
       </bean>
    </property>
    where createHeaderCallback is a static method that returns null in case of empty parameter or a new HeaderCallback otherwise.

    This is the stacktrace:

    Code:
    org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'lazyBindingProxy.csvWriter#sysinit' defined in class path resource [job-datatimerec-diff.xml]: Initialization of bean failed; nested exception is java.lang.NullPointerException
    	at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:480)
    	at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory$1.run(AbstractAutowireCapableBeanFactory.java:409)
    	at java.security.AccessController.doPrivileged(Native Method)
    	at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:380)
    	at org.springframework.beans.factory.support.AbstractBeanFactory$2.getObject(AbstractBeanFactory.java:302)
    	at org.springframework.batch.core.scope.StepScope.get(StepScope.java:150)
    	at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:298)
    	at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:185)
    	at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:164)
    	at org.springframework.batch.core.scope.util.PlaceholderTargetSource.getTarget(PlaceholderTargetSource.java:185)
    	at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:184)
    	at $Proxy17.open(Unknown Source)
    	at org.springframework.batch.item.support.CompositeItemStream.open(CompositeItemStream.java:98)
    	at org.springframework.batch.core.step.tasklet.TaskletStep.open(TaskletStep.java:288)
    	at org.springframework.batch.core.step.AbstractStep.execute(AbstractStep.java:193)
    	at org.springframework.batch.core.job.SimpleStepHandler.handleStep(SimpleStepHandler.java:135)
    	at org.springframework.batch.core.job.flow.JobFlowExecutor.executeStep(JobFlowExecutor.java:61)
    	at org.springframework.batch.core.job.flow.support.state.StepState.handle(StepState.java:60)
    	at org.springframework.batch.core.job.flow.support.SimpleFlow.resume(SimpleFlow.java:144)
    	at org.springframework.batch.core.job.flow.support.SimpleFlow.start(SimpleFlow.java:124)
    	at org.springframework.batch.core.job.flow.FlowJob.doExecute(FlowJob.java:135)
    	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 java.lang.Thread.run(Thread.java:619)
    Caused by: java.lang.NullPointerException
    	at org.springframework.batch.core.scope.util.PlaceholderTargetSource$1.convertIfNecessary(PlaceholderTargetSource.java:148)
    	at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.convertForProperty(AbstractAutowireCapableBeanFactory.java:1294)
    	at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.applyPropertyValues(AbstractAutowireCapableBeanFactory.java:1250)
    	at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.populateBean(AbstractAutowireCapableBeanFactory.java:1010)
    	at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:472)
    	... 23 more
    Last edited by luigi.toziani; Mar 8th, 2011 at 10:19 AM. Reason: Forgot stacktrace

  6. #6
    Join Date
    Jun 2005
    Posts
    4,230

    Default

    Interesting. Looks like a corner case bug in Spring Batch PlaceholderTargetSource. This component isn't used if you use Spring 3, so you could try that (and raise a ticket in JIRA), or if you could remove the scope="step" from the enclosing bean definition that would work too.

  7. #7

    Default

    Well, thanks.

    Anyway I tried removing scope step from writer but nothing happened. I will try to use Spring 3.0. (Actually using 2.5.6)

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •