Aplicación Spring Boot con Cloud Datastore

Google Cloud Datastore es una base de datos de documentos NoSQL creada para proporcionar ajuste de escala automático, alto rendimiento y facilidad de desarrollo de aplicaciones.

Qué aprenderás

  • Cómo usar Cloud Datastore para guardar y recuperar objetos Java en Spring Boot

Requisitos

  • Un proyecto de Google Cloud Platform
  • Un navegador, como Chrome o Firefox

¿Cómo usarás este instructivo?

Ler Leer y completar los ejercicios

¿Cómo calificarías tu experiencia con el uso de los servicios de Google Cloud Platform?

Principiante Intermedio Avanzado

Configuración del entorno de autoaprendizaje

Si aún no tienes una Cuenta de Google (Gmail o Google Apps), debes crear una. Accede a Google Cloud Platform Console (console.cloud.google.com) y crea un proyecto nuevo:

Screenshot from 2016-02-10 12:45:26.png

Recuerde el ID de proyecto, un nombre único en todos los proyectos de Google Cloud (el nombre anterior ya se encuentra en uso y no lo podrá usar). Se mencionará más adelante en este codelab como PROJECT_ID.

A continuación, deberás habilitar la facturación en la consola de Cloud para usar los recursos de Google Cloud.

Ejecutar este codelab debería costar solo unos pocos dólares, pero su costo podría aumentar si decides usar más recursos o si los dejas en ejecución (consulta la sección “Limpiar” al final de este documento).

Los usuarios nuevos de Google Cloud Platform son aptos para obtener una prueba gratuita de USD 300.

Activa Google Cloud Shell

En GCP Console, haga clic en el ícono de Cloud Shell en la barra de herramientas superior derecha:

Haga clic en "Start Cloud Shell":

El aprovisionamiento y la conexión al entorno debería llevar solo unos minutos:

Esta máquina virtual está cargada con todas las herramientas para desarrolladores que necesitará. Ofrece un directorio principal persistente de 5 GB y se ejecuta en Google Cloud, lo que permite mejorar considerablemente el rendimiento de la red y la autenticación. Gran parte de su trabajo, si no todo, se puede hacer simplemente con un navegador o su Google Chromebook.

Una vez que te conectes a Cloud Shell, deberías ver que ya te autenticaste y que el proyecto ya se configuró con tu PROJECT_ID.

En Cloud Shell, ejecuta el siguiente comando para confirmar que tienes la autenticación:

gcloud auth list

Resultado del comando

Credentialed accounts:
 - <myaccount>@<mydomain>.com (active)
gcloud config list project

Resultado del comando

[core]
project = <PROJECT_ID>

De lo contrario, puedes configurarlo con el siguiente comando:

gcloud config set project <PROJECT_ID>

Resultado del comando

Updated property [core/project].

En GCP Console, navega a Menú -> Datastore (en la sección Storage).

Si nunca usaste Datastore en el proyecto actual, verás la pantalla "Selecciona un modo de Cloud Firestore". Selecciona la opción "Modo Datastore".

Luego, verás la pantalla "Elige dónde almacenar tus datos". Selecciona us-east1 o cualquier otra ubicación regional y haz clic en "Crear base de datos":

Desde el entorno de Cloud Shell, usa el siguiente comando para inicializar y arrancar una nueva aplicación de Spring Boot:

$ curl https://start.spring.io/starter.tgz \
  -d packaging=war \
  -d dependencies=cloud-gcp \
  -d baseDir=datastore-example \
  -d bootVersion=2.1.1.RELEASE | tar -xzvf -

Esto creará un nuevo directorio datastore-example/ con un nuevo proyecto de Maven, junto con pom.xml de Maven, un wrapper de Maven y un punto de entrada de la aplicación.

Nuestra aplicación proporcionará una CLI para que los usuarios ingresen comandos y vean los resultados. Crearemos una clase para representar un libro y, luego, la guardaremos en Cloud Datastore con Datastore Repository.

También debemos agregar una dependencia más necesaria a pom.xml.

Haz clic en Iniciar editor de código en el menú de Cloud Shell para abrir el editor de código web.

Después de que se cargue el editor, modifica el archivo pom.xml para agregar la dependencia del iniciador de Spring Boot de Spring Data Cloud Datastore:

pom.xml

<project>
  ...
  <dependencies>
        ...
        <!-- Add GCP Datastore Starter -->
        <dependency>
                <groupId>org.springframework.cloud</groupId>          
                <artifactId>spring-cloud-gcp-starter-data-datastore</artifactId>
        </dependency>

        <!-- Add Spring Shell Starter -->
        <dependency>
                <groupId>org.springframework.shell</groupId>
                <artifactId>spring-shell-starter</artifactId>
                <version>2.0.0.RELEASE</version>
        </dependency>

  </dependencies>
</project>

Con el editor, crea la clase Book con el siguiente contenido:

datastore-example/src/main/java/com/example/demo/Book.java

package com.example.demo;

import org.springframework.cloud.gcp.data.datastore.core.mapping.Entity;
import org.springframework.data.annotation.Id;


@Entity(name = "books")
public class Book {
        @Id
        Long id;

        String title;

        String author;

        int year;

        public Book(String title, String author, int year) {
                this.title = title;
                this.author = author;
                this.year = year;
        }

        public long getId() {
                return this.id;
        }

        @Override
        public String toString() {
                return "Book{" +
                                "id=" + this.id +
                                ", title='" + this.title + '\'' +
                                ", author='" + this.author + '\'' +
                                ", year=" + this.year +
                                '}';
        }
}

Como puedes ver, este es un POJO simple. La clase se anota con @Entity para indicar que se puede almacenar en Datastore y proporcionar el nombre del tipo (piensa en un tipo como una tabla en las bases de datos SQL; consulta la documentación para obtener más detalles). El nombre del tipo es opcional. Si se omite, se generará en función del nombre de la clase.

Ten en cuenta que anotamos la propiedad id con @Id. Esto indica que queremos que este campo se use como la parte del identificador de la clave de Datastore. Cada entidad de Datastore necesita un identificador. Los tipos admitidos son String y Long.

Anulamos el método toString para que la representación de cadena de los objetos sea más legible, lo que será útil cuando los imprimamos.

No olvides guardar el archivo.

Crea la clase BookRepository con el siguiente contenido:

datastore-example/src/main/java/com/example/demo/BookRepository.java

package com.example.demo;

import java.util.List;

import org.springframework.cloud.gcp.data.datastore.repository.DatastoreRepository;


public interface BookRepository extends DatastoreRepository<Book, Long> {

  List<Book> findByAuthor(String author);

  List<Book> findByYearGreaterThan(int year);

  List<Book> findByAuthorAndYear(String author, int year);

}

La interfaz extiende DatastoreRepository<Book, Long> , donde Book es la clase de dominio y Long es el tipo Id. Declaramos tres métodos de consulta en nuestro repositorio para los que se generan implementaciones automáticamente en segundo plano.

El primero es findByAuthor. Como puedes suponer, la implementación de este método ejecutará una consulta que usará un valor proporcionado por el usuario en el filtro de condición para la igualdad con el campo de autor.

El método findByYearGreaterThan ejecuta una consulta que filtra el campo de año para que sea mayor que el valor proporcionado por el usuario.

findByAuthorAndYear ejecuta una búsqueda de entidades en la que los campos de autor y año coinciden con los valores proporcionados por el usuario.

Abre la clase DemoApplication de la aplicación principal y modifícala para que se vea de la siguiente manera:

datastore-example/src/main/java/com/example/demo/DemoApplication.java

package com.example.demo;

import java.util.List;

import com.google.common.collect.Lists;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.shell.standard.ShellComponent;
import org.springframework.shell.standard.ShellMethod;

@ShellComponent
@SpringBootApplication
public class DemoApplication {
  @Autowired
  BookRepository bookRepository;

  public static void main(String[] args) {
     SpringApplication.run(DemoApplication.class, args);
  }

  @ShellMethod("Saves a book to Cloud Datastore: save-book <title> <author> <year>")
  public String saveBook(String title, String author, int year) {
     Book savedBook = this.bookRepository.save(new Book(title, author, year));
     return savedBook.toString();
  }

  @ShellMethod("Loads all books")
  public String findAllBooks() {
     Iterable<Book> books = this.bookRepository.findAll();
     return Lists.newArrayList(books).toString();
  }

  @ShellMethod("Loads books by author: find-by-author <author>")
  public String findByAuthor(String author) {
     List<Book> books = this.bookRepository.findByAuthor(author);
     return books.toString();
  }

  @ShellMethod("Loads books published after a given year: find-by-year-after <year>")
  public String findByYearAfter(int year) {
     List<Book> books = this.bookRepository.findByYearGreaterThan(year);
     return books.toString();
  }

  @ShellMethod("Loads books by author and year: find-by-author-year <author> <year>")
  public String findByAuthorYear(String author, int year) {
     List<Book> books = this.bookRepository.findByAuthorAndYear(author, year);
     return books.toString();
  }

  @ShellMethod("Removes all books")
  public void removeAllBooks() {
     this.bookRepository.deleteAll();
  }
}

Observa cómo anotamos la clase con @ShellComponent. Esto le informa a Spring que queremos usar esta clase como fuente para los comandos de la CLI. Los métodos anotados con @ShellMethod se expondrán como comandos de CLI en nuestra aplicación.

Aquí usamos los métodos que declaramos en la interfaz BookRepository: findByAuthor, findByYearGreaterThan y findByAuthorAndYear. También usamos tres métodos integrados: save, findAll y deleteAll.

Veamos el método saveBook . Creamos un objeto Book con los valores proporcionados por el usuario para el título, el autor y el año. Como puedes ver, no proporcionamos un valor de id, por lo que se asignará automáticamente y se asignará al campo id cuando se guarde. El método save acepta un objeto de tipo Book y lo guarda en Cloud Datastore. Devuelve un objeto Book con todos los campos completados, incluido el campo id. Al final, devolvemos una representación de cadena de este objeto.

El resto de los métodos funcionan de manera similar: aceptan parámetros pasados a los métodos de repositorio apropiados y devuelven resultados convertidos en cadenas.

Para compilar y ejecutar la aplicación, ejecuta este comando en Cloud Shell (desde la raíz del proyecto datastore-example/ donde se encuentra el archivo pom.xml) :

$ mvn spring-boot:run

Después de una etapa de compilación exitosa, aparecerá el logotipo de Spring y el símbolo del sistema de shell:

 .   ____          _            __ _ _
 /\\ / ___'_ __ _ _(_)_ __  __ _ \ \ \ \
( ( )\___ | '_ | '_| | '_ \/ _` | \ \ \ \
 \\/  ___)| |_)| | | | | || (_| |  ) ) ) )
  '  |____| .__|_| |_|_| |_\__, | / / / /
 =========|_|==============|___/=/_/_/_/
 :: Spring Boot ::        (v2.1.1.RELEASE)


shell:> 

Ahora puedes experimentar con los comandos que definimos anteriormente. Para ver la lista de comandos, usa el comando de ayuda:

shell:> help
...
find-all-books: Loads all books
find-by-author: Loads books by author: find-by-author <author>
find-by-author-year: Loads books by author and year: find-by-author-year <author> <year>
find-by-year-after: Loads books published after a given year: find-by-year-after <year>
remove-all-books: Removes all books
save-book: Saves a book to Cloud Datastore: save-book <title> <author> <year>

Prueba lo siguiente:

  1. Crea algunos libros con el comando save-book .
  2. Ejecuta una búsqueda con el comando find-all-books .
  3. Buscar libros de un autor específico (find-by-author <author>)
  4. Busca libros publicados después de un año específico (find-by-year-after <year>).
  5. Buscar libros por autor y año específicos (find-by-author-year <author> <year>)

Para ver cómo se almacenan las entidades en Cloud Datastore, ve a GCP Console y navega a Menú -> Datastore (en la sección Almacenamiento) -> Entidades (selecciona el espacio de nombres "[default]" y el tipo "books", si es necesario).

Para limpiar, quita todos los libros con el comando remove-all-books de la shell de la aplicación, que tiene un nombre adecuado.

shell:> remove-all-books

Para salir de la aplicación, usa el comando quit y, luego, Ctrl + C.

En este codelab, creaste una aplicación interactiva de CLI que puede almacenar y recuperar objetos de Cloud Datastore.

Más información

Licencia

Este trabajo cuenta con una licencia Atribución 2.0 Genérica de Creative Commons.