initial
This commit is contained in:
parent
8fcd8cbe6b
commit
89f69dae7f
42
.gitignore
vendored
Normal file
42
.gitignore
vendored
Normal file
@ -0,0 +1,42 @@
|
||||
HELP.md
|
||||
target/
|
||||
!.mvn/wrapper/maven-wrapper.jar
|
||||
!**/src/main/**/target/
|
||||
!**/src/test/**/target/
|
||||
|
||||
### STS ###
|
||||
.apt_generated
|
||||
.classpath
|
||||
.factorypath
|
||||
.project
|
||||
.settings
|
||||
.springBeans
|
||||
.sts4-cache
|
||||
|
||||
### IntelliJ IDEA ###
|
||||
.idea
|
||||
*.iws
|
||||
*.iml
|
||||
*.ipr
|
||||
|
||||
### NetBeans ###
|
||||
/nbproject/private/
|
||||
/nbbuild/
|
||||
/dist/
|
||||
/nbdist/
|
||||
/.nb-gradle/
|
||||
build/
|
||||
!**/src/main/**/build/
|
||||
!**/src/test/**/build/
|
||||
|
||||
### VS Code ###
|
||||
.vscode/
|
||||
.DS_Store/
|
||||
|
||||
gradle.properties
|
||||
gradlew
|
||||
gradlew.bat
|
||||
gradle/
|
||||
|
||||
**/.gradle
|
||||
**/build
|
||||
109
build.gradle.kts
Normal file
109
build.gradle.kts
Normal file
@ -0,0 +1,109 @@
|
||||
plugins {
|
||||
`java-library`
|
||||
`maven-publish`
|
||||
`kotlin-dsl`
|
||||
pmd
|
||||
checkstyle
|
||||
jacoco
|
||||
id("io.freefair.lombok") version "8.4"
|
||||
id("org.sonarqube") version "4.0.0.2929"
|
||||
}
|
||||
|
||||
repositories {
|
||||
mavenLocal()
|
||||
maven {
|
||||
url = uri("https://pdftron.com/maven/release")
|
||||
}
|
||||
maven {
|
||||
url = uri("https://nexus.knecon.com/repository/gindev/");
|
||||
credentials {
|
||||
username = providers.gradleProperty("mavenUser").getOrNull();
|
||||
password = providers.gradleProperty("mavenPassword").getOrNull();
|
||||
}
|
||||
}
|
||||
mavenCentral()
|
||||
}
|
||||
|
||||
val springBootVersion = "3.1.5"
|
||||
|
||||
dependencies {
|
||||
api("com.knecon.fforesight:tenant-commons:maverick-mongo")
|
||||
api("org.liquibase:liquibase-core:4.24.0")
|
||||
api("org.liquibase.ext:liquibase-mongodb:4.24.0")
|
||||
api("org.springframework.cloud:spring-cloud-starter-openfeign:4.0.4")
|
||||
api("org.springframework.boot:spring-boot-starter-data-mongodb:${springBootVersion}")
|
||||
api("org.springframework.boot:spring-boot-configuration-processor:${springBootVersion}")
|
||||
api("org.projectlombok:lombok:1.18.28")
|
||||
runtimeOnly("org.springframework.boot:spring-boot-devtools:${springBootVersion}")
|
||||
testImplementation("org.springframework.boot:spring-boot-starter-test:${springBootVersion}")
|
||||
}
|
||||
|
||||
group = "com.knecon.fforesight"
|
||||
description = "mongo-database-commons"
|
||||
java.sourceCompatibility = JavaVersion.VERSION_17
|
||||
java.targetCompatibility = JavaVersion.VERSION_17
|
||||
|
||||
publishing {
|
||||
publications {
|
||||
create<MavenPublication>("mavenJava") {
|
||||
from(components["java"])
|
||||
}
|
||||
}
|
||||
repositories {
|
||||
maven {
|
||||
url = uri("https://nexus.knecon.com/repository/red-platform-releases/")
|
||||
credentials {
|
||||
username = providers.gradleProperty("mavenUser").getOrNull();
|
||||
password = providers.gradleProperty("mavenPassword").getOrNull();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
tasks.withType<PublishToMavenRepository> {
|
||||
onlyIf { publication.name == "mavenJava" }
|
||||
}
|
||||
|
||||
|
||||
pmd {
|
||||
isConsoleOutput = true
|
||||
}
|
||||
|
||||
tasks.pmdMain {
|
||||
pmd.ruleSetFiles = files("${rootDir}/config/pmd/pmd.xml")
|
||||
}
|
||||
|
||||
tasks.pmdTest {
|
||||
pmd.ruleSetFiles = files("${rootDir}/config/pmd/test_pmd.xml")
|
||||
}
|
||||
|
||||
tasks.named<Test>("test") {
|
||||
useJUnitPlatform()
|
||||
reports {
|
||||
junitXml.outputLocation.set(layout.buildDirectory.dir("reports/junit"))
|
||||
}
|
||||
}
|
||||
|
||||
sonarqube {
|
||||
properties {
|
||||
property("sonar.login", providers.gradleProperty("sonarToken").getOrNull())
|
||||
property("sonar.host.url", "https://sonarqube.knecon.com")
|
||||
}
|
||||
}
|
||||
|
||||
tasks.test {
|
||||
finalizedBy(tasks.jacocoTestReport)
|
||||
}
|
||||
|
||||
tasks.jacocoTestReport {
|
||||
dependsOn(tasks.test)
|
||||
reports {
|
||||
xml.required.set(true)
|
||||
csv.required.set(false)
|
||||
html.outputLocation.set(layout.buildDirectory.dir("jacocoHtml"))
|
||||
}
|
||||
}
|
||||
|
||||
java {
|
||||
withJavadocJar()
|
||||
}
|
||||
39
config/checkstyle/checkstyle.xml
Normal file
39
config/checkstyle/checkstyle.xml
Normal file
@ -0,0 +1,39 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE module PUBLIC "-//Puppy Crawl//DTD Check Configuration 1.3//EN"
|
||||
"http://www.puppycrawl.com/dtds/configuration_1_3.dtd">
|
||||
<module name="Checker">
|
||||
<property
|
||||
name="severity"
|
||||
value="error"/>
|
||||
<module name="TreeWalker">
|
||||
<module name="SuppressWarningsHolder"/>
|
||||
<module name="MissingDeprecated"/>
|
||||
<module name="MissingOverride"/>
|
||||
<module name="AnnotationLocation"/>
|
||||
<module name="JavadocStyle"/>
|
||||
<module name="NonEmptyAtclauseDescription"/>
|
||||
<module name="IllegalImport"/>
|
||||
<module name="RedundantImport"/>
|
||||
<module name="RedundantModifier"/>
|
||||
<module name="EmptyBlock"/>
|
||||
<module name="DefaultComesLast"/>
|
||||
<module name="EmptyStatement"/>
|
||||
<module name="EqualsHashCode"/>
|
||||
<module name="ExplicitInitialization"/>
|
||||
<module name="IllegalInstantiation"/>
|
||||
<module name="ModifiedControlVariable"/>
|
||||
<module name="MultipleVariableDeclarations"/>
|
||||
<module name="PackageDeclaration"/>
|
||||
<module name="ParameterAssignment"/>
|
||||
<module name="SimplifyBooleanExpression"/>
|
||||
<module name="SimplifyBooleanReturn"/>
|
||||
<module name="StringLiteralEquality"/>
|
||||
<module name="OneStatementPerLine"/>
|
||||
<module name="FinalClass"/>
|
||||
<module name="ArrayTypeStyle"/>
|
||||
<module name="UpperEll"/>
|
||||
<module name="OuterTypeFilename"/>
|
||||
</module>
|
||||
<module name="FileTabCharacter"/>
|
||||
<module name="SuppressWarningsFilter"/>
|
||||
</module>
|
||||
20
config/pmd/pmd.xml
Normal file
20
config/pmd/pmd.xml
Normal file
@ -0,0 +1,20 @@
|
||||
<?xml version="1.0"?>
|
||||
<ruleset name="Custom ruleset"
|
||||
xmlns="http://pmd.sourceforge.net/ruleset/2.0.0"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://pmd.sourceforge.net/ruleset/2.0.0 http://pmd.sourceforge.net/ruleset_2_0_0.xsd">
|
||||
|
||||
<description>
|
||||
Knecon ruleset checks the code for bad stuff
|
||||
</description>
|
||||
|
||||
<rule ref="category/java/errorprone.xml">
|
||||
<exclude name="MissingSerialVersionUID"/>
|
||||
<exclude name="AvoidLiteralsInIfCondition"/>
|
||||
<exclude name="AvoidDuplicateLiterals"/>
|
||||
<exclude name="NullAssignment"/>
|
||||
<exclude name="AssignmentInOperand"/>
|
||||
<exclude name="BeanMembersShouldSerialize"/>
|
||||
</rule>
|
||||
|
||||
</ruleset>
|
||||
22
config/pmd/test_pmd.xml
Normal file
22
config/pmd/test_pmd.xml
Normal file
@ -0,0 +1,22 @@
|
||||
<?xml version="1.0"?>
|
||||
<ruleset name="Custom ruleset"
|
||||
xmlns="http://pmd.sourceforge.net/ruleset/2.0.0"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://pmd.sourceforge.net/ruleset/2.0.0 http://pmd.sourceforge.net/ruleset_2_0_0.xsd">
|
||||
|
||||
<description>
|
||||
Knecon test ruleset checks the code for bad stuff
|
||||
</description>
|
||||
|
||||
|
||||
<rule ref="category/java/errorprone.xml">
|
||||
<exclude name="MissingSerialVersionUID"/>
|
||||
<exclude name="AvoidLiteralsInIfCondition"/>
|
||||
<exclude name="AvoidDuplicateLiterals"/>
|
||||
<exclude name="NullAssignment"/>
|
||||
<exclude name="AssignmentInOperand"/>
|
||||
<exclude name="TestClassWithoutTestCases"/>
|
||||
<exclude name="BeanMembersShouldSerialize"/>
|
||||
</rule>
|
||||
|
||||
</ruleset>
|
||||
1
gradle.properties.kts
Normal file
1
gradle.properties.kts
Normal file
@ -0,0 +1 @@
|
||||
version = 0.2-SNAPSHOT
|
||||
6
renovate.json
Normal file
6
renovate.json
Normal file
@ -0,0 +1,6 @@
|
||||
{
|
||||
"$schema": "https://docs.renovatebot.com/renovate-schema.json",
|
||||
"extends": [
|
||||
"config:base"
|
||||
]
|
||||
}
|
||||
5
settings.gradle.kts
Normal file
5
settings.gradle.kts
Normal file
@ -0,0 +1,5 @@
|
||||
/*
|
||||
* This file was generated by the Gradle 'init' task.
|
||||
*/
|
||||
|
||||
rootProject.name = "mongo-database-commons"
|
||||
@ -0,0 +1,19 @@
|
||||
package com.knecon.fforesight.mongo.database.commons;
|
||||
|
||||
import org.springframework.boot.autoconfigure.AutoConfiguration;
|
||||
import org.springframework.boot.autoconfigure.AutoConfigureAfter;
|
||||
import org.springframework.boot.autoconfigure.ImportAutoConfiguration;
|
||||
import org.springframework.boot.autoconfigure.liquibase.LiquibaseProperties;
|
||||
import org.springframework.boot.context.properties.EnableConfigurationProperties;
|
||||
import org.springframework.context.annotation.ComponentScan;
|
||||
|
||||
import com.knecon.fforesight.tenantcommons.MultiTenancyAutoConfiguration;
|
||||
|
||||
@ComponentScan
|
||||
@AutoConfiguration
|
||||
@AutoConfigureAfter(MultiTenancyAutoConfiguration.class)
|
||||
@ImportAutoConfiguration(MultiTenancyAutoConfiguration.class)
|
||||
@EnableConfigurationProperties({LiquibaseProperties.class})
|
||||
public class MongoDatabaseCommonsAutoConfiguration {
|
||||
|
||||
}
|
||||
@ -0,0 +1,53 @@
|
||||
package com.knecon.fforesight.mongo.database.commons.config;
|
||||
|
||||
import java.time.OffsetDateTime;
|
||||
import java.time.ZoneOffset;
|
||||
import java.util.Arrays;
|
||||
import java.util.Date;
|
||||
|
||||
import org.bson.Document;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.core.convert.converter.Converter;
|
||||
import org.springframework.data.mongodb.core.convert.MongoCustomConversions;
|
||||
|
||||
@Configuration
|
||||
public class MongoDbConfiguration {
|
||||
|
||||
@Bean
|
||||
public MongoCustomConversions mongoCustomConversions() {
|
||||
|
||||
return new MongoCustomConversions(Arrays.asList(new MongoOffsetDateTimeWriter(), new MongoOffsetDateTimeReader()));
|
||||
}
|
||||
|
||||
|
||||
public static class MongoOffsetDateTimeWriter implements Converter<OffsetDateTime, Document> {
|
||||
|
||||
public static final String DATE_FIELD = "dateTime";
|
||||
public static final String OFFSET_FIELD = "offset";
|
||||
|
||||
|
||||
@Override
|
||||
public Document convert(final OffsetDateTime offsetDateTime) {
|
||||
|
||||
final Document document = new Document();
|
||||
document.put(DATE_FIELD, Date.from(offsetDateTime.toInstant()));
|
||||
document.put(OFFSET_FIELD, offsetDateTime.getOffset().toString());
|
||||
return document;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public static class MongoOffsetDateTimeReader implements Converter<Document, OffsetDateTime> {
|
||||
|
||||
@Override
|
||||
public OffsetDateTime convert(final Document document) {
|
||||
|
||||
final Date dateTime = document.getDate(MongoOffsetDateTimeWriter.DATE_FIELD);
|
||||
final ZoneOffset offset = ZoneOffset.of(document.getString(MongoOffsetDateTimeWriter.OFFSET_FIELD));
|
||||
return OffsetDateTime.ofInstant(dateTime.toInstant(), offset);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
@ -0,0 +1,33 @@
|
||||
package com.knecon.fforesight.mongo.database.commons.config;
|
||||
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.beans.factory.annotation.Qualifier;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.data.mongodb.core.SimpleMongoClientDatabaseFactory;
|
||||
|
||||
import com.knecon.fforesight.mongo.database.commons.service.MongoDataSources;
|
||||
import com.mongodb.client.MongoClient;
|
||||
import com.mongodb.client.MongoDatabase;
|
||||
|
||||
@Configuration
|
||||
public class MultiTenantMongoDBFactory extends SimpleMongoClientDatabaseFactory {
|
||||
|
||||
@Autowired
|
||||
MongoDataSources mongoDataSources;
|
||||
|
||||
|
||||
public MultiTenantMongoDBFactory(@Qualifier("getMongoClient") MongoClient mongoClient, String databaseName) {
|
||||
|
||||
super(mongoClient, databaseName);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
protected @NotNull MongoDatabase doGetMongoDatabase(@NotNull String dbName) {
|
||||
|
||||
return mongoDataSources.mongoDatabaseCurrentTenantResolver();
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
@ -0,0 +1,9 @@
|
||||
package com.knecon.fforesight.mongo.database.commons.exception;
|
||||
|
||||
public class MongoDBTenantException extends RuntimeException {
|
||||
|
||||
public MongoDBTenantException(String msg, Throwable t) {
|
||||
super(msg, t);
|
||||
}
|
||||
|
||||
}
|
||||
@ -0,0 +1,29 @@
|
||||
package com.knecon.fforesight.mongo.database.commons.liquibase;
|
||||
|
||||
import org.springframework.boot.autoconfigure.liquibase.LiquibaseProperties;
|
||||
import org.springframework.boot.context.properties.ConfigurationProperties;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
|
||||
import com.knecon.fforesight.tenantcommons.EncryptionDecryptionService;
|
||||
import com.knecon.fforesight.tenantcommons.TenantProvider;
|
||||
|
||||
@Configuration
|
||||
public class MongoLiquibaseConfig {
|
||||
|
||||
@Bean
|
||||
@ConfigurationProperties("multitenancy.tenant.liquibase")
|
||||
public LiquibaseProperties tenantLiquibaseProperties() {
|
||||
|
||||
return new LiquibaseProperties();
|
||||
}
|
||||
|
||||
|
||||
@Bean
|
||||
public TenantMongoLiquibaseExecutor tenantLiquibase(EncryptionDecryptionService encryptionService,
|
||||
TenantProvider tenantProvider,
|
||||
LiquibaseProperties tenantLiquibaseProperties) {
|
||||
|
||||
return new TenantMongoLiquibaseExecutor(encryptionService, tenantProvider, tenantLiquibaseProperties);
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,75 @@
|
||||
package com.knecon.fforesight.mongo.database.commons.liquibase;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import org.springframework.beans.factory.InitializingBean;
|
||||
import org.springframework.beans.factory.annotation.Qualifier;
|
||||
import org.springframework.boot.autoconfigure.liquibase.LiquibaseProperties;
|
||||
|
||||
import com.knecon.fforesight.mongo.database.commons.utils.MongoUtils;
|
||||
import com.knecon.fforesight.tenantcommons.EncryptionDecryptionService;
|
||||
import com.knecon.fforesight.tenantcommons.TenantProvider;
|
||||
import com.knecon.fforesight.tenantcommons.model.MongoDBConnection;
|
||||
import com.knecon.fforesight.tenantcommons.model.TenantResponse;
|
||||
|
||||
import feign.RetryableException;
|
||||
import liquibase.Contexts;
|
||||
import liquibase.Liquibase;
|
||||
import liquibase.changelog.ChangeSet;
|
||||
import liquibase.database.DatabaseFactory;
|
||||
import liquibase.ext.mongodb.database.MongoLiquibaseDatabase;
|
||||
import liquibase.resource.ClassLoaderResourceAccessor;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import lombok.SneakyThrows;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
|
||||
@Slf4j
|
||||
@RequiredArgsConstructor
|
||||
public class TenantMongoLiquibaseExecutor implements InitializingBean {
|
||||
|
||||
private final EncryptionDecryptionService encryptionService;
|
||||
private final TenantProvider tenantProvider;
|
||||
|
||||
@Qualifier("tenantLiquibaseProperties")
|
||||
private final LiquibaseProperties tenantLiquibaseProperties;
|
||||
|
||||
|
||||
@Override
|
||||
public void afterPropertiesSet() {
|
||||
|
||||
log.info("MongoDB multi-tenancy enabled");
|
||||
try {
|
||||
this.runOnAllTenants(tenantProvider.getTenants());
|
||||
} catch (RetryableException e) {
|
||||
log.warn("Tenant Service not online, skipping liquibase migration: {}", e.getMessage(), e);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@SneakyThrows
|
||||
protected void runOnAllTenants(List<TenantResponse> tenants) {
|
||||
|
||||
for (var tenant : tenants) {
|
||||
|
||||
MongoDBConnection mongoDBConnection = tenant.getMongoDBConnection();
|
||||
var mongoUrl = MongoUtils.buildMongoUrl(mongoDBConnection);
|
||||
log.info("Initializing MongoDB liquibase for tenant {} / {}", tenant.getTenantId(), mongoUrl);
|
||||
|
||||
try (MongoLiquibaseDatabase database = (MongoLiquibaseDatabase) DatabaseFactory.getInstance()
|
||||
.openDatabase(mongoUrl, mongoDBConnection.getUsername(), encryptionService.decrypt(mongoDBConnection.getPassword()), null, null)) {
|
||||
|
||||
Liquibase liquibase = new Liquibase(tenantLiquibaseProperties.getChangeLog(), new ClassLoaderResourceAccessor(), database);
|
||||
Contexts contexts = new Contexts(tenantLiquibaseProperties.getContexts());
|
||||
List<ChangeSet> changeSetsList = liquibase.listUnrunChangeSets(contexts, null);
|
||||
if (!changeSetsList.isEmpty()) {
|
||||
liquibase.update(contexts);
|
||||
}
|
||||
|
||||
} catch (Exception e) {
|
||||
log.error("Failed to run liquibase migration on MongoDB for tenant: {}", tenant.getTenantId(), e);
|
||||
}
|
||||
log.info("Liquibase ran on MongoDB for tenant " + tenant.getTenantId());
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@ -0,0 +1,6 @@
|
||||
package com.knecon.fforesight.mongo.database.commons.model;
|
||||
|
||||
import com.mongodb.client.MongoClient;
|
||||
|
||||
public record MongoClientConnection (String database, MongoClient mongoClient) {
|
||||
}
|
||||
@ -0,0 +1,83 @@
|
||||
package com.knecon.fforesight.mongo.database.commons.service;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.springframework.beans.factory.annotation.Value;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import com.google.common.cache.CacheBuilder;
|
||||
import com.google.common.cache.CacheLoader;
|
||||
import com.google.common.cache.LoadingCache;
|
||||
import com.knecon.fforesight.mongo.database.commons.model.MongoClientConnection;
|
||||
import com.knecon.fforesight.tenantcommons.model.MongoDBConnection;
|
||||
import com.mongodb.MongoClientSettings;
|
||||
import com.mongodb.MongoCredential;
|
||||
import com.mongodb.ServerAddress;
|
||||
import com.mongodb.client.MongoClient;
|
||||
import com.mongodb.client.MongoClients;
|
||||
|
||||
import jakarta.annotation.PostConstruct;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import lombok.SneakyThrows;
|
||||
|
||||
@Service
|
||||
@RequiredArgsConstructor
|
||||
public class MongoClientCache {
|
||||
|
||||
private final MongoConnectionProvider mongoConnectionProvider;
|
||||
|
||||
@Value("${mongo.client-cache.maximumSize:100}")
|
||||
private Long maximumSize;
|
||||
|
||||
@Value("${mongo.client-cache.expireAfterAccess:10}")
|
||||
private Integer expireAfterAccess;
|
||||
|
||||
private LoadingCache<String, MongoClientConnection> clients;
|
||||
|
||||
|
||||
@PostConstruct
|
||||
protected void createCache() {
|
||||
|
||||
clients = CacheBuilder.newBuilder().maximumSize(maximumSize).expireAfterAccess(expireAfterAccess, TimeUnit.MINUTES).build(new CacheLoader<>() {
|
||||
public @NotNull MongoClientConnection load(@NotNull String key) {
|
||||
|
||||
var mongoDBConnection = mongoConnectionProvider.getMongoDBConnection(key);
|
||||
|
||||
if (mongoDBConnection != null) {
|
||||
return new MongoClientConnection(mongoDBConnection.getDatabase(), buildMongoClient(mongoDBConnection));
|
||||
}
|
||||
throw new RuntimeException("No Connection provided");
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
private MongoClient buildMongoClient(MongoDBConnection mongoDBConnection) {
|
||||
|
||||
MongoCredential credential = MongoCredential.createCredential(mongoDBConnection.getUsername(),
|
||||
mongoDBConnection.getDatabase(),
|
||||
mongoDBConnection.getPassword().toCharArray());
|
||||
return MongoClients.create(MongoClientSettings.builder()
|
||||
.applyToClusterSettings(builder -> builder.hosts(Collections.singletonList(new ServerAddress(mongoDBConnection.getHost(),
|
||||
Integer.parseInt(mongoDBConnection.getPort())))))
|
||||
.credential(credential)
|
||||
.build());
|
||||
}
|
||||
|
||||
|
||||
@SneakyThrows
|
||||
public MongoClient getClient(String tenantId) {
|
||||
|
||||
return clients.get(tenantId).mongoClient();
|
||||
}
|
||||
|
||||
|
||||
@SneakyThrows
|
||||
public MongoClientConnection getClientConnection(String tenantId) {
|
||||
|
||||
return clients.get(tenantId);
|
||||
}
|
||||
|
||||
}
|
||||
@ -0,0 +1,9 @@
|
||||
package com.knecon.fforesight.mongo.database.commons.service;
|
||||
|
||||
import com.knecon.fforesight.tenantcommons.model.MongoDBConnection;
|
||||
|
||||
public interface MongoConnectionProvider {
|
||||
|
||||
MongoDBConnection getMongoDBConnection(String tenantId);
|
||||
|
||||
}
|
||||
@ -0,0 +1,31 @@
|
||||
package com.knecon.fforesight.mongo.database.commons.service;
|
||||
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import com.knecon.fforesight.tenantcommons.EncryptionDecryptionService;
|
||||
import com.knecon.fforesight.tenantcommons.TenantProvider;
|
||||
import com.knecon.fforesight.tenantcommons.model.MongoDBConnection;
|
||||
import com.knecon.fforesight.tenantcommons.model.TenantResponse;
|
||||
|
||||
import lombok.RequiredArgsConstructor;
|
||||
|
||||
@Service
|
||||
@RequiredArgsConstructor
|
||||
@ConditionalOnClass(MongoConnectionProvider.class)
|
||||
public class MongoConnectionProviderImpl implements MongoConnectionProvider {
|
||||
|
||||
private final TenantProvider tenantProvider;
|
||||
private final EncryptionDecryptionService encryptionDecryptionService;
|
||||
|
||||
|
||||
@Override
|
||||
public MongoDBConnection getMongoDBConnection(String tenantId) {
|
||||
|
||||
TenantResponse tenant = tenantProvider.getTenant(tenantId);
|
||||
MongoDBConnection mongoDBConnection = tenant.getMongoDBConnection();
|
||||
mongoDBConnection.setPassword(encryptionDecryptionService.decrypt(mongoDBConnection.getPassword()));
|
||||
return mongoDBConnection;
|
||||
}
|
||||
|
||||
}
|
||||
@ -0,0 +1,46 @@
|
||||
package com.knecon.fforesight.mongo.database.commons.service;
|
||||
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import com.knecon.fforesight.mongo.database.commons.exception.MongoDBTenantException;
|
||||
import com.knecon.fforesight.tenantcommons.TenantContext;
|
||||
import com.mongodb.client.MongoClient;
|
||||
import com.mongodb.client.MongoDatabase;
|
||||
|
||||
import lombok.RequiredArgsConstructor;
|
||||
|
||||
@Component
|
||||
@RequiredArgsConstructor
|
||||
public class MongoDataSources {
|
||||
|
||||
private final MongoClientCache mongoClientCache;
|
||||
|
||||
|
||||
@Bean
|
||||
public String databaseName() {
|
||||
|
||||
return mongoClientCache.getClientConnection(TenantContext.getTenantId()).database();
|
||||
}
|
||||
|
||||
|
||||
@Bean
|
||||
public MongoClient getMongoClient() {
|
||||
|
||||
return mongoClientCache.getClient(TenantContext.getTenantId());
|
||||
}
|
||||
|
||||
|
||||
public MongoDatabase mongoDatabaseCurrentTenantResolver() {
|
||||
|
||||
try {
|
||||
final String tenantId = TenantContext.getTenantId();
|
||||
|
||||
return mongoClientCache.getClient(tenantId).getDatabase(mongoClientCache.getClientConnection(tenantId).database());
|
||||
|
||||
} catch (Exception exception) {
|
||||
throw new MongoDBTenantException("MongoDB Tenant exception", exception);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@ -0,0 +1,55 @@
|
||||
package com.knecon.fforesight.mongo.database.commons.utils;
|
||||
|
||||
import com.knecon.fforesight.tenantcommons.model.MongoDBConnection;
|
||||
|
||||
import lombok.experimental.UtilityClass;
|
||||
|
||||
@UtilityClass
|
||||
public class MongoUtils {
|
||||
|
||||
|
||||
private StringBuilder createMongoConnectionStringBuilder(String host, String port, String database) {
|
||||
|
||||
return new StringBuilder("mongodb://").append(host).append(':').append(port).append('/').append(database);
|
||||
}
|
||||
|
||||
private StringBuilder createMongoConnectionStringBuilder(String host, String port, String username, String password, String database) {
|
||||
|
||||
return createMongoConnectionStringBuilder(host, port, username, password).append('/').append(database);
|
||||
}
|
||||
|
||||
|
||||
private StringBuilder createMongoConnectionStringBuilder(String host, String port, String username, String password) {
|
||||
|
||||
return new StringBuilder("mongodb://").append(username).append(':').append(password).append("@").append(host).append(':').append(port);
|
||||
}
|
||||
|
||||
|
||||
public String buildMongoUrl(MongoDBConnection mongoDBConnection) {
|
||||
|
||||
return createMongoConnectionStringBuilder(mongoDBConnection.getHost(),
|
||||
mongoDBConnection.getPort(),
|
||||
mongoDBConnection.getDatabase()).toString();
|
||||
}
|
||||
|
||||
|
||||
public String buildMongoUrlWithAuth(MongoDBConnection mongoDBConnection) {
|
||||
|
||||
return createMongoConnectionStringBuilder(mongoDBConnection.getHost(),
|
||||
mongoDBConnection.getPort(),
|
||||
mongoDBConnection.getUsername(),
|
||||
mongoDBConnection.getPassword()).toString();
|
||||
}
|
||||
|
||||
|
||||
public String buildMongoUrlWithAuthForDatabase(MongoDBConnection mongoDBConnection) {
|
||||
|
||||
return createMongoConnectionStringBuilder(mongoDBConnection.getHost(),
|
||||
mongoDBConnection.getPort(),
|
||||
mongoDBConnection.getUsername(),
|
||||
mongoDBConnection.getPassword(),
|
||||
mongoDBConnection.getDatabase()).toString();
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
1
src/main/resources/META-INF/spring.factories
Normal file
1
src/main/resources/META-INF/spring.factories
Normal file
@ -0,0 +1 @@
|
||||
org.springframework.boot.autoconfigure.EnableAutoConfiguration=com.knecon.fforesight.mongo.database.commons.mongo.database.commonsAutoConfiguration
|
||||
Loading…
x
Reference in New Issue
Block a user