application.properties

spring.datasource.url=jdbc:ha-jdbc:default
spring.datasource.username=user
spring.datasource.password=passwd
spring.datasource.driver-class-name=net.sf.hajdbc.sql.Driver

hajdbc.driverDatabases[0].id=db1
hajdbc.driverDatabases[0].location=jdbc:sqlserver://xxx01;databaseName=DBNAME;instanceName=001
hajdbc.driverDatabases[0].properties.user=user
hajdbc.driverDatabases[0].properties.password=passwd
#hajdbc.driverDatabases[0].properties.loginTimeout=5
#hajdbc.driverDatabases[0].properties.cancelQueryTimeout=5
#hajdbc.driverDatabases[0].properties.queryTimeout=20

#hajdbc.driverDatabases[1].id=db2
#hajdbc.driverDatabases[1].location=jdbc:sqlserver://xxx02;databaseName=DBNAME
#hajdbc.driverDatabases[1].properties.user=user
#hajdbc.driverDatabases[1].properties.password=passwd

AutoConfigure

java

Property

@ConfigurationProperties(prefix="hajdbc")
public class HaJdbcProperties {
	
	static final List<SynchronizationStrategy> SYNCHRONIZATION_STRATEGIES = Arrays.asList(
			new FullSynchronizationStrategy(),
			new DumpRestoreSynchronizationStrategy(),
			new DifferentialSynchronizationStrategy(),
			new FastDifferentialSynchronizationStrategy(),
			new PerTableSynchronizationStrategy(new FullSynchronizationStrategy()),
			new PassiveSynchronizationStrategy()						
	);

	/**
	 * Enable or disable HA JDBC integration
	 */
	private boolean enabled = true;
	/**
	 * Configure the backend databases for HA JDBC. Possible properties
	 * are id, location, driver, user and password
	 */
	private List<DriverDatabase> driverDatabases;
	/**
	 * The name of the HA JDBC cluster. To be used in the Spring Boot datasource url
	 */
	private String clusterName = "default";
	/**
	 * The cron expression that indicates when synchronization should occur
	 */
	private String cronExpression = "0 0/1 * 1/1 * ? *";
	
	private String failCronExpression= "0 * * ? * *"; 
	
	/**
	 * What synchronization factory should be used
	 */
	private String defaultSynchronizationStrategy = "passive";
	/**
	 * Whether identity column detection should be enabled
	 */
	private boolean identityColumnDetectionEnabled = false;
	/**
	 * Whether sequence detection should be enabled
	 */
	private boolean sequenceDetectionEnabled = false;

	public boolean isEnabled() {
		return enabled;
	}

	public void setEnabled(final boolean enabled) {
		this.enabled = enabled;
	}

	public List<DriverDatabase> getDriverDatabases() {
		return driverDatabases;
	}

	public void setDriverDatabases(final List<DriverDatabase> driverDatabases) {
		this.driverDatabases = driverDatabases;
	}

	public String getClusterName() {
		return clusterName;
	}

	public void setClusterName(final String clusterName) {
		this.clusterName = clusterName;
	}

	public String getCronExpression() {
		return cronExpression;
	}

	public void setCronExpression(final String cronExpression) {
		this.cronExpression = cronExpression;
	}

	public String getDefaultSynchronizationStrategy() {
		return defaultSynchronizationStrategy;
	}

	public void setDefaultSynchronizationStrategy(final String defaultSynchronizationStrategy) {
		this.defaultSynchronizationStrategy = defaultSynchronizationStrategy;
	}

	public boolean isIdentityColumnDetectionEnabled() {
		return identityColumnDetectionEnabled;
	}

	public void setIdentityColumnDetectionEnabled(final boolean identityColumnDetectionEnabled) {
		this.identityColumnDetectionEnabled = identityColumnDetectionEnabled;
	}

	public boolean isSequenceDetectionEnabled() {
		return sequenceDetectionEnabled;
	}

	public void setSequenceDetectionEnabled(final boolean sequenceDetectionEnabled) {
		this.sequenceDetectionEnabled = sequenceDetectionEnabled;
	}

	public String getFailCronExpression() {
		return failCronExpression;
	}

	public void setFailCronExpression(String failCronExpression) {
		this.failCronExpression = failCronExpression;
	}

}

AutoConfiguration

@ConditionalOnClass(Driver.class)
@AutoConfigureBefore(DataSourceAutoConfiguration.class)
@EnableConfigurationProperties(HaJdbcProperties.class)
@Configuration
public class HaJdbcAutoConfiguration {
	private static Log log = LogFactory.getLog(HaJdbcAutoConfiguration.class);
	private HaJdbcProperties properties;
	
	public HaJdbcAutoConfiguration(HaJdbcProperties properties) {
		this.properties = properties;
	}

	@Bean
	@ConditionalOnMissingBean
	public DialectFactory dialectFactory() {
		log.debug("StandardDialectFactory");
		return new StandardDialectFactory();
	}

	@Bean
	@ConditionalOnMissingBean
	public BalancerFactory balancerFactory() {
		log.debug("RoundRobinBalancerFactory");
		return new RoundRobinBalancerFactory();
	}

	@Bean
	@ConditionalOnMissingBean
	public StateManagerFactory stateManagerFactory() {
		log.debug("SimpleStateManagerFactory");
		return new SimpleStateManagerFactory();
	}

	@Bean
	@ConditionalOnMissingBean
	public DatabaseMetaDataCacheFactory databaseMetaDataCacheFactory() {
		log.debug("SimpleDatabaseMetaDataCacheFactory");
		return new SimpleDatabaseMetaDataCacheFactory();
	}
	
	@Bean
	@ConditionalOnMissingBean
	public DurabilityFactory durabilityFactory() {
		log.debug("NoDurabilityFactory");
		return new NoDurabilityFactory();
	}

	@Bean
	@ConditionalOnMissingBean
	public CommandDispatcherFactory dispatcherFactory() {
		log.debug("JGroupsCommandDispatcherFactory");
		return new JGroupsCommandDispatcherFactory();
	}
	
	
	@PostConstruct
	void register() throws ParseException {				
		if (properties.isEnabled()) {
			DriverDatabaseClusterConfiguration config = new DriverDatabaseClusterConfiguration();
			if (properties.getDriverDatabases() != null && !properties.getDriverDatabases().isEmpty()) {
				config.setDatabases(properties.getDriverDatabases());
			} else {
				throw new IllegalStateException(
						"HA JDBC driver databases should be configured to contain at least one driver database");
			}
			config.setDialectFactory(dialectFactory());
			config.setDatabaseMetaDataCacheFactory(databaseMetaDataCacheFactory());
			config.setBalancerFactory(balancerFactory());
			config.setStateManagerFactory(stateManagerFactory());
			config.setSynchronizationStrategyMap(getSynchronizationStrategyMap());
			config.setDefaultSynchronizationStrategy(properties.getDefaultSynchronizationStrategy());
			config.setIdentityColumnDetectionEnabled(properties.isIdentityColumnDetectionEnabled());
			config.setSequenceDetectionEnabled(properties.isSequenceDetectionEnabled());
			config.setAutoActivationExpression(new CronExpression(properties.getCronExpression()));
			config.setDurabilityFactory(durabilityFactory());
			
			//config.setEmptyClusterAllowed(true);			
			config.setFailureDetectionExpression(new CronExpression(properties.getFailCronExpression()));
			config.setTransactionMode(TransactionModeEnum.SERIAL);	
			config.setDispatcherFactory(dispatcherFactory());
			
			
			Driver.setConfigurationFactory(properties.getClusterName(),
					new SimpleDatabaseClusterConfigurationFactory<>(config));
			log.info("HA-JDBC registered");
		}
	}

	private static Map<String, SynchronizationStrategy> getSynchronizationStrategyMap() {
		Map<String, SynchronizationStrategy> map = new HashMap<>();
		for (SynchronizationStrategy synchronizationStrategy : HaJdbcProperties.SYNCHRONIZATION_STRATEGIES) {
			map.put(synchronizationStrategy.getId(), synchronizationStrategy);
		}
		return map;
	}

}

pom.xml

	<properties>
		<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
		<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
		<maven.compiler.source>1.8</maven.compiler.source>
		<maven.compiler.target>1.8</maven.compiler.target>
		<java.version>1.8</java.version>
		<hajdbc.version>3.0.3</hajdbc.version>
	</properties>

	<parent>
		<groupId>org.springframework.boot</groupId>
		<artifactId>spring-boot-starter-parent</artifactId>
		<version>2.0.7.RELEASE</version>
	</parent>

  <dependencies>
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-jdbc</artifactId>
			<exclusions>
				<exclusion>
					<groupId>org.springframework.boot</groupId>
					<artifactId>spring-boot-starter-logging</artifactId>
				</exclusion>
			</exclusions>
		</dependency>
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-log4j2</artifactId>
		</dependency>
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-autoconfigure</artifactId>
		</dependency>
		
		<dependency>
			<groupId>net.sf.ha-jdbc</groupId>
			<artifactId>ha-jdbc</artifactId>
			<version>${hajdbc.version}</version>
		</dependency>
		<dependency>
			<groupId>org.jgroups</groupId>
			<artifactId>jgroups</artifactId>
			<version>3.4.3.Final</version>
		</dependency>		

		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-test</artifactId>
			<scope>test</scope>
		</dependency>
  </dependencies>