package org.gbif.checklistbank.service.mybatis.guice; import org.gbif.api.service.checklistbank.DatasetMetricsService; import org.gbif.api.service.checklistbank.DescriptionService; import org.gbif.api.service.checklistbank.DistributionService; import org.gbif.api.service.checklistbank.IdentifierService; import org.gbif.api.service.checklistbank.MultimediaService; import org.gbif.api.service.checklistbank.NameParser; import org.gbif.api.service.checklistbank.NameUsageService; import org.gbif.api.service.checklistbank.ReferenceService; import org.gbif.api.service.checklistbank.SpeciesProfileService; import org.gbif.api.service.checklistbank.TypeSpecimenService; import org.gbif.api.service.checklistbank.VernacularNameService; import org.gbif.checklistbank.config.ClbConfiguration; import org.gbif.checklistbank.service.CitationService; import org.gbif.checklistbank.service.ColAnnotationService; import org.gbif.checklistbank.service.DatasetAnalysisService; import org.gbif.checklistbank.service.DatasetImportService; import org.gbif.checklistbank.service.ParsedNameService; import org.gbif.checklistbank.service.UsageService; import org.gbif.checklistbank.service.UsageSyncService; import org.gbif.checklistbank.service.mybatis.mapper.NameUsageMapper; import org.gbif.checklistbank.service.mybatis.mapper.UsageCountMapper; import org.gbif.mybatis.guice.MyBatisModule; import org.gbif.service.guice.PrivateServiceModule; import java.io.Closeable; import java.io.IOException; import java.util.Properties; import com.google.inject.Provides; import com.google.inject.Singleton; import org.slf4j.Logger; import org.slf4j.LoggerFactory; /** * Guice Module to use the database backed ChecklistBank MyBatis layer. * To use this instantiate this module using one of the available constructors and provide the required properties. You * need to provide at least the following entries for this to work. All properties have to be * prefixed with {@code checklistbank.db}: * <ul> * <li>{@code checklistbank.db.dataSource.serverName</li> * <li>{@code checklistbank.db.dataSource.databaseName</li> * <li>{@code checklistbank.db.dataSource.user</li> * <li>{@code checklistbank.db.dataSource.password</li> * </ul> * You can also use any other properties that MyBatis or HikariCP understands as long as they * have the proper prefix. * See https://github.com/brettwooldridge/HikariCP#configuration-knobs-baby */ public class ChecklistBankServiceMyBatisModule extends PrivateServiceModule implements Closeable { private static final Logger LOG = LoggerFactory.getLogger(ChecklistBankServiceMyBatisModule.class); private static final String PREFIX = "checklistbank.db."; private final int parserTimeout; private final int importThreads; /** * Uses the given properties to configure the service. * * @param properties to use */ public ChecklistBankServiceMyBatisModule(Properties properties) { super(PREFIX, properties); parserTimeout = Integer.parseInt(properties.getProperty(ClbConfiguration.PARSER_TIMEOUT_PROP, "500")); importThreads = Integer.parseInt(properties.getProperty(ClbConfiguration.IMPORT_THREADS_PROP, "2")); } public static ChecklistBankServiceMyBatisModule create(ClbConfiguration cfg) { LOG.info("Connecting to checklistbank db {} on {} with user {}", cfg.databaseName, cfg.serverName, cfg.user); return new ChecklistBankServiceMyBatisModule(cfg.toProps(true)); } @Provides @Singleton public ClbConfiguration provideCfg() throws Exception { ClbConfiguration cfg = new ClbConfiguration(); cfg.serverName = getProperties().getProperty("dataSource.serverName"); cfg.databaseName = getProperties().getProperty("dataSource.databaseName"); cfg.user = getProperties().getProperty("dataSource.user"); cfg.password = getProperties().getProperty("dataSource.password"); cfg.parserTimeout = parserTimeout; cfg.syncThreads = importThreads; cfg.maximumPoolSize = getIntProp("maximumPoolSize", cfg.maximumPoolSize); cfg.minimumIdle = getIntProp("minimumIdle", cfg.minimumIdle); cfg.idleTimeout = getIntProp("idleTimeout", cfg.idleTimeout); cfg.maxLifetime = getIntProp("maxLifetime", cfg.maxLifetime); cfg.connectionTimeout = getIntProp("connectionTimeout", cfg.connectionTimeout); LOG.info("Provide {}", cfg.toString()); return cfg; } private int getIntProp(String name, int defaultVal) { try { return Integer.valueOf(getProperties().getProperty(name, "x")); } catch (NumberFormatException e) { return defaultVal; } } @Override protected void configureService() { // default parser timeout is 500ms // install mybatis module MyBatisModule mybatModule = new InternalChecklistBankServiceMyBatisModule(getProperties(), parserTimeout, importThreads); install(mybatModule); // expose a named datasource binding and session manager for transactions expose(mybatModule.getDatasourceKey()); expose(mybatModule.getSessionManagerKey()); expose(NameUsageService.class); expose(VernacularNameService.class); expose(ReferenceService.class); expose(DescriptionService.class); expose(DistributionService.class); expose(IdentifierService.class); expose(MultimediaService.class); expose(SpeciesProfileService.class); expose(TypeSpecimenService.class); expose(DatasetMetricsService.class); // not available in API: expose(UsageService.class); expose(ParsedNameService.class); expose(NameParser.class); expose(CitationService.class); expose(ColAnnotationService.class); expose(DatasetAnalysisService.class); expose(UsageCountMapper.class); expose(DatasetImportService.class).annotatedWith(Mybatis.class); expose(UsageSyncService.class); // mappers being exposed expose(NameUsageMapper.class); expose(ClbConfiguration.class); } @Override public void close() throws IOException { } }