Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Added couchbase spring boot 3 driver #9

Merged
merged 1 commit into from
Jan 10, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
100 changes: 100 additions & 0 deletions spring/couchbase-springboot-v3-driver/pom.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,100 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>

<parent>
<groupId>io.mongock</groupId>
<artifactId>spring-jdk17</artifactId>
<version>5.3.6-SNAPSHOT</version>
</parent>

<artifactId>couchbase-springboot-v3-driver</artifactId>
<packaging>jar</packaging>

<dependencyManagement>
<dependencies>
<dependency>
<groupId>io.mongock</groupId>
<artifactId>mongock-driver-couchbase-bom</artifactId>
<version>${mongock.community.version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>

<dependencies>
<!-- CORE DEPENDENCIES -->
<dependency>
<groupId>io.mongock</groupId>
<artifactId>mongock-driver-core</artifactId>
</dependency>
<dependency>
<groupId>io.mongock</groupId>
<artifactId>mongock-api</artifactId>
</dependency>
<dependency>
<groupId>io.mongock</groupId>
<artifactId>couchbase-driver</artifactId>
</dependency>
<dependency>
<groupId>io.mongock</groupId>
<artifactId>mongock-springboot-v3</artifactId>
<version>${project.version}</version>
</dependency>

<!-- SPRING -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-autoconfigure</artifactId>
<version>${spring-boot-3.version}</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-configuration-processor</artifactId>
<version>${spring-boot-3.version}</version>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.springframework.data</groupId>
<artifactId>spring-data-couchbase</artifactId>
<version>${spring-data-5.couchbase.version}</version>
</dependency>
<dependency>
<groupId>com.couchbase.client</groupId>
<artifactId>java-client</artifactId>
<version>${couchbase-java-client.version}</version>
</dependency>

<!-- TEST -->
<dependency>
<groupId>io.mongock</groupId>
<artifactId>mongock-test-util</artifactId>
<version>${mongock.community.version}</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<version>${spring-boot-3.version}</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.junit.jupiter</groupId>
<artifactId>junit-jupiter-engine</artifactId>
<version>${junit.jupiter.version}</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-simple</artifactId>
<version>${slf4j-api.version}</version>
<scope>test</scope>
</dependency>

</dependencies>


</project>
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
package io.mongock.driver.couchbase.springboot.config;

import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.annotation.Configuration;

/**
* Configuration properties for Mongock Couchbase.
*
* @author Tigran Babloyan
*/
@Configuration
@ConfigurationProperties("mongock.couchbase")
public class CouchbaseConfiguration {
/**
* The custom scope to be used by the Mongock.
* Can be used for Couchbase Server 7+ to set custom scope on the stored data.
*
* Note: If scope is set the collection needs to be set as well.
*/
private String scope;
/**
* The custom collection to be used by the Mongock.
* Can be used for Couchbase Server 7+ to set custom collection on the stored data.
*/
private String collection;

public String getScope() {
return scope;
}

public void setScope(String scope) {
this.scope = scope;
}

public String getCollection() {
return collection;
}

public void setCollection(String collection) {
this.collection = collection;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
package io.mongock.driver.couchbase.springboot.config;

import com.couchbase.client.java.Collection;
import io.mongock.api.config.MongockConfiguration;
import io.mongock.driver.api.driver.ConnectionDriver;
import io.mongock.driver.couchbase.driver.CouchbaseDriver;
import org.springframework.boot.autoconfigure.AutoConfiguration;
import org.springframework.boot.autoconfigure.AutoConfigureAfter;
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
import org.springframework.boot.autoconfigure.condition.ConditionalOnBean;
import org.springframework.boot.autoconfigure.condition.ConditionalOnExpression;
import org.springframework.boot.autoconfigure.data.couchbase.CouchbaseDataAutoConfiguration;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.couchbase.CouchbaseClientFactory;
import org.springframework.util.StringUtils;


/**
* {@link EnableAutoConfiguration Auto-configuration} for Mongock Couchbase support.
*
* @author Tigran Babloyan
*/
@AutoConfiguration
@ConditionalOnExpression("${mongock.enabled:true}")
@ConditionalOnBean({MongockConfiguration.class, CouchbaseClientFactory.class})
@EnableConfigurationProperties(CouchbaseConfiguration.class)
@AutoConfigureAfter(CouchbaseDataAutoConfiguration.class)
public class CouchbaseSpringbootContext {

@Bean
public ConnectionDriver connectionDriver(CouchbaseClientFactory couchbaseClientFactory,
CouchbaseConfiguration couchbaseConfiguration,
MongockConfiguration mongockConfig) {
Collection collection = isCustomCollection(couchbaseConfiguration) ?
couchbaseClientFactory.withScope(couchbaseConfiguration.getScope()).getCollection(couchbaseConfiguration.getCollection()) :
couchbaseClientFactory.getDefaultCollection();
CouchbaseDriver driver = CouchbaseDriver.withLockStrategy(couchbaseClientFactory.getCluster(),
collection,
mongockConfig.getLockAcquiredForMillis(),
mongockConfig.getLockQuitTryingAfterMillis(),
mongockConfig.getLockTryFrequencyMillis());
driver.setIndexCreation(mongockConfig.isIndexCreation());
return driver;
}

private boolean isCustomCollection(CouchbaseConfiguration couchbaseConfiguration){
return StringUtils.hasText(couchbaseConfiguration.getCollection()) &&
StringUtils.hasText(couchbaseConfiguration.getScope());
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
io.mongock.driver.couchbase.springboot.config.CouchbaseSpringbootContext
Original file line number Diff line number Diff line change
@@ -0,0 +1,114 @@
package io.mongock.driver.couchbase.springboot.config;

import com.couchbase.client.core.io.CollectionIdentifier;
import com.couchbase.client.java.Bucket;
import com.couchbase.client.java.Cluster;
import com.couchbase.client.java.Collection;
import com.couchbase.client.java.Scope;
import io.mongock.api.config.MongockConfiguration;
import io.mongock.driver.api.driver.ConnectionDriver;
import io.mongock.driver.couchbase.driver.CouchbaseDriver;
import io.mongock.runner.springboot.base.config.MongockSpringConfiguration;
import io.mongock.util.test.ReflectionUtils;
import org.junit.jupiter.api.Test;
import org.springframework.boot.autoconfigure.AutoConfigurations;
import org.springframework.boot.test.context.runner.ApplicationContextRunner;
import org.springframework.data.couchbase.SimpleCouchbaseClientFactory;

import static org.assertj.core.api.Assertions.assertThat;
import static org.mockito.Mockito.*;

class CouchbaseSpringbootContextTest {

private static final String NONE_DEFAULT_NAME = "nondefault";
private final ApplicationContextRunner contextRunner = new ApplicationContextRunner();

@Test
void test_driver_autoconfigured() {
contextRunner
.withPropertyValues("mongock.enabled=true")
.withBean(SimpleCouchbaseClientFactory.class, mockCluster(), "mongock", null)
.withConfiguration(AutoConfigurations.of(
MongockConfiguration.class,
CouchbaseSpringbootContext.class))
.run(context -> {
assertThat(context).hasSingleBean(ConnectionDriver.class);
CouchbaseDriver driver = context.getBean(CouchbaseDriver.class);
assertThat(collectionName(driver)).isEqualTo(CollectionIdentifier.DEFAULT_COLLECTION);
assertThat(driver.isIndexCreation()).isTrue();
}
);
}

@Test
void test_driver_missing_on_mongock_disabled() {
contextRunner
.withPropertyValues("mongock.enabled=false")
.withBean(SimpleCouchbaseClientFactory.class, mockCluster(), "mongock", null)
.withConfiguration(AutoConfigurations.of(
MongockConfiguration.class,
CouchbaseSpringbootContext.class))
.run((context) -> assertThat(context)
.doesNotHaveBean(ConnectionDriver.class));
}

@Test
void test_context_collection_modifications() {
contextRunner
.withPropertyValues("mongock.enabled=true", "mongock.couchbase.scope=nondefault", "mongock.couchbase.collection=nondefault")
.withBean(SimpleCouchbaseClientFactory.class, mockCluster(), "mongock", null)
.withConfiguration(AutoConfigurations.of(
MongockConfiguration.class,
CouchbaseSpringbootContext.class))
.run(context -> {
assertThat(context).hasSingleBean(ConnectionDriver.class);
CouchbaseDriver driver = context.getBean(CouchbaseDriver.class);
assertThat(collectionName(driver)).isEqualTo(NONE_DEFAULT_NAME);
assertThat(driver.isIndexCreation()).isTrue();
}
);
}

@Test
void test_context_index_creation_disabled() {
contextRunner
.withPropertyValues("mongock.enabled=true", "mongock.index-creation=false", "mongock.indexCreation=false")
.withBean(SimpleCouchbaseClientFactory.class, mockCluster(), "mongock", null)
.withUserConfiguration(
MongockSpringConfiguration.class,
CouchbaseSpringbootContext.class
)
.run(context -> {
assertThat(context).hasSingleBean(ConnectionDriver.class);
CouchbaseDriver driver = context.getBean(CouchbaseDriver.class);
assertThat(driver.isIndexCreation()).isFalse();
}
);
}

private String collectionName(ConnectionDriver connectionDriver) {
Collection collection = (Collection) ReflectionUtils.getPrivateField(connectionDriver, CouchbaseDriver.class, "collection");
return collection.name();
}

private Cluster mockCluster() {
Cluster cluster = mock(Cluster.class);
Bucket bucket = mock(Bucket.class);
Scope defaultScope = mock(Scope.class);
Scope customeScope = mock(Scope.class);
Collection defaultCollection = mock(Collection.class);
doReturn(CollectionIdentifier.DEFAULT_COLLECTION).when(defaultCollection).name();
Collection customCollection = mock(Collection.class);
doReturn(NONE_DEFAULT_NAME).when(customCollection).name();
doReturn(bucket).when(cluster).bucket(any());
doReturn(defaultScope).when(bucket).defaultScope();
doReturn(defaultScope).when(bucket).scope(eq(CollectionIdentifier.DEFAULT_SCOPE));
doReturn(customeScope).when(bucket).scope(eq(NONE_DEFAULT_NAME));
doReturn(defaultCollection).when(bucket).defaultCollection();
doReturn(defaultCollection).when(defaultScope).collection(any());
doReturn(customCollection).when(customeScope).collection(any());
doReturn(CollectionIdentifier.DEFAULT_SCOPE).when(defaultScope).name();
return cluster;
}

}
3 changes: 3 additions & 0 deletions spring/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -17,10 +17,13 @@
<spring-boot-3.version>[3.0.0-RC1, 4.0.0)</spring-boot-3.version>
<spring-data-4.version>4.0.0-RC1</spring-data-4.version>
<spring-data-4.mongodb.version>4.8.0-beta0</spring-data-4.mongodb.version>
<spring-data-5.couchbase.version>5.2.1</spring-data-5.couchbase.version>
<couchbase-java-client.version>3.5.1</couchbase-java-client.version>
</properties>
<modules>
<module>mongock-springboot-v3</module>
<module>mongodb-springdata-v4-driver</module>
<module>couchbase-springboot-v3-driver</module>
</modules>

<repositories>
Expand Down