App 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ê aprenderá

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

Pré-requisitos

  • 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 personalizada

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 novo projeto:

Captura de tela de 10/02/2016 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, você precisará ativar 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 estão qualificados para um teste sem custo financeiro de US$ 300.

Ativa 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 que você se conectar ao Cloud Shell, sua autenticação já terá sido feita, e o projeto estará definido 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, faça a configuração usando este comando:

gcloud config set project <PROJECT_ID>

Resposta ao comando

Updated property [core/project].

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

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

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

No ambiente do Cloud Shell, use o seguinte comando para inicializar e inicializar 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 criará um novo diretório datastore-example/ com um novo projeto Maven, junto com o pom.xml do Maven, um wrapper Maven e um ponto de entrada do aplicativo.

Nosso aplicativo fornecerá uma CLI para que os usuários digitem comandos e vejam resultados. Vamos criar uma classe para representar um livro e, em seguida, 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 Launch code editor no menu do Cloud Shell.

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

pom.xml (link em inglês)

<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 podemos 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 ele 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 repositório de dados. Toda entidade do Datastore precisa de um identificador. Os tipos compatíveis 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 as 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.

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ção para a igualdade de campo para autor.

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

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

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

datastore-example/src/main/java/com/example/demo/DemoApplication.java (link em inglês)

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 origem 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 que declaramos na interface do 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, então ele será automaticamente alocado e atribuído 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. No final, retornamos uma representação da 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 string.

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

$ mvn spring-boot:run

Após a conclusão do estágio de criação, o logotipo da spring será exibido e o prompt do shell será exibido:

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


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. Fazer 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 o ano específico (find-by-year-after <year>)
  5. Encontrar livros por 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 "Storage") -> Entidades (selecione "[padrão]" namespace e "livros" se necessário.

Para fazer a limpeza, remova todos os livros usando o comando adequadamente chamado remove-all-books do shell do aplicativo.

shell:> remove-all-books

Para sair do aplicativo, use o comando "quit" e, em seguida, Ctrl+C.

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