7
votes

When using Spring Batch Admin, it tries to provide some defaults for dataSource, transactionManager etc.

If you want to override these defaults, you create your own xml bean definitions under META-INF/spring/batch/servlet/override/ folder and during the bootstrap it guarantees that the default properties will be overridden.

In spring-batch-admin, a dataSource default is defined in data-source-context.xml with this definition

<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}" />
    <property name="testWhileIdle" value="${batch.jdbc.testWhileIdle}"/>
    <property name="validationQuery" value="${batch.jdbc.validationQuery}"/>
</bean>

Now, I want to override this dataSource with a JNDI datasource so I removed the property lines like batch.jdbc.driver, batch.jdbc.url and have the following jndi definition

<bean id="dataSource" class="org.springframework.jndi.JndiObjectFactoryBean">
     <property name="jndiName" value="java:comp/env/jdbc/dbconn" />
</bean> 

As you may easily guess the system first tries to initialize the dataSource bean defined in data-source-context.xml and since it cannot find any values for property values batch.jdbc.* it fails with an exception.

Could not resolve placeholder 'batch.jdbc.driver' in string value [${batch.jdbc.driver}]

Since I will be using JNDI and do not want to deal with these property values, I cannot proceed.

Any idea on how to override dataSource in this situation?

2
Hi- did you find a solution? (I don't want to use profiles just for this issue.)dsatish
@sdny No. Also trying to use a solution without profiles.Serkan Arıkuşu
I've run across the same issue. Even by setting up a working "default" connection using the required properties, I was not able to get the override dataSource to be used.Eric
You need to put your custom data-source-context.xml under META-INF/spring/batch/override/ instead of META-INF/spring/batch/servlet/override/Integrating Stuff

2 Answers

6
votes

Within Spring Batch Admin, there are 2 Spring ApplicationContexts that are being loaded:

  • servlet-config.xml
  • webapp-config.xml

servlet-config.xml has these imports:

<import resource="classpath*:/META-INF/spring/batch/servlet/resources/*.xml" />
<import resource="classpath*:/META-INF/spring/batch/servlet/manager/*.xml" />
<import resource="classpath*:/META-INF/spring/batch/servlet/override/*.xml" />

webapp-config.xml has these imports:

<import resource="classpath*:/META-INF/spring/batch/bootstrap/**/*.xml" />
<import resource="classpath*:/META-INF/spring/batch/override/**/*.xml" />

servlet-config.xml configurers the servlet, webapp-config.xml configures (the backend part of the) the application. The problem is that the dataSource bean is part of/defined in the second config, not the first. Hence, when you add the dataSource bean to an override for the servlet config(/META-INF/spring/batch/servlet/override/*.xml), as you are doing, you add a new bean to the first context, instead of overwriting the dataSource bean of the second context.

So, you need to put your custom data-source-context.xml under META-INF/spring/batch/override/ instead of META-INF/spring/batch/servlet/override/

Then it works and you won't even get the Could not resolve placeholder 'batch.jdbc.driver' in string value [${batch.jdbc.driver}] error.

3
votes

since Spring 3.1 there's the 'profiles' feature which allows you to set your datasource 'source' based on the environment you're in. (an embedded one for local testing, a JNDI one for deployment.)

this would look something like the following;

<?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:jee="http://www.springframework.org/schema/jee"
    xmlns:jdbc="http://www.springframework.org/schema/jdbc"
    xsi:schemaLocation="http://www.springframework.org/schema/jdbc http://www.springframework.org/schema/jdbc/spring-jdbc-3.2.xsd
        http://www.springframework.org/schema/jee http://www.springframework.org/schema/jee/spring-jee-3.2.xsd
        http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">

    <!-- "production" datasource -->
    <jee:jndi-lookup id="dataSource" jndi-name="java:comp/env/jdbc/dbconn"/>

    <!-- profile for "local" testing -->
    <beans profile="local">
            <!-- datasource that only gets created in that active profile -->
        <jdbc:embedded-database id="dataSource" type="H2"/>
    </beans>


</beans>

in this example, when the 'active profile' is set to "local", it overwrites the jndi-lookup datasource.