Skip to content

Commit

Permalink
Added couchbase spring boot 3 driver (#9)
Browse files Browse the repository at this point in the history
  • Loading branch information
babltiga committed Jan 10, 2024
1 parent 4661bf8 commit df4f0ae
Show file tree
Hide file tree
Showing 6 changed files with 312 additions and 0 deletions.
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

0 comments on commit df4f0ae

Please sign in to comment.