Spring – Using jndi datasource with spring batch admin

springspring-batchspring-batch-admin

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?

Best Answer

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.

Related Topic