Aplicativo Spring Boot com o Cloud Datastore

1. Visão geral

O Google Cloud Datastore é um banco de dados de documentos NoSQL criado para oferecer escalonamento automático, alto desempenho e facilidade no desenvolvimento de aplicativos.

O que você vai aprender

  • Como usar o Cloud Datastore para salvar e recuperar objetos Java no Spring Boot

O que é necessário

  • Um projeto do Google Cloud Platform
  • Um navegador, como o Chrome ou o Firefox

Como você usará este tutorial?

Apenas leitura Leitura e exercícios

Como você classificaria sua experiência com o uso dos serviços do Google Cloud Platform?

Iniciante Intermediário Proficiente

2. Configuração e requisitos

Configuração de ambiente autoguiada

  1. Faça login no Console do Google Cloud e crie um novo projeto ou reutilize um existente. Crie uma conta do Gmail ou do Google Workspace, se ainda não tiver uma.

b35bf95b8bf3d5d8.png

a99b7ace416376c4.png

bd84a6d3004737c5.png

  • O Nome do projeto é o nome de exibição para os participantes do projeto. É uma string de caracteres não usada pelas APIs do Google e pode ser atualizada quando você quiser.
  • O ID do projeto precisa ser exclusivo em todos os projetos do Google Cloud e não pode ser mudado após a definição. O console do Cloud gera automaticamente uma string exclusiva. Em geral, não importa o que seja. Na maioria dos codelabs, é necessário fazer referência ao ID do projeto, normalmente identificado como PROJECT_ID. Se você não gostar do ID gerado, crie outro aleatório. Se preferir, teste o seu e confira se ele está disponível. Ele não pode ser mudado após essa etapa e permanece durante o projeto.
  • Para sua informação, há um terceiro valor, um Número do projeto, que algumas APIs usam. Saiba mais sobre esses três valores na documentação.
  1. Em seguida, ative o faturamento no console do Cloud para usar os recursos/APIs do Cloud. A execução deste codelab não vai ser muito cara, se tiver algum custo. Para encerrar os recursos e evitar cobranças além deste tutorial, exclua os recursos criados ou exclua o projeto. Novos usuários do Google Cloud estão qualificados para o programa de US$ 300 de avaliação sem custos.

Ativar o Cloud Shell

  1. No Console do Cloud, clique em Ativar o Cloud Shell853e55310c205094.png.

55efc1aaa7a4d3ad.png

Se você estiver iniciando o Cloud Shell pela primeira vez, verá uma tela intermediária com a descrição dele. Se aparecer uma tela intermediária, clique em Continuar.

9c92662c6a846a5c.png

Leva apenas alguns instantes para provisionar e se conectar ao Cloud Shell.

9f0e51b578fecce5.png

Essa máquina virtual tem todas as ferramentas de desenvolvimento necessárias. Ela oferece um diretório principal persistente de 5 GB, além de ser executada no Google Cloud. Isso aprimora o desempenho e a autenticação da rede. Grande parte do trabalho neste codelab, se não todo, pode ser feito em um navegador.

Depois de se conectar ao Cloud Shell, você verá sua autenticação e o projeto estará configurado com o ID do seu projeto.

  1. Execute o seguinte comando no Cloud Shell para confirmar se a conta está autenticada:
gcloud auth list

Resposta ao comando

 Credentialed Accounts
ACTIVE  ACCOUNT
*       <my_account>@<my_domain.com>

To set the active account, run:
    $ gcloud config set account `ACCOUNT`
  1. Execute o seguinte comando no Cloud Shell para confirmar que o comando gcloud sabe sobre seu projeto:
gcloud config list project

Resposta ao comando

[core]
project = <PROJECT_ID>

Se o projeto não estiver configurado, configure-o usando este comando:

gcloud config set project <PROJECT_ID>

Resposta ao comando

Updated property [core/project].

3. inicializará o Cloud Datastore;

No Console do GCP, navegue até Menu -> Datastore (na seção "Armazenamento") ou clique aqui.

Se você nunca usou o Datastore no projeto atual, verá a tela Selecione um modo do Cloud Firestore. Selecione a opção "Datastore mode".

f938295c7ff297f4.png

Depois disso, a tela Escolha onde armazenar seus dados vai aparecer. Selecione us-east1 ou qualquer outro local regional e clique em "Criar banco de dados":

916ac84fec10fae7.png

4. Inicializar um novo aplicativo Java do Spring Boot

No ambiente do Cloud Shell, use o seguinte comando para inicializar um novo aplicativo Spring Boot:

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

Isso vai criar um novo diretório datastore-example/ com um novo projeto Maven, junto com o pom.xml do Maven, um wrapper do Maven e um ponto de entrada do aplicativo.

Nosso aplicativo fornece uma CLI para os usuários inserirem comandos e verem resultados. Criaremos uma classe para representar um livro e o salvaremos no Cloud Datastore usando o repositório do Datastore.

Também precisamos adicionar mais uma dependência necessária ao pom.xml.

Clique em Abrir editor no menu do Cloud Shell para abrir o Editor de código da Web.

6d823258c76a7452.png

Depois que o editor for carregado, modifique o arquivo pom.xml para adicionar as dependências do Google Cloud Datastore Starter e do Spring Shell Starter:

pom.xml

<project>
  ...
  <dependencies>
        ...
        <!-- Add GCP Datastore Starter -->
        <dependency>
                <groupId>com.google.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>3.0.2</version>
        </dependency>

  </dependencies>
</project>

5. Criar a classe Book

Usando o editor, crie a classe Book com o seguinte conteúdo:

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

package com.example.demo;

import com.google.cloud.spring.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 você pode ver, este é um POJO simples. A classe é anotada com @Entity para indicar que pode ser armazenada no Datastore e fornece o nome do tipo. Pense em um tipo como uma tabela em bancos de dados SQL. Consulte a documentação para mais detalhes. O nome do tipo é opcional. Se for omitido, o nome do tipo será gerado com base no nome da classe.

Anotamos a propriedade id com @Id. Isso indica que queremos que esse campo seja usado como parte do identificador da chave do Datastore. Toda entidade do Datastore precisa de um identificador. Os tipos aceitos são String e Long.

Substituímos o método toString para tornar a representação da string dos objetos mais legível. isso será útil quando os imprimirmos.

6. Criar a interface BookRepository

Crie a classe BookRepository com o seguinte conteúdo:

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

package com.example.demo;

import java.util.List;

import com.google.cloud.spring.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);
}

A interface estende DatastoreRepository<Book, Long>, em que Book é a classe de domínio e Long é o tipo Id. Declaramos três métodos de consulta em nosso repositório para os quais as implementações são geradas automaticamente em segundo plano.

A primeira é findByAuthor. Como você pode imaginar, a implementação desse método executará uma consulta que usará um valor fornecido pelo usuário no filtro de condições para o campo de igualdade com o autor.

O método findByYearGreaterThan executa uma consulta que filtra o campo do ano maior que o valor fornecido pelo usuário.

findByAuthorAndYear executa uma consulta que procura entidades em que os campos de autor e ano correspondem aos valores fornecidos pelo usuário.

7. criar o aplicativo de CLI interativo

Abra a classe DemoApplication do aplicativo principal e modifique-a para que fique assim:

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();
  }
}

Observe como anotamos a classe com @ShellComponent. Isso informa ao Spring que queremos usar essa classe como uma fonte para comandos da CLI. Os métodos anotados com @ShellMethod serão expostos como comandos da CLI no aplicativo.

Aqui, usamos os métodos que declaramos na interface BookRepository: findByAuthor, findByYearGreaterThan, findByAuthorAndYear. Além disso, usamos três métodos integrados: save, findAll e deleteAll.

Vejamos o método saveBook. Criamos um objeto Book usando valores fornecidos pelo usuário para título, autor e ano. Como você pode notar, não fornecemos um valor id. Portanto, ele será alocado e atribuído automaticamente ao campo id ao salvar. O método save aceita um objeto do tipo Book e o salva no Cloud Datastore. Ela retorna um objeto Book com todos os campos preenchidos, incluindo o campo id. Ao final, retornamos uma representação em string desse objeto.

O restante dos métodos funciona de forma semelhante: eles aceitam a transmissão de parâmetros para os métodos de repositório apropriados e retornam resultados em formato de string.

8. Execute o aplicativo

Para criar e iniciar o aplicativo, primeiro verifique se JAVA_HOME está configurado para a versão correta:

$ export JAVA_HOME=/usr/lib/jvm/java-1.17.0-openjdk-amd64

Execute este comando no Cloud Shell (da raiz do projeto datastore-example/ em que pom.xml está localizado):

$ ./mvnw spring-boot:run
export JAVA_HOME=/usr/lib/jvm/java-1.17.0-openjdk-amd64

Após a criação, o logotipo de primavera vai aparecer e o prompt de shell vai aparecer:

  .   ____          _            __ _ _
 /\\ / ___'_ __ _ _(_)_ __  __ _ \ \ \ \
( ( )\___ | '_ | '_| | '_ \/ _` | \ \ \ \
 \\/  ___)| |_)| | | | | || (_| |  ) ) ) )
  '  |____| .__|_| |_|_| |_\__, | / / / /
 =========|_|==============|___/=/_/_/_/
 :: Spring Boot ::                (v3.0.5)



shell:>

Agora você pode testar os comandos que definimos anteriormente. Para ver a lista de comandos, use o comando de ajuda:

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>

Tente o seguinte:

  1. Crie alguns livros usando o comando save-book
  2. Faça uma pesquisa usando o comando find-all-books.
  3. Encontrar livros de um autor específico: find-by-author <author>
  4. Encontrar livros publicados após um ano específico: find-by-year-after <year>
  5. Encontrar livros por autor e ano específicos: find-by-author-year <author> <year>

9. Verificar o que está armazenado no Datastore usando a interface da Web

Para ver como as entidades são armazenadas no Cloud Datastore, acesse o Console do GCP. Insira "books" no campo de tipo, se necessário.

5fab21a6c89f45a.png

10. Limpar

Para limpar, remova todos os livros usando o comando remove-all-books do shell do aplicativo.

shell:> remove-all-books

Para sair do aplicativo, use o comando de saída e, em seguida, Ctrl+C.

11. Parabéns!

Neste codelab, você criou um aplicativo de CLI interativo que pode armazenar e recuperar objetos do Cloud Datastore.

Saiba mais

Licença

Este conteúdo está sob a licença Atribuição 2.0 Genérica da Creative Commons.