Search code examples
javaspringspring-integrationdatasourcehazelcast

How to create a Hazelcast DataSource


Hello everyone I am currently experimenting with using Hazelcast as a persistence layer with Spring Batch and to do this I need to create a DataSource that has Hazelcast backing it. This way projects like Spring Batch & Spring Data can use the Repository and TransactionManager provided by the Hazelcast + Spring Integration.

Does anyone know how to create a DataSource that points to Hazelcast?

I have tried defining a bean like so but to no avail it does not work:

@Configuration
public class DataSourceConfig {

//    @Value("${spring.datasource.url}")
//    String url;
//    @Value("${spring.datasource.username}")
//    String userName;
//    @Value("${spring.datasource.password}")
//    String pwd;

    @SneakyThrows
    @Bean
    public JobRepository hazelCastJobRepo(DataSource dataSource, HazelcastTransactionManager hazelcastTransactionManager){
        JobRepositoryFactoryBean jobRepositoryFactoryBean = new JobRepositoryFactoryBean();
        jobRepositoryFactoryBean.setDataSource(dataSource);
        jobRepositoryFactoryBean.setDatabaseType("POSTGRES");
        jobRepositoryFactoryBean.setTransactionManager(hazelcastTransactionManager);
        return jobRepositoryFactoryBean.getObject();
    }

    @Bean
    public HazelcastInstance hazelcastInstance() {
        ClientConfig config = new ClientConfig();
        config.setClusterName("dev");
        return HazelcastClient.newHazelcastClient(config);
    }

    @Bean
    public HazelcastTransactionManager hazelcastTransactionManager(HazelcastInstance hazelcastInstance) {
        return new HazelcastTransactionManager(hazelcastInstance);
    }

    @Bean
    public JobBuilderFactory jobBuilderFactory(JobRepository hazelCastJobRepo){
        JobBuilderFactory jobBuilderFactory = new JobBuilderFactory(hazelCastJobRepo);
        return jobBuilderFactory;
    }

    @Bean
    public StepBuilderFactory stepBuilderFactory(JobRepository hazelCastJobRepo, HazelcastTransactionManager hazelcastTransactionManager){
        StepBuilderFactory stepBuilderFactory = new StepBuilderFactory(hazelCastJobRepo, hazelcastTransactionManager);
        return stepBuilderFactory;
    }

    @Bean
    public JobExplorer jobExplorer(){
        JobInstanceDao jdbcJobInstanceDao = new JdbcJobInstanceDao();
        JobExecutionDao jobExecutionDao = new JdbcJobExecutionDao();
        StepExecutionDao stepExecutionDao = new JdbcStepExecutionDao();
        ExecutionContextDao executionContextDao = new JdbcExecutionContextDao();
        return new SimpleJobExplorer(jdbcJobInstanceDao, jobExecutionDao, stepExecutionDao, executionContextDao);
    }

    @Bean
    public ListableJobLocator listableJobLocator(){
        return new MapJobRegistry();
    }

    @Bean
    public DataSource dataSource() {
        return new DriverDataSource("jdbc:mysql://127.0.0.1:5701", "com.hazelcast.datastore.JdbcDataStoreFactory", new Properties(), "", "");
    }

}

Solution

  • See com.hazelcast.config.Config:

    /**
     * Adds an external data store configuration.
     * <p>
     * <p>
     * Example:
     * <pre>{@code
     *      Config config = new Config();
     *      Properties properties = new Properties();
     *      properties.put("jdbcUrl", jdbcUrl);
     *      properties.put("username", username);
     *      properties.put("password", password);
     *      ExternalDataStoreConfig externalDataStoreConfig = new ExternalDataStoreConfig()
     *              .setName("my-jdbc-data-store")
     *              .setClassName(JdbcDataStoreFactory.class.getName())
     *              .setProperties(properties);
     *      config.addExternalDataStoreConfig(externalDataStoreConfig);
     * }</pre>
     *
     * @since 5.2
     */
    @Beta
    public Config addExternalDataStoreConfig(ExternalDataStoreConfig externalDataStoreConfig) {
    

    To register an external data store.

    Then it looks like you need to do something like this:

    NodeEngineImpl nodeEngine = Util.getNodeEngine(hazelcastInstance);
    ExternalDataStoreFactory<?> dataStoreFactory = nodeEngine.getExternalDataStoreService().getExternalDataStoreFactory(name);
    

    and call its getDataStore().

    This is something new since Hazelcast 5.2 and looks lie we really need it for its Jet streaming processor. Not sure why would one deal with Hazelcast facade if it is still an external DB, so you simply can configure regular DataSource for that jdbc:mysql://127.0.0.1:5701.