package com.example.sbcamel; import java.io.IOException; import java.util.Objects; import java.util.Set; import java.util.stream.Collectors; import javax.sql.DataSource; import org.apache.camel.component.mybatis.MyBatisComponent; import org.apache.camel.spring.spi.SpringTransactionPolicy; import org.apache.ibatis.mapping.Environment; import org.apache.ibatis.session.SqlSessionFactory; import org.apache.ibatis.session.SqlSessionFactoryBuilder; import org.apache.ibatis.transaction.jdbc.JdbcTransactionFactory; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Value; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.jdbc.datasource.DataSourceTransactionManager; import org.springframework.jdbc.datasource.TransactionAwareDataSourceProxy; import org.springframework.transaction.PlatformTransactionManager; import com.google.common.reflect.ClassPath; import com.zaxxer.hikari.HikariConfig; import com.zaxxer.hikari.HikariDataSource; @Configuration public class DatabaseConfig { private static final Logger logger = LoggerFactory.getLogger(DatabaseConfig.class); public static final String CFG_APP_DATABASE_URL = "${app.database.url}"; public static final String CFG_APP_DATABASE_USERNAME = "${app.database.username:}"; public static final String CFG_APP_DATABASE_PASSWORD = "${app.database.password:}"; public static final String CFG_APP_DATABASE_MAPPER_PACKAGE = "${app.database.mapper-package}"; public static final String CFG_APP_DATABASE_SPRINGBOOT_CLASS_PREFIX = "${app.database.springboot-class-prefix:BOOT-INF.classes.}"; @Value(CFG_APP_DATABASE_URL) private String dbUrl; @Value(CFG_APP_DATABASE_USERNAME) private String dbUsername; @Value(CFG_APP_DATABASE_PASSWORD) private String dbPassword; @Value(CFG_APP_DATABASE_MAPPER_PACKAGE) private String mapperPackage; @Value(CFG_APP_DATABASE_SPRINGBOOT_CLASS_PREFIX) private String springBootClassPrefix; @Bean HikariConfig hikariConfig() { HikariConfig config = new HikariConfig(); config.setJdbcUrl(dbUrl); config.setUsername(dbUsername); config.setPassword(dbPassword); config.addDataSourceProperty("cachePrepStmts", "true"); config.addDataSourceProperty("prepStmtCacheSize", "250"); config.addDataSourceProperty("prepStmtCacheSqlLimit", "2048"); return config; } @Bean DataSource dataSource(HikariConfig hikariConfig) { return new TransactionAwareDataSourceProxy(new HikariDataSource(hikariConfig)); } @Bean PlatformTransactionManager txManager(DataSource dataSource) { return new DataSourceTransactionManager(dataSource); } @Bean SqlSessionFactory sqlSessionFactory(DataSource dataSource) throws Exception { Environment environment = new Environment("development", new JdbcTransactionFactory(), dataSource); org.apache.ibatis.session.Configuration configuration = new org.apache.ibatis.session.Configuration( environment); Set> mapperClasses = findAllClassesUsingGuava(mapperPackage); mapperClasses.forEach(configuration::addMapper); return new SqlSessionFactoryBuilder().build(configuration); } @Bean MyBatisComponent mybatis(SqlSessionFactory sqlSessionFactory) { MyBatisComponent mybatis = new MyBatisComponent(); mybatis.setSqlSessionFactory(sqlSessionFactory); return mybatis; } @Bean SpringTransactionPolicy propagationRequired(PlatformTransactionManager txManager) { SpringTransactionPolicy propagationRequired = new SpringTransactionPolicy(); propagationRequired.setTransactionManager(txManager); propagationRequired.setPropagationBehaviorName("PROPAGATION_REQUIRED"); return propagationRequired; } private Set> findAllClassesUsingGuava(String packageName) throws IOException { logger.trace("Orm mappers packageName: {}", packageName); return ClassPath.from(ClassLoader.getSystemClassLoader()).getAllClasses().stream() .peek(clazz -> logger.trace("candidate class: {}, package name: {}", clazz, clazz.getPackageName())) .filter(clazz -> clazz.getPackageName().endsWith(packageName)) .peek(clazz -> logger.info("accepted class: {}, package name: {}", clazz, clazz.getPackageName())) .map(clazz -> { try { if (clazz.getName().startsWith(springBootClassPrefix)) { return Class.forName(clazz.getName().replace(springBootClassPrefix, "")); } return Class.forName(clazz.getName()); } catch (ClassNotFoundException e) { logger.error("cannot convert this class name to class: {}", clazz.getName()); } return null; }).filter(Objects::nonNull).collect(Collectors.toSet()); } }