Skip to content

A Spring starter for oracle nosql #122

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

Merged
merged 2 commits into from
Sep 18, 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.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions spring-cloud-oci/docs/src/main/asciidoc/index.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,8 @@ include::storage.adoc[]

include::notifications.adoc[]

include::nosql.adoc[]

include::queues.adoc[]

include::streaming.adoc[]
Expand Down
97 changes: 97 additions & 0 deletions spring-cloud-oci/docs/src/main/asciidoc/nosql.adoc
Original file line number Diff line number Diff line change
@@ -0,0 +1,97 @@
// Copyright (c) 2024, Oracle and/or its affiliates.
// Licensed under the Universal Permissive License v 1.0 as shown at https://oss.oracle.com/licenses/upl/

[#oci-nosql]
== Oracle NoSQL Database

https://docs.oracle.com/en-us/iaas/nosql-database/index.html[Oracle NoSQL Database] service offering on-demand throughput and storage based provisioning that supports JSON, Table and Key-Value datatypes, all with flexible transaction guarantees.

Maven coordinates:

[source,xml]
----
<dependency>
<groupId>com.oracle.cloud.spring</groupId>
<artifactId>spring-cloud-oci-starter-nosql</artifactId>
</dependency>
----

Gradle coordinates:

[source,subs="normal"]
----
dependencies {
implementation("com.oracle.cloud.spring:spring-cloud-oci-starter-nosql")
}
----

=== Using Oracle NoSQL Database

The starter automatically configures and registers a `NosqlDBConfig` bean in the Spring application, allowing the use of Oracle NoSQL Database repositories.

[source,yaml]
----
spring:
cloud:
oci:
config:
type: file
region:
static: us-ashburn-1
----

Enable NoSQL repositories in your application by using the `@EnableNosqlRepositories` annotation and extending the `AbstractNosqlConfiguration` class.

[source,java]
----
import com.oracle.nosql.spring.data.config.AbstractNosqlConfiguration;
import com.oracle.nosql.spring.data.repository.config.EnableNosqlRepositories;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

@SpringBootApplication
@EnableNosqlRepositories
public class MyApp extends AbstractNosqlConfiguration {
public static void main(String[] args) {
SpringApplication.run(MyApp.class, args);
}
}
----

NoSQL repositories and tables are simply defined by extending the `NosqlRepository` interface and applying the `@NosqlTable` annotation:

[source,java]
----
public interface BookRepository extends NosqlRepository<Book, Long> {
// Add repository methods as needed.
Iterable<Book> findByAuthor(String author);
Iterable<Book> findByTitle(String title);
}
----

[source,java]
----
@NosqlTable(tableName = "books")
public class Book {
@NosqlId(generated = true)
long id;
String title;
String author;
double price;
}
----


=== Configuration

The Spring Boot Starter for Oracle Cloud NoSQL Database provides the following configuration options:

|===
^| Name ^| Description ^| Required ^| Default value
| `spring.cloud.oci.nosql.enabled` | Enables the NoSQL DB Config. | No | `true`
|===


=== Sample

A sample application provided https://github.com/oracle/spring-cloud-oracle/tree/main/spring-cloud-oci/spring-cloud-oci-samples/spring-cloud-oci-nosql-sample[here] contains the examples to demonstrates the usage of OCI Spring Cloud NoSQL module.
42 changes: 42 additions & 0 deletions spring-cloud-oci/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,8 @@ Licensed under the Universal Permissive License v 1.0 as shown at https://oss.or
<spring-cloud-oci-dependencies.version>${project.version}</spring-cloud-oci-dependencies.version>
<spring-cloud-dependencies.version>2023.0.2</spring-cloud-dependencies.version>
<spring-framework.version>6.1.10</spring-framework.version>
<spring-data-oracle-nosql.version>2.0.0</spring-data-oracle-nosql.version>
<oracle.nosql.driver.version>5.4.15</oracle.nosql.driver.version>
<jakarta-mail.version>2.0.3</jakarta-mail.version>
<oci-sdk.version>3.44.3</oci-sdk.version>
<maven.compiler.source>17</maven.compiler.source>
Expand Down Expand Up @@ -172,6 +174,46 @@ Licensed under the Universal Permissive License v 1.0 as shown at https://oss.or
<version>${spring-framework.version}</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>com.oracle.nosql.sdk</groupId>
<artifactId>spring-data-oracle-nosql</artifactId>
<version>${spring-data-oracle-nosql.version}</version>
</dependency>
<dependency>
<groupId>com.oracle.nosql.sdk</groupId>
<artifactId>nosqldriver</artifactId>
<version>${oracle.nosql.driver.version}</version>
</dependency>
<dependency>
<groupId>org.springframework.data</groupId>
<artifactId>spring-data-commons</artifactId>
<version>${spring-boot.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-core</artifactId>
<version>${spring-framework.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-tx</artifactId>
<version>${spring-framework.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-expression</artifactId>
<version>${spring-framework.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-beans</artifactId>
<version>${spring-framework.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>${spring-framework.version}</version>
</dependency>
<dependency>
<groupId>org.eclipse.angus</groupId>
<artifactId>jakarta.mail</artifactId>
Expand Down
5 changes: 5 additions & 0 deletions spring-cloud-oci/spring-cloud-oci-autoconfigure/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -100,6 +100,11 @@ Licensed under the Universal Permissive License v 1.0 as shown at https://oss.or
<artifactId>spring-cloud-oci-logging</artifactId>
<optional>true</optional>
</dependency>
<dependency>
<groupId>com.oracle.nosql.sdk</groupId>
<artifactId>spring-data-oracle-nosql</artifactId>
<optional>true</optional>
</dependency>
<dependency>
<groupId>com.oracle.cloud.spring</groupId>
<artifactId>spring-cloud-oci-function</artifactId>
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
/*
** Copyright (c) 2024, Oracle and/or its affiliates.
** Licensed under the Universal Permissive License v 1.0 as shown at https://oss.oracle.com/licenses/upl/
*/
package com.oracle.cloud.spring.nosql;

import java.io.IOException;

import com.oracle.bmc.auth.RegionProvider;
import com.oracle.cloud.spring.autoconfigure.core.CredentialsProperties;
import com.oracle.nosql.spring.data.config.NosqlDbConfig;
import oracle.nosql.driver.iam.SignatureProvider;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.boot.autoconfigure.AutoConfiguration;
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.cloud.context.config.annotation.RefreshScope;
import org.springframework.context.annotation.Bean;

import static com.oracle.cloud.spring.autoconfigure.core.RegionProviderAutoConfiguration.regionProviderQualifier;

@AutoConfiguration
@ConditionalOnClass(NosqlDbConfig.class)
@ConditionalOnProperty(name = "spring.cloud.oci.nosql.enabled", havingValue = "true", matchIfMissing = true)
public class NoSQLAutoConfiguration {
@Bean
@RefreshScope
@ConditionalOnMissingBean
public NosqlDbConfig nosqlDbConfig(@Qualifier(regionProviderQualifier) RegionProvider regionProvider,
CredentialsProperties properties) throws IOException {
String profile = properties.hasProfile() ? properties.getProfile() : "DEFAULT";
SignatureProvider signatureProvider;
switch (properties.getType()) {
case WORKLOAD_IDENTITY -> signatureProvider = SignatureProvider.createWithOkeWorkloadIdentity();
case RESOURCE_PRINCIPAL -> signatureProvider = SignatureProvider.createWithResourcePrincipal();
case INSTANCE_PRINCIPAL ->
signatureProvider = SignatureProvider.createWithInstancePrincipal();
case SIMPLE -> signatureProvider = new SignatureProvider(
properties.getTenantId(),
properties.getUserId(),
properties.getFingerprint(),
properties.getPrivateKey(),
properties.getPassPhrase() != null ? properties.getPassPhrase().toCharArray() : null
);
case SESSION_TOKEN -> {
if (properties.hasFile()) {
signatureProvider = SignatureProvider.createWithSessionToken(properties.getFile(), profile);
} else {
signatureProvider = SignatureProvider.createWithSessionToken(profile);
}
}
default -> {
if (properties.hasFile()) {
signatureProvider = new SignatureProvider(properties.getFile(), profile);
} else {
signatureProvider = new SignatureProvider(profile);
}

}
}
return new NosqlDbConfig(regionProvider.getRegion().getRegionId(), signatureProvider);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,12 @@
"type": "java.lang.Boolean",
"description": "Auto-configure OCI Autonomous Database components.",
"defaultValue": true
},
{
"name": "spring.cloud.oci.nosql.enabled",
"type": "java.lang.Boolean",
"description": "Auto-configure Oracle NoSQL Database components.",
"defaultValue": true
}
]
}
Original file line number Diff line number Diff line change
Expand Up @@ -11,3 +11,4 @@ com.oracle.cloud.spring.genai.GenAIAutoConfiguration
com.oracle.cloud.spring.vault.VaultAutoConfiguration
com.oracle.cloud.spring.adb.AutonomousDbAutoConfiguration
com.oracle.cloud.spring.email.EmailDeliveryAutoConfiguration
com.oracle.cloud.spring.nosql.NoSQLAutoConfiguration
Original file line number Diff line number Diff line change
Expand Up @@ -8,16 +8,24 @@
import com.oracle.bmc.Region;
import com.oracle.bmc.auth.BasicAuthenticationDetailsProvider;
import com.oracle.bmc.auth.RegionProvider;
import com.oracle.cloud.spring.autoconfigure.core.CredentialsProperties;
import com.oracle.cloud.spring.core.compartment.CompartmentProvider;
import com.oracle.cloud.spring.core.compartment.StaticCompartmentProvider;
import com.oracle.cloud.spring.core.region.StaticRegionProvider;
import org.springframework.boot.test.context.assertj.AssertableApplicationContext;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

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

@Configuration
public class TestCommonConfigurationBeans {
@Bean
CredentialsProperties credentialsProperties() {
return new CredentialsProperties();
}

@Bean
BasicAuthenticationDetailsProvider credentialsProvider() {
return mock(BasicAuthenticationDetailsProvider.class);
Expand All @@ -33,4 +41,17 @@ CompartmentProvider compartmentProvider() {
return new StaticCompartmentProvider("compartmentOCID");
}

public static void assertBeanLoaded(AssertableApplicationContext ctx, Class<?> clazz) {
assertBeanLoaded(ctx, clazz, true);
}

public static void assertBeanNotLoaded(AssertableApplicationContext ctx, Class<?> clazz) {
assertBeanLoaded(ctx, clazz, false);
}

static void assertBeanLoaded(AssertableApplicationContext ctx, Class<?> clazz, boolean loaded) {
String[] beans = ctx.getBeanNamesForType(clazz);
assertThat(beans).hasSize(loaded ? 2 : 0);
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
// Copyright (c) 2024, Oracle and/or its affiliates.
// Licensed under the Universal Permissive License v 1.0 as shown at https://oss.oracle.com/licenses/upl/
package com.oracle.cloud.spring.nosql;

import com.oracle.cloud.spring.autoconfigure.TestCommonConfigurationBeans;
import com.oracle.nosql.spring.data.config.NosqlDbConfig;
import org.junit.jupiter.api.Test;
import org.springframework.boot.autoconfigure.AutoConfigurations;
import org.springframework.boot.test.context.runner.ApplicationContextRunner;

import static com.oracle.cloud.spring.autoconfigure.TestCommonConfigurationBeans.assertBeanLoaded;
import static com.oracle.cloud.spring.autoconfigure.TestCommonConfigurationBeans.assertBeanNotLoaded;

public class NoSQLAutoConfigurationTests {
private final ApplicationContextRunner contextRunner = new ApplicationContextRunner()
.withPropertyValues("spring.cloud.oci.nosql.enabled=true")
.withConfiguration(AutoConfigurations.of(NoSQLAutoConfiguration.class))
.withUserConfiguration(TestCommonConfigurationBeans.class);

@Test
void beansAreLoaded() {
contextRunner.run(ctx -> assertBeanLoaded(ctx, NosqlDbConfig.class));
}

@Test
void beansAreNotLoadedWhenDisabled() {
contextRunner.withPropertyValues("spring.cloud.oci.nosql.enabled=false")
.run(ctx -> assertBeanNotLoaded(ctx, NosqlDbConfig.class));
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -5,10 +5,10 @@
import com.oracle.cloud.spring.autoconfigure.TestCommonConfigurationBeans;
import org.junit.jupiter.api.Test;
import org.springframework.boot.autoconfigure.AutoConfigurations;
import org.springframework.boot.test.context.assertj.AssertableApplicationContext;
import org.springframework.boot.test.context.runner.ApplicationContextRunner;

import static org.assertj.core.api.Assertions.assertThat;
import static com.oracle.cloud.spring.autoconfigure.TestCommonConfigurationBeans.assertBeanLoaded;
import static com.oracle.cloud.spring.autoconfigure.TestCommonConfigurationBeans.assertBeanNotLoaded;

public class VaultAutoConfigurationTests {
private final String vaultIdProperty = "spring.cloud.oci.vault.vault-id=xyz";
Expand All @@ -22,23 +22,18 @@ public class VaultAutoConfigurationTests {
@Test
void beansAreLoaded() {
contextRunner.withPropertyValues(vaultIdProperty)
.run(ctx -> assertVaultTemplateBean(ctx, true));
.run(ctx -> assertBeanLoaded(ctx, VaultTemplate.class));
}

@Test
void beansAreNotLoadedWhenDisabled() {
contextRunner.withPropertyValues(vaultIdProperty,
"spring.cloud.oci.vault.enabled=false")
.run(ctx -> assertVaultTemplateBean(ctx, false));
.run(ctx -> assertBeanNotLoaded(ctx, VaultTemplate.class));
}

@Test
void beansAreNotLoadedWhenNoVault() {
contextRunner.run(ctx -> assertVaultTemplateBean(ctx, false));
}

private void assertVaultTemplateBean(AssertableApplicationContext ctx, boolean hasBean) {
String[] beans = ctx.getBeanNamesForType(VaultTemplate.class);
assertThat(beans).hasSize(hasBean ? 2 : 0);
contextRunner.run(ctx -> assertBeanNotLoaded(ctx, VaultTemplate.class));
}
}
5 changes: 5 additions & 0 deletions spring-cloud-oci/spring-cloud-oci-dependencies/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -157,6 +157,11 @@
<artifactId>spring-cloud-oci-starter-email</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>com.oracle.cloud.spring</groupId>
<artifactId>spring-cloud-oci-starter-nosql</artifactId>
<version>${project.version}</version>
</dependency>
</dependencies>
</dependencyManagement>

Expand Down
1 change: 1 addition & 0 deletions spring-cloud-oci/spring-cloud-oci-samples/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,7 @@ Licensed under the Universal Permissive License v 1.0 as shown at https://oss.or
<module>spring-cloud-oci-function-sample</module>
<module>spring-cloud-oci-adb-sample</module>
<module>spring-cloud-oci-email-sample</module>
<module>spring-cloud-oci-nosql-sample</module>
</modules>

<artifactId>spring-cloud-oci-samples</artifactId>
Expand Down
Loading
Loading