spring-bootapache-camelquartz-scheduler

How to dynamically set jobstore dataSource in quartz.properties file


I'm using the Quartz component from Apache Camel to run some scheduled routes. I would like to configure the JDBC JobStore for the scheduler, and was able to set the necessary properties in a quartz.properties file, as shown below.

org.quartz.jobStore.useProperties = true
org.quartz.jobStore.dataSource=myDataSource
org.quartz.jobStore.tablePrefix = II_QRTZ_

org.quartz.dataSource.myDataSource.driver = com.ibm.db2.jcc.DB2Driver
org.quartz.dataSource.myDataSource.URL = url
org.quartz.dataSource.myDataSource.user = example-user
org.quartz.dataSource.myDataSource.password = example-pwd

However, we need to set different data sources/credentials based on different server environments (dev vs test vs prod). I can't seem to find a way to dynamically set the data source from the properties file.

We already had a datasource bean that would connect to the correct database based on the environment, and so I tried referencing to that after annotating it with the @QuartzDataSource annotation. Ideally this would have been the cleanest solution. For example,

DataSourceConfig.java

    @Bean(name="myDataSource")
    @QuartzDataSource
    @ConfigurationProperties(prefix="org.quartz.mydatasource")
    @Autowired
    public DataSource myDataSource(@Qualifier("applicationProps") BasePropReader applicationProperties) {
        String connectionString = (String) applicationProperties.get("spring.datasource.connection.url");
        return buildDataSource(applicationProperties, "example-user", "example-pwd", "com.ibm.db2.jcc.DB2Driver", connectionString);
    }

/////////////////////////

quartz.properties

org.quartz.jobStore.useProperties = true
org.quartz.jobStore.dataSource=myDataSource
org.quartz.jobStore.tablePrefix = II_QRTZ_

In our web applications we did something similar as the above, where in the quartz properties file we could refer to data sources that were already configured by environment by a JNDI url. For example:

org.quartz.jobStore.useProperties = true
org.quartz.jobStore.dataSource=myDataSource
org.quartz.jobStore.tablePrefix = II_QRTZ_

org.quartz.dataSource.myDataSource.jndiURL=java:/MYDATASOURCE

We also tried setting the properties from application.properties but that didn't work - I suspect because we're using the Quartz component from Camel.

I've tried reading up on reading environment variables from the properties file itself (via this thread), but all the variables I read end up as empty strings.

Is this even possible via Apache Camel's Quartz? Ideally we would like to continue using Camel as it saves us a lot of refactoring.

EDIT: I'm also trying to configure the quartz component by defining it as a bean in the context xml file and then passing a quartz property file based on the environment/spring active profile, but the quartz component doesn't seem to be picking up on that either. for example:

    <bean id="quartz" class="org.apache.camel.component.quartz.QuartzComponent">
        <property name="propertiesFile" value="org/quartz/quartz-dev.properties"/>
    </bean>

Solution

  • I ended up creating a QuartzConfig.java file. From there I created the quartz bean I loaded the easily configurable properties with my existing properties file, and then sourced the environment/secret properties from code. It went something like this

        @Bean("quartz")
        public QuartzComponent quartzComponent() {
            QuartzComponent quartzComponent = new QuartzComponent();
            Properties quartzPropertiesObj = quartzProperties.getProperties();
            String env = "dev"; // however you get your environment
    
            // applicationProperties was an instance of our class that allowed us to get our secrets by environment
            quartzPropertiesObj.setProperty("org.quartz.dataSource.dataSourceDB2.URL", applicationProperties.get("spring.datasource.connection.url").toString());
            quartzPropertiesObj.setProperty("org.quartz.dataSource.dataSourceDB2.user", applicationProperties.get("user" + env).toString());
            quartzPropertiesObj.setProperty("org.quartz.dataSource.dataSourceDB2.password", applicationProperties.get("pwd" + env).toString());
            quartzComponent.setProperties(quartzPropertiesObj);
            LOG.info("Quartz Config: Quartz properties file loaded into quartz component.");
            return quartzComponent;
        }