How to change the TaskExecutor implementation dynamically depending on the application server
I am using Spring 3.0.x to get a WorkManager from an application server and use it to run scheduled jobs that need database access. The problem is, is that this application could be deployed to different Java application servers - in this case, to Websphere 7.0 and GlassFish 3.1 OSE. (Crazy combo, I know...开发者_运维知识库)
The problem I am having is that before deploying to either, I have to change the bean to reference the appropriate TaskExecutor class used for each server. I have Spring load up an applicationContext.xml with these beans in it.
For Websphere, I have to pull the WorkManager externally and use the following bean:
<bean id="myTaskExecutor" class="org.springframework.scheduling.commonj.WorkManagerTaskExecutor">
<property name="workManagerName" value="wm/default" />
<property name="resourceRef" value="true"/>
</bean>
and the web.xml has something like this:
<resource-ref>
<description>WorkManager</description>
<res-ref-name>wm/default</res-ref-name>
<res-type>commonj.work.WorkManager</res-type>
<res-auth>Container</res-auth>
<res-sharing-scope>Shareable</res-sharing-scope>
</resource-ref>
For GlassFish, I can just use the bean:
<bean id="myTaskExecutor" class="org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor">
</bean>
Can I somehow dynamically change which TaskExecutor implementation is used on the fly?
I could easily check for the Websphere resource to determine if I am on Websphere, then fall back to GlassFish. But how to load a class like that with Spring (using Annotations or otherwise) is baffling me.
Any help is appreciated. Thanks!
P.S. I am not worried about being J2EE compliant for GlassFish - it's just that Websphere forces you to be so (hence pulling an external WorkManager)
You can easily use a custom VM argument to determine what environment you are running in, and use that to load the appropriate context file.
One file for each supported environment, all of which define the same bean.
task-exec-was.xml
task-exec-glassfish.xml
Add a required VM argument.
-Dapp.server=was
Then, wherever you actually load the bean you include the appropriate file based on a PropertyPlaceholderConfigurer.
<bean class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer" />
<import resource="task-exec-${app.server}.xml" />
Edits based on information in the comments.
You can override for the environment you do have control over in this case.
<bean class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
<property name="systemPropertiesModeName" value="SYSTEM_PROPERTIES_MODE_OVERRIDE"/>
<property name="location" value="classpath:spring/was.properties/>
</bean>
<import resource="task-exec-${app.server}.xml" />
Now you have a file called spring/was.properties that defines a property app.server=was, which is read by default. In Glassfish, you supply the same property as a VM argument, which will now override the property read from the file.
精彩评论