Aplicativo Spring Boot com o Cloud Datastore

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

Configuração de ambiente autoguiada

Se você ainda não tem uma Conta do Google (Gmail ou Google Apps), crie uma. Faça login no Console do Google Cloud Platform (console.cloud.google.com) e crie um projeto:

Captura de tela de 2016-02-10 12:45:26.png

Lembre-se do código do projeto, um nome exclusivo em todos os projetos do Google Cloud. O nome acima já foi escolhido e não servirá para você. Faremos referência a ele mais adiante neste codelab como PROJECT_ID.

Em seguida, ative o faturamento no console do Cloud para usar os recursos do Google Cloud.

A execução por meio deste codelab terá um custo baixo, mas poderá ser mais se você decidir usar mais recursos ou se deixá-los em execução. Consulte a seção "limpeza" no final deste documento.

Novos usuários do Google Cloud Platform têm direito a uma avaliação sem custo financeiro de US$300.

Ativar o Google Cloud Shell

No Console do GCP, clique no ícone do Cloud Shell na barra de ferramentas localizada no canto superior direito:

Em seguida, clique em "Start Cloud Shell":

O provisionamento e a conexão ao ambiente levarão apenas alguns instantes para serem concluídos:

Essa máquina virtual contém 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. Praticamente todo o seu trabalho neste laboratório pode ser feito em um navegador ou no seu Google Chromebook.

Depois de se conectar ao Cloud Shell, sua conta já estará autenticada e o projeto estará configurado com seu PROJECT_ID.

Execute o seguinte comando no Cloud Shell para confirmar se a conta está autenticada:

gcloud auth list

Resposta ao comando

Credentialed accounts:
 - <myaccount>@<mydomain>.com (active)
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].

No console do GCP, acesse Menu -> Datastore (na seção "Storage").

Se você nunca usou o Datastore no projeto atual, a tela Selecionar um modo do Cloud Firestore vai aparecer. Selecione a opção Modo Datastore.

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

No ambiente do Cloud Shell, use o comando a seguir para inicializar e fazer o bootstrap de um novo aplicativo 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 -

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

Nosso aplicativo vai fornecer uma CLI para que os usuários insiram comandos e vejam os resultados. Vamos criar uma classe para representar um livro e salvá-la no Cloud Datastore usando o repositório do Datastore.

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

Abra o editor de código da Web clicando em Iniciar editor de código no menu do Cloud Shell.

Depois que o editor for carregado, modifique o arquivo pom.xml para adicionar a dependência do Spring Data Cloud Datastore Spring Boot Starter:

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>

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 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 você pode ver, este é um POJO simples. A classe é anotada com @Entity para indicar que pode ser armazenada no Datastore e fornecer 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, ele será gerado com base no nome da classe.

A propriedade id foi anotada com @Id. Isso indica que queremos que esse campo seja usado como a parte identificadora 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 de string dos objetos mais legível. Isso será útil quando os imprimirmos.

Não se esqueça de salvar o arquivo.

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

}

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 no nosso repositório, para os quais as implementações são geradas automaticamente em segundo plano.

O primeiro é findByAuthor. Como você pode imaginar, a implementação desse método vai executar uma consulta que usa um valor fornecido pelo usuário no filtro de condição para igualdade ao campo "autor".

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

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

Abra a classe principal do aplicativo DemoApplication 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 adicionamos a anotação @ShellComponent à classe. 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 nosso aplicativo.

Aqui usamos os métodos declarados na interface BookRepository: findByAuthor, findByYearGreaterThan, findByAuthorAndYear. Também usamos três métodos integrados: save, findAll e deleteAll.

Vamos analisar o método saveBook . Criamos um objeto Book usando valores fornecidos pelo usuário para título, autor e ano. Como você pode ver, 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. Ele retorna um objeto Book com todos os campos preenchidos, incluindo o campo id. No final, retornamos uma representação em string desse objeto.

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

Para criar e iniciar o aplicativo, execute este comando no Cloud Shell (na raiz do projeto datastore-example/ em que o pom.xml está localizado) :

$ mvn spring-boot:run

Após uma etapa de build bem-sucedida, o logotipo do Spring vai aparecer, e o prompt do shell será exibido:

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


shell:> 

Agora você pode testar os comandos que definimos antes. Para conferir 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 de um autor e ano específicos (find-by-author-year <author> <year>)

Para ver como as entidades são armazenadas no Cloud Datastore, acesse o console do GCP e navegue até Menu -> Datastore (na seção "Armazenamento") -> Entidades. Selecione o namespace "[default]" e o tipo "books", se necessário.

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 "quit" e pressione Ctrl+C.

Neste codelab, você criou um aplicativo interativo de CLI 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.