Skip to content

Commit

Permalink
feat(main): Migrate spanner spring data r2dbc (#2080)
Browse files Browse the repository at this point in the history
  • Loading branch information
prash-mi authored Jul 28, 2023
1 parent 81d6f98 commit f5e3c7a
Show file tree
Hide file tree
Showing 36 changed files with 2,588 additions and 1 deletion.
2 changes: 2 additions & 0 deletions docs/src/main/asciidoc/index.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,8 @@ include::metrics.adoc[]

include::spanner.adoc[]

include::spanner-spring-data-r2dbc.adoc[]

include::datastore.adoc[]

include::firestore.adoc[]
Expand Down
45 changes: 45 additions & 0 deletions docs/src/main/asciidoc/spanner-spring-data-r2dbc.adoc
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
:spring-data-commons-ref: https://docs.spring.io/spring-data/data-commons/docs/current/reference/html

[#spring-data-cloud-spanner-r2dbc]
== Cloud Spanner Spring Data R2DBC

The Spring Data R2DBC Dialect for Cloud Spanner enables the usage of https://github.com/spring-projects/spring-data-r2dbc[Spring Data R2DBC] with Cloud Spanner.

The goal of the Spring Data project is to create easy and consistent ways of using data access technologies from Spring Framework applications.

=== Setup

Maven coordinates, using <<getting-started.adoc#bill-of-materials, Spring Framework on Google Cloud BOM>>:

[source,xml]
----
<dependency>
<groupId>com.google.cloud</groupId>
<artifactId>spring-cloud-spanner-spring-data-r2dbc</artifactId>
</dependency>
----

Gradle coordinates:

[source,subs="normal"]
----
dependencies {
implementation("com.google.cloud:spring-cloud-spanner-spring-data-r2dbc")
}
----
=== Overview

Spring Data R2DBC allows you to use the convenient features of Spring Data in a reactive application.
These features include:

* Spring configuration support using Java based `@Configuration` classes.
* Annotation based mapping metadata.
* Automatic implementation of Repository interfaces.
* Support for Reactive Transactions.
* Schema and data initialization utilities.

See the https://docs.spring.io/spring-data/r2dbc/docs/current/reference/html/[Spring Data R2DBC documentation] for more information on how to use Spring Data R2DBC.

=== Sample Application

We provide a https://github.com/GoogleCloudPlatform/spring-cloud-gcp/tree/main/spring-cloud-gcp-samples/spring-cloud-spanner-r2dbc-samples[sample application] which demonstrates using the Spring Data R2DBC framework with Cloud Spanner in https://docs.spring.io/spring-framework/reference/web/webflux.html[Spring WebFlux].
3 changes: 2 additions & 1 deletion pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -456,6 +456,7 @@

<module>spring-cloud-previews</module>
<module>spring-cloud-generator</module>
<module>spring-cloud-spanner-spring-data-r2dbc</module>
<!-- Docs and Samples -->
<module>docs</module>
<module>spring-cloud-gcp-samples</module>
Expand Down Expand Up @@ -675,8 +676,8 @@
<module>spring-cloud-gcp-security-firebase</module>
<module>spring-cloud-gcp-vision</module>
<module>spring-cloud-gcp-kms</module>

<module>spring-cloud-previews</module>
<module>spring-cloud-spanner-spring-data-r2dbc</module>
</modules>
<build>
<pluginManagement>
Expand Down
12 changes: 12 additions & 0 deletions spring-cloud-gcp-dependencies/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@
<gcp-libraries-bom.version>26.19.0</gcp-libraries-bom.version>
<cloud-sql-socket-factory.version>1.13.1</cloud-sql-socket-factory.version>
<r2dbc-postgres-driver.version>1.0.2.RELEASE</r2dbc-postgres-driver.version>
<cloud-spanner-r2dbc.version>1.2.2</cloud-spanner-r2dbc.version>
</properties>

<dependencyManagement>
Expand Down Expand Up @@ -233,6 +234,11 @@
<artifactId>spring-cloud-gcp-starter-kms</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>com.google.cloud</groupId>
<artifactId>spring-cloud-spanner-spring-data-r2dbc</artifactId>
<version>${project.version}</version>
</dependency>

<!-- spring-cloud-gcp-starter-sql -->
<dependency>
Expand Down Expand Up @@ -265,6 +271,12 @@
<version>${r2dbc-postgres-driver.version}</version>
</dependency>

<dependency>
<groupId>com.google.cloud</groupId>
<artifactId>cloud-spanner-r2dbc</artifactId>
<version>${cloud-spanner-r2dbc.version}</version>
</dependency>

<!--Google Cloud Libraries BOM -->
<dependency>
<groupId>com.google.cloud</groupId>
Expand Down
1 change: 1 addition & 0 deletions spring-cloud-gcp-samples/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -84,6 +84,7 @@
<module>spring-cloud-gcp-kotlin-samples</module>
<module>spring-cloud-gcp-metrics-sample</module>
<module>spring-cloud-gcp-kms-sample</module>
<module>spring-cloud-spanner-r2dbc-samples</module>
</modules>
</profile>
<profile>
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
# Cloud Spanner Spring Data R2DBC sample

This sample creates a table called `BOOK` on application startup, and deletes it prior to application shutdown.

## Running the Sample

image:http://gstatic.com/cloudssh/images/open-btn.svg[link=https://ssh.cloud.google.com/cloudshell/editor?cloudshell_git_repo=https%3A%2F%2Fgithub.com%2FGoogleCloudPlatform%2Fcloud-spanner-r2dbc&cloudshell_open_in_editor=cloud-spanner-r2dbc-samples/cloud-spanner-spring-data-r2dbc-sample/README.adoc]


1. Run the sample from the command line, providing `spanner.instance`, `spanner.database` and `gcp.project` properties:
```
mvn spring-boot:run -Dspring-boot.run.jvmArguments="-Dspanner.instance=[SPANNER-INSTANCE] -Dspanner.database=[SPANNER-DATABASE] -Dgcp.project=GCP-PROJECT"
```

2. Visit http://localhost:8080/index.html
3. Try the different actions available
- Listing all books.
- Adding a new book with only title.
- Adding a new book with extra details (a `Map` field in `Book` entity) stored as a spanner JSON column.
- Adding a new book with a review (a custom class field in `Book` entity) stored as a spanner JSON column
- Searching for a book by its ID.
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
<?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">

<parent>
<!-- Your own application should inherit from spring-boot-starter-parent -->
<artifactId>spring-cloud-gcp-samples</artifactId>
<groupId>com.google.cloud</groupId>
<version>4.6.1-SNAPSHOT</version><!-- {x-version-update:spring-cloud-gcp:current} -->
</parent>
<modelVersion>4.0.0</modelVersion>

<artifactId>spring-cloud-spanner-r2dbc-samples</artifactId>
<name>Spring Framework on Google Cloud Code Sample - Spanner-r2dbc</name>


<dependencyManagement>
<dependencies>
<dependency>
<groupId>com.google.cloud</groupId>
<artifactId>spring-cloud-gcp-dependencies</artifactId>
<version>${project.version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
<dependencies>

<dependency>
<groupId>com.google.cloud</groupId>
<artifactId>spring-cloud-spanner-spring-data-r2dbc</artifactId>
</dependency>

<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-webflux</artifactId>
</dependency>

<!-- Test dependencies -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>io.projectreactor</groupId>
<artifactId>reactor-test</artifactId>
<scope>test</scope>
</dependency>
</dependencies>

<build>
<plugins>
<plugin>
<artifactId>maven-deploy-plugin</artifactId>
<configuration>
<skip>true</skip>
</configuration>
</plugin>
</plugins>
</build>

</project>
Original file line number Diff line number Diff line change
@@ -0,0 +1,98 @@
/*
* Copyright 2020 Google LLC
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

package com.example;

import java.util.List;
import java.util.Map;
import java.util.UUID;
import org.springframework.data.annotation.Id;
import org.springframework.data.domain.Persistable;
import org.springframework.data.relational.core.mapping.Column;
import org.springframework.data.relational.core.mapping.Table;

/** Book entity. */
@Table
public class Book implements Persistable {

@Id
@Column("ID")
private String id;

@Column("TITLE")
private String title;

@Column("EXTRADETAILS")
private Map<String, String> extraDetails;

@Column("REVIEWS")
private Review review;

@Column("CATEGORIES")
private List<String> categories;

public Book(String title, Map<String, String> extraDetails, Review review) {
this.id = UUID.randomUUID().toString();
this.title = title;
this.extraDetails = extraDetails;
this.review = review;
}

public String getId() {
return id;
}

@Override
public boolean isNew() {
return true;
}

public String getTitle() {
return this.title;
}

public Map<String, String> getExtraDetails() {
return extraDetails;
}

public Review getReview() {
return review;
}

public List<String> getCategories() {
return categories;
}

public void setCategories(List<String> categories) {
this.categories = categories;
}

@Override
public String toString() {
return "Book{"
+ "id='"
+ id
+ '\''
+ ", title='"
+ title
+ '\''
+ ", extraDetails="
+ (extraDetails == null ? "" : extraDetails.toString())
+ ", categories="
+ (categories == null ? "" : categories)
+ '}';
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
/*
* Copyright 2020 Google LLC
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

package com.example;

import org.springframework.data.repository.reactive.ReactiveCrudRepository;

/**
* Spring Data repository for books.
*
* <p>Query derivation is not supported yet.
*/
interface BookRepository extends ReactiveCrudRepository<Book, String> {}
Loading

0 comments on commit f5e3c7a

Please sign in to comment.