Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Spring batch Source directory [target/config] does not exist

I have a spring batch application which has the property file batch-default.properties set up as

batch.job.configuration.file.dir=target/config

Now this application works well on my local machine even though i do not have any such directory but when i try to deploy the same on my integration server i am getting the error:

Cannot resolve reference to bean 'org.springframework.integration.config.SourcePollingChannelAdapterFactoryBean#0.source' while setting bean property 'source'; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'org.springframework.integration.config.SourcePollingChannelAdapterFactoryBean#0.source': FactoryBean threw exception on object creation; nested exception is java.lang.IllegalArgumentException: Source directory [target/config] does not exist.
    at org.springframework.beans.factory.support.BeanDefinitionValueResolver.resolveReference(BeanDefinitionValueResolver.java:334)
    at org.springframework.beans.factory.support.BeanDefinitionValueResolver.resolveValueIfNecessary(BeanDefinitionValueResolver.java:108)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.applyPropertyValues(AbstractAutowireCapableBeanFactory.java:1417)

Has anyone faced any similar problem?

Any help appriciated here.

-Vaibhav

like image 390
vaibhav Avatar asked Feb 03 '15 06:02

vaibhav


1 Answers

We had a similar issue on our test server. Looks like a problem with file permissions, i.e. Spring Batch Admin tries to create a directory structure for "target/config", but the user is not allowed to create the directories.

This is the chain causing the problem:

META-INF/spring/batch/bootstrap/integration/configuration-context.xml contains the definition of a file poller refering to the property:

<file:inbound-channel-adapter directory="${batch.job.configuration.file.dir}" channel="job-configuration-files"
        filename-pattern=".*\.xml">
        <poller max-messages-per-poll="1" cron="5/1 * * * * *" />
    </file:inbound-channel-adapter>

Checking the documentation of the inbound-channel-adapter reveals the following (spring-integration-file-2.1.xsd):

 <xsd:attribute name="directory" type="xsd:string" use="required">
                <xsd:annotation>
                    <xsd:documentation><![CDATA[Specifies the input directory (The directory to poll from) e.g.:
                    directory="file:/absolute/input" or directory="file:relative/input"]]></xsd:documentation>
                </xsd:annotation>            
            </xsd:attribute>

and (!)

 <xsd:attribute name="auto-create-directory" type="xsd:string" default="true">
                <xsd:annotation>
                    <xsd:documentation>
                        Specify whether to automatically create the source directory if it does not yet exist when this
                        adapter is being initialized. The default value is 'true'. If set to 'false' and the directory
                        does not exist upon initialization, an Exception will be thrown.
                    </xsd:documentation>
                </xsd:annotation>
            </xsd:attribute>

So, as an result, auto-create-directory is true and Spring is trying to create the (relative) directory structure somewhere on the shell path of your server.

For the error message, checking the java class org.springframework.integration.file.FileReadingMessageSource gives the explanation:

if (!this.directory.exists() && this.autoCreateDirectory) {
            this.directory.mkdirs();
        }
        Assert.isTrue(this.directory.exists(),
                "Source directory [" + directory + "] does not exist.");

The javadoc of java.io.File.mkdirs() says:

public boolean mkdirs()

Creates the directory named by this abstract pathname, including any necessary but nonexistent parent directories. Note that if this operation fails it may have succeeded in creating some of the necessary parent directories.

Returns:
    true if and only if the directory was created, along with all necessary parent directories; false otherwise

So what happens is, the mkdirs() returns "false" because he couldn't create the directory. The following exists() will also return "false" returning the error messsage as stated in the original post.

You can workaround be setting the parameter to an existing and writeable directory like "/tmp" using an absolute path. Unfortunately I have no idea how this spring batch feature should work, if you store your job definitions on a classpath; it would make more sense not to use a file poller but to use a "classpath-aware" file poller...

like image 60
Rainer Montag Avatar answered Sep 28 '22 01:09

Rainer Montag