Tworzenie aplikacji wiosennej Kotlin w Google Cloud Platform

1. Wprowadzenie

Platforma Spring Framework 5.0 dodała specjalną obsługę Kotlin, ułatwiając deweloperom Kotlin korzystanie z platformy Spring. W efekcie zmiany te sprawiły, że integracje z Google Cloud dostępne w ramach usługi Spring Cloud GCP również bezproblemowo działają w kotlinie. Dzięki temu ćwiczeniu w Codelabs dowiesz się, jak łatwo jest zacząć korzystać z usług Google Cloud w aplikacjach Kotlin.

Dzięki nim dowiesz się, jak skonfigurować prostą aplikację do rejestracji w Kotlin, która pokazuje korzystanie z usług GCP, takich jak Cloud Pub/Sub i Cloud SQL.

Co utworzysz

W ramach tego ćwiczenia w programie skonfigurujesz aplikację Kotlin Spring Boot, która przyjmuje informacje o abonentach, opublikujesz ją w temacie Cloud Pub/Sub i utrwala w bazie danych Cloud MySQL.

Czego się nauczysz

Integracja z usługami Google Cloud w aplikacji Kotlin Spring.

Czego potrzebujesz

  • Projekt Google Cloud Platform
  • Przeglądarka, np. Chrome lub Firefox

Jak wykorzystasz ten samouczek?

Tylko do przeczytania Przeczytaj go i wykonaj ćwiczenia

Jak oceniasz swoje doświadczenie z tworzeniem aplikacji internetowych HTML/CSS?

Początkujący Poziom średnio zaawansowany Biegły

Jak oceniasz swoje wrażenia z korzystania z usług Google Cloud Platform?

Początkujący Poziom średnio zaawansowany Biegły
.

2. Konfiguracja i wymagania

Samodzielne konfigurowanie środowiska

  1. Zaloguj się w konsoli Google Cloud i utwórz nowy projekt lub wykorzystaj już istniejący. Jeśli nie masz jeszcze konta Gmail lub G Suite, musisz je utworzyć.

dMbN6g9RawQj_VXCSYpdYncY-DbaRzr2GbnwoV7jFf1u3avxJtmGPmKpMYgiaMH-qu80a_NJ9p2IIXFppYk8x3wyymZXavjglNLJJhuXieCem56H30hwXtd8PvXGpXJO9gEUDu3cZw

ci9Oe6PgnbNuSYlMyvbXF1JdQyiHoEgnhl4PlV_MFagm2ppzhueRkqX4eLjJllZco_2zCp0V0bpTupUSKji9KkQyWqj11pqit1K1faS1V6aFxLGQdkuzGp4rsQTan7F01iePL5DtqQ

8-tA_Lheyo8SscAVKrGii2coplQp2_D1Iosb2ViABY0UUO1A8cimXUu6Wf1R9zJIRExL5OB2j946aIiFtyKTzxDcNnuznmR45vZ2HMoK3o67jxuoUJCAnqvEX6NgPGFjCVNgASc-lg

Zapamiętaj identyfikator projektu, unikalną nazwę we wszystkich projektach Google Cloud (powyższa nazwa jest już zajęta i nie będzie Ci odpowiadać). W dalszej części tego ćwiczenia w programie będzie ona określana jako PROJECT_ID.

  1. Następnie musisz włączyć płatności w Cloud Console, aby korzystać z zasobów Google Cloud.

Ukończenie tego ćwiczenia z programowania nie powinno kosztować zbyt wiele. Postępuj zgodnie z instrukcjami podanymi w sekcji „Czyszczenie” W tym samouczku znajdziesz wskazówki, jak wyłączyć zasoby, aby uniknąć naliczania opłat. Nowi użytkownicy Google Cloud mogą skorzystać z programu bezpłatnego okresu próbnego o wartości 300 USD.

Google Cloud Shell,

Google Cloud można obsługiwać zdalnie z Twojego laptopa, ale w ramach tego ćwiczenia z programowania wykorzystamy Google Cloud Shell – środowisko wiersza poleceń działające w chmurze.

Aktywowanie Cloud Shell

  1. W konsoli Cloud kliknij Aktywuj Cloud Shell H7JlbhKGHITmsxhQIcLwoe5HXZMhDlYue4K-SPszMxUxDjIeWfOHBfxDHYpmLQTzUmQ7Xx8o6OJUlANnQF0iBuUyfp1RzVad_4nCa0Zz5LtwBlUZFXFCWFrmrWZLqg1MkZz2LdgUDQ.

zlNW0HehB_AFW1qZ4AyebSQUdWm95n7TbnOr7UVm3j9dFcg6oWApJRlC0jnU1Mvb-IQp-trP1Px8xKNwt6o3pP6fyih947sEhOFI4IRF0W7WZk6hFqZDUGXQQXrw21GuMm2ecHrbzQ

Jeśli dopiero zaczynasz korzystać z Cloud Shell, wyświetli się ekran pośredni (w części strony widocznej po przewinięciu) z opisem tej funkcji. W takim przypadku kliknij Dalej (nie zobaczysz go więcej). Tak wygląda ten jednorazowy ekran:

kEPbNAo_w5C_pi9QvhFwWwky1cX8hr_xEMGWySNIoMCdi-Djx9AQRqWn-__DmEpC7vKgUtl-feTcv-wBxJ8NwzzAp7mY65-fi2LJo4twUoewT1SUjd6Y3h81RG3rKIkqhoVlFR-G7w

Uzyskanie dostępu do Cloud Shell i połączenie się z nim powinno zająć tylko kilka chwil.

pTv5mEKzWMWp5VBrg2eGcuRPv9dLInPToS-mohlrqDASyYGWnZ_SwE-MzOWHe76ZdCSmw0kgWogSJv27lrQE8pvA5OD6P1I47nz8vrAdK7yR1NseZKJvcxAZrPb8wRxoqyTpD-gbhA

Ta maszyna wirtualna ma wszystkie potrzebne narzędzia dla programistów. Zawiera stały katalog domowy o pojemności 5 GB i działa w Google Cloud, co znacznie zwiększa wydajność sieci i uwierzytelnianie. Większość czynności z tego ćwiczenia z programowania można wykonać w przeglądarce lub na Chromebooku.

Po nawiązaniu połączenia z Cloud Shell powinno pojawić się potwierdzenie, że użytkownik jest już uwierzytelniony i że projekt jest już ustawiony na identyfikator Twojego projektu.

  1. Uruchom to polecenie w Cloud Shell, aby potwierdzić, że jesteś uwierzytelniony:
gcloud auth list

Dane wyjściowe polecenia

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

To set the active account, run:
    $ gcloud config set account `ACCOUNT`
gcloud config list project

Dane wyjściowe polecenia

[core]
project = <PROJECT_ID>

Jeśli tak nie jest, możesz go ustawić za pomocą tego polecenia:

gcloud config set project <PROJECT_ID>

Dane wyjściowe polecenia

Updated property [core/project].

3. Udostępnianie zasobów Pub/Sub

Najpierw musimy skonfigurować temat i subskrypcję Cloud Pub/Sub. W tej aplikacji opublikujemy informacje rejestracyjne w temacie Pub/Sub. informacje są następnie odczytywane z tego tematu i zapisywane w bazie danych.

W tym samouczku będziemy udostępniać nasze zasoby za pomocą Cloud Shell. Pamiętaj, że zasoby Pub/Sub można też konfigurować w sekcji Cloud Pub/Sub w konsoli Google Cloud.

W terminalu Cloud Shell najpierw włącz interfejs Pub/Sub API.

$ gcloud services enable pubsub.googleapis.com

Następnie utworzymy dla tej aplikacji temat Pub/Sub o nazwie registrations. Informacje rejestracyjne przesłane za pomocą zgłoszenia zostaną opublikowane w tym temacie.

$ gcloud pubsub topics create registrations

Na koniec utwórz subskrypcję dotyczącą tego tematu. Subskrypcja Pub/Sub umożliwia odbieranie wiadomości z tematu.

$ gcloud pubsub subscriptions create registrations-sub --topic=registrations

Udało Ci się utworzyć temat i subskrypcję Cloud Pub/Sub dla Twojej aplikacji.

4. Tworzenie instancji i bazy danych Cloud SQL (MySQL)

W przypadku naszej przykładowej aplikacji musimy też skonfigurować instancję bazy danych, w której będą przechowywane informacje o abonencie. Ten krok będzie także zależał od terminala Cloud Shell do obsługi administracyjnej zasobów Cloud SQL. Pamiętaj, że instancje Cloud SQL możesz wyświetlać i konfigurować w konsoli Google Cloud.

Najpierw włącz Cloud SQL Admin API.

$ gcloud services enable sqladmin.googleapis.com

Następnie udostępnimy instancję Cloud SQL (MySQL). Wykonanie polecenia może zająć trochę czasu.

$ gcloud sql instances create codelab-instance --region=us-east1

Po utworzeniu instancji Cloud SQL utwórz w niej nową bazę danych o nazwie registrants.

$ gcloud sql databases create registrants --instance codelab-instance

Masz już za sobą konfigurowanie instancji i bazy danych Cloud SQL dla Twojej aplikacji.

5. Inicjowanie aplikacji Spring Boot

Teraz możemy zacząć pisać zgłoszenie. Kolejne kroki będą kontynuowane przy użyciu Cloud Shell opisanej w krokach konfiguracji.

Najpierw użyjemy narzędzia Initializr, aby wygenerować kod rusztowania dla projektu. W oknie Cloud Shell uruchom polecenie:

$ cd ~
$ curl https://start.spring.io/starter.tgz \
  -d language=kotlin \
  -d bootVersion=2.4.0 \
  -d dependencies=web,data-jpa,integration,cloud-gcp-pubsub,thymeleaf \
  -d baseDir=registrations-codelab | tar -xzvf -
$ cd registrations-codelab

To polecenie generuje wstępną konfigurację projektu Maven oraz kod rusztowania dla aplikacji w katalogu registrations-codelab/. W kolejnych sekcjach opisano zmiany w kodzie niezbędne do utworzenia działającej aplikacji.

Edytujący kod Cloud Shell

Najprostszym sposobem rozpoczęcia modyfikowania i wyświetlania kodu w środowisku Cloud Shell jest użycie wbudowanego edytora kodu Cloud Shell.

Po otwarciu instancji Cloud Shell kliknij ikonę ołówka, aby otworzyć edytor kodu. Edytor powinien pozwalać na bezpośrednie modyfikowanie plików projektu utworzonych przez Initialzr.

cce293b40119c37b.png

6. Konfiguracja bazy danych

Najpierw skonfiguruj aplikację tak, aby mogła łączyć się ze skonfigurowaną bazą danych Cloud MySQL. Biblioteki Spring Cloud GCP oferują pole inicjujące Cloud MySQL, które określa zależności niezbędne do nawiązania połączenia z instancją Cloud MySQL.

Dodaj zależność spring-cloud-gcp-starter-sql-mysql do pliku pom.xml projektu:

registrations-codelab/pom.xml

...
<dependencies>

  ... Other dependencies above ...

  <!-- Add the MySQL starter to the list of dependencies -->
  <dependency>
    <groupId>com.google.cloud</groupId>
    <artifactId>spring-cloud-gcp-starter-sql-mysql</artifactId>
  </dependency>
</dependencies>

Dodatkowo musisz zmodyfikować plik konfiguracji application.properties, aby opisać konfigurację bazy danych. Skopiuj te właściwości do pliku application.properties.

Znajdź nazwę połączenia instancji z bazą danych:

$ gcloud sql instances describe codelab-instance \
  --format 'value(connectionName)'

Dane wyjściowe zostaną użyte w pliku application.properties do skonfigurowania informacji o połączeniu.

src/main/resources/application.properties

# Modify this property using the output from the previous command line.
spring.cloud.gcp.sql.instance-connection-name=INSTANCE_CONNECTION_NAME

# Your database name
spring.cloud.gcp.sql.database-name=registrants

# So app starts despite "table already exists" errors.
spring.datasource.continue-on-error=true

# Enforces database initialization
spring.datasource.initialization-mode=always

# Cloud SQL (MySQL) only supports InnoDB, not MyISAM
spring.jpa.database-platform=org.hibernate.dialect.MySQL55Dialect
spring.jpa.hibernate.ddl-auto=create-drop

# This is used if you want to connect to a different database instance
# user other than root; not used in codelab.
# spring.datasource.username=root

# This is used to specify the password of the database user;
# not used in codelab.
# spring.datasource.password=password

Jedyną właściwością, którą musisz zmodyfikować, jest nazwa połączenia instancji. Ta wartość musi być sformatowana jako wartość rozdzielana dwukropkiem w formacie YOUR_GCP_PROJECT_ID:REGION:DATABASE_INSTANCE_NAME.

7. Tworzenie treści statycznej

Najpierw utworzymy frontend naszej aplikacji. Zgłoszenie powinno zawierać formularz umożliwiający rejestrację osób oraz widok z listą wszystkich zarejestrowanych użytkowników.

Dla strony głównej utwórz index.html zawierający formularz rejestracyjny.

src/main/resources/static/index.html

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <title>Registration Sample Application</title>
</head>
<body>

<h1>Registration</h1>

<div>
  <nav>
    <a href="/">Home</a><br>
    <a href="/registrants">Registered People</a><br>
  </nav>

  <p>
    This is a demo registration application which sends user information to a Pub/Sub topic and
    persists it into a MySQL database.
  </p>

  <h2>Register Person</h2>
  <div>
    <form action="/registerPerson" method="post">
      First Name: <input type="text" name="firstName" />
      Last Name: <input type="text" name="lastName" />
      Email: <input type="text" name="email" />
      <input type="submit" value="Submit"/>
    </form>
  </div>
</div>

</body>
</html>

Następnie utworzymy szablon Thymeleaf o nazwie registrants.html do wyświetlania zarejestrowanych użytkowników. Thymeleaf to struktura szablonów, z których korzystamy do tworzenia i wyświetlania dynamicznie tworzonego kodu HTML. Szablon wygląda jak HTML, ale zawiera dodatkowe elementy Markdown do obsługi zawartości dynamicznej. Ten szablon akceptuje jeden parametr o nazwie personsList, który zawiera wszystkich abonentów, którzy zostali zarejestrowani za pomocą aplikacji.

src/main/resources/templates/registrants.html

<!DOCTYPE HTML>
<html xmlns:th="http://www.thymeleaf.org">
<head>
  <title>Registrants List</title>
  <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
</head>
<body>
<h1>Registrants List</h1>
<p>
  This page displays all the people who were registered through the Pub/Sub topic.
  All results are retrieved from the MySQL database.
</p>
<table border="1">
  <tr>
    <th>First Name</th>
    <th>Last Name</th>
    <th>Email</th>
  </tr>
  <tr th:each="person : ${personsList}">
    <td>[[${person.firstName}]]</td>
    <td>[[${person.lastName}]]</td>
    <td>[[${person.email}]]</td>
  </tr>
</table>

</body>
</html>

Na tym etapie możesz sprawdzić, czy wyświetlane są treści statyczne.

Skompiluj i uruchom aplikację, korzystając z narzędzia Maven:

$ ./mvnw spring-boot:run

Kliknij przycisk podglądu w oknie Cloud Shell i sprawdź, czy widzisz renderowaną stronę główną. Żadna z funkcji interfejsu nie będzie jednak działać, ponieważ brakuje kontrolera internetowego. Zostanie ona dodana w następnym kroku.

5e38bb0d0e93002e.png

Po wyświetleniu podglądu aplikacji naciśnij CTRL+C, aby ją zamknąć.

8. Wysyłanie zarejestrowanych użytkowników do tematu Pub/Sub

W tym kroku wdrożymy funkcję, dzięki której rejestratorzy, którzy przesłali formularz za pomocą formularza internetowego, będą opublikowani w temacie Cloud Pub/Sub.

Dodaj klasy danych

Najpierw utworzymy klasy danych Kotlin, będą to podmioty w ramach JPA i będą także pośredniczyć w reprezentowaniu abonentów przesłanych za pomocą formularza.

W pakiecie demonstracyjnym dodaj 2 nowe pliki: klasę Person i Spring Data PersonRepository. Te 2 klasy pozwolą nam łatwo przechowywać i pobierać wpisy rejestracyjne z bazy danych MySQL przy użyciu Spring Data JPA.

src/main/kotlin/com/example/demo/Person.kt

package com.example.demo

import javax.persistence.Entity
import javax.persistence.GeneratedValue
import javax.persistence.Id

@Entity
data class Person(
    val firstName: String,
    val lastName: String,
    val email: String,
    @Id @GeneratedValue
    var id: Long? = 0)

src/main/kotlin/com/example/demo/PersonRepository.kt

package com.example.demo

import org.springframework.data.repository.CrudRepository

interface PersonRepository : CrudRepository<Person, Long>

Dodawanie kontrolera internetowego

Następnie utworzymy klasę administratora, która przetwarza abonentów z formularza i wysyła informacje do utworzonego wcześniej tematu Cloud Pub/Sub. Ten kontroler tworzy 2 punkty końcowe:

  • /registerPerson: punkt końcowy POST, w którym są przesyłane informacje o abonencie, a następnie wysyłane do tematu Pub/Sub. W funkcji registerPerson(..) informacje o abonencie są wysyłane do tematu Pub/Sub za pomocą PubSubTemplate, czyli wygodnej klasy z integracji Spring Cloud GCP Pub/Sub, która minimalizuje powtarzalny kod potrzebny do rozpoczęcia interakcji z Cloud Pub/Sub.
  • /registrants: wyświetla wszystkich zarejestrowanych użytkowników w bazie danych. Te informacje są pobierane z instancji MySQL przy użyciu repozytorium Spring Data utworzonego w poprzednim kroku.

Utwórz tę klasę kontrolera w pakiecie demonstracyjnym:

src/main/kotlin/com/example/demo/Controller.kt

package com.example.demo

import com.google.cloud.spring.pubsub.core.PubSubTemplate
import org.springframework.web.bind.annotation.GetMapping
import org.springframework.web.bind.annotation.PostMapping
import org.springframework.web.bind.annotation.RequestParam
import org.springframework.web.bind.annotation.RestController
import org.springframework.web.servlet.ModelAndView
import org.springframework.web.servlet.view.RedirectView

@RestController
class Controller(val pubSubTemplate: PubSubTemplate, val personRepository: PersonRepository) {
  
  // The Pub/Sub topic name created earlier.
  val REGISTRATION_TOPIC = "registrations"

  @PostMapping("/registerPerson")
  fun registerPerson(
    @RequestParam("firstName") firstName: String,
    @RequestParam("lastName") lastName: String,
    @RequestParam("email") email: String): RedirectView {

    pubSubTemplate.publish(
        REGISTRATION_TOPIC,
        Person(firstName, lastName, email))
    return RedirectView("/")
  }

  @GetMapping("/registrants")
  fun getRegistrants(): ModelAndView {
    val personsList = personRepository.findAll().toList()
    return ModelAndView("registrants", mapOf("personsList" to personsList))
  }
}

Administrator odczytuje informacje o abonentach przesłane za pomocą formularza internetowego, a następnie publikuje je w temacie Pub/Sub.

Dodawanie komponentu JSON Object Mapper

W kontrolerze możesz zauważyć, że w temacie Pub/Sub publikujemy obiekt Person, a nie ciąg znaków. Jest to możliwe, ponieważ wykorzystujemy obsługę Spring Cloud GCP do wysyłania niestandardowych ładunków JSON do tematów. Biblioteki umożliwiają serializację obiektów w formacie JSON, wysyłanie ładunków JSON do tematu i deserializację ładunku po jego otrzymaniu.

Aby korzystać z tej funkcji, musimy dodać do kontekstu Twojej aplikacji komponent bean ObjectMapper. Ten obiekt typu bean ObjectMapper będzie używany do serializowania obiektów do i z JSON, gdy aplikacja wysyła i odbiera wiadomości. Do zajęć DemoApplication.kt dodaj ziarna wiosenna JacksonPubSubMessageConverter:

src/main/kotlin/com/example/demo/DemoApplication.kt

package com.example.demo

import org.springframework.boot.autoconfigure.SpringBootApplication
import org.springframework.boot.runApplication

// new imports to add
import org.springframework.context.annotation.Bean
import com.fasterxml.jackson.databind.ObjectMapper
import com.google.cloud.spring.pubsub.support.converter.JacksonPubSubMessageConverter

@SpringBootApplication
class DemoApplication {
  // This bean enables serialization/deserialization of
  // Java objects to JSON for Pub/Sub payloads
  @Bean
  fun jacksonPubSubMessageConverter(objectMapper: ObjectMapper) = 
      JacksonPubSubMessageConverter(objectMapper)
}

fun main(args: Array<String>) {
        runApplication<DemoApplication>(*args)
}

Na tym etapie możesz spróbować ponownie uruchomić aplikację, uruchamiając polecenie:

$ ./mvnw spring-boot:run

Z formularza internetowego na stronie głównej aplikacja wyśle informacje do utworzonego tematu Pub/Sub. Jednak nadal nie jest on jeszcze przydatny, ponieważ nadal musimy czytać z tego tematu Pub/Sub. Zostanie to zrobione w następnym kroku.

9. Odczytywanie rejestrujących się z tematu Pub/Sub

W ostatnim kroku przetworzymy informacje o abonentach z tematu Pub/Sub i zachujemy je w bazie danych Cloud MySQL. Spowoduje to zakończenie zgłoszenia, co umożliwi Ci przesłanie nowych zarejestrowanych użytkowników za pomocą formularza i wyświetlenie wszystkich zarejestrowanych użytkowników za pomocą punktu końcowego /registrants.

Ta aplikacja będzie korzystać z usługi Spring Integration, która umożliwia wygodne obchodzenie się z wiadomościami. Dodamy obiekt PubSubInboundChannelAdapter, aby umożliwić nam odczytywanie wiadomości z tematu Pub/Sub i umieszczanie ich w elemencie pubsubInputChannel w celu dalszego przetwarzania. Następnie skonfigurujemy funkcję messageReceiver za pomocą metody @ServiceActivator, która będzie wywoływana z wiadomościami, które dotarły pubsubInputChannel.

src/main/kotlin/com/example/demo/DemoApplication.kt

package com.example.demo

import org.springframework.boot.autoconfigure.SpringBootApplication
import org.springframework.boot.runApplication

import org.springframework.context.annotation.Bean
import com.fasterxml.jackson.databind.ObjectMapper
import org.springframework.cloud.gcp.pubsub.support.converter.JacksonPubSubMessageConverter

// new imports to add
import com.google.cloud.spring.pubsub.core.PubSubTemplate
import com.google.cloud.spring.pubsub.integration.AckMode
import com.google.cloud.spring.pubsub.integration.inbound.PubSubInboundChannelAdapter
import com.google.cloud.spring.pubsub.support.BasicAcknowledgeablePubsubMessage
import com.google.cloud.spring.pubsub.support.GcpPubSubHeaders
import org.springframework.beans.factory.annotation.Autowired
import org.springframework.beans.factory.annotation.Qualifier
import org.springframework.integration.annotation.ServiceActivator
import org.springframework.integration.channel.DirectChannel
import org.springframework.messaging.MessageChannel
import org.springframework.messaging.handler.annotation.Header

@SpringBootApplication
class DemoApplication {

  private val REGISTRANT_SUBSCRIPTION = "registrations-sub"

  @Autowired
  private lateinit var personRepository: PersonRepository

  // New Spring Beans to add
  @Bean
  fun pubsubInputChannel() = DirectChannel()

  @Bean
  fun messageChannelAdapter(
      @Qualifier("pubsubInputChannel") inputChannel: MessageChannel,
      pubSubTemplate: PubSubTemplate): PubSubInboundChannelAdapter {

    val adapter = PubSubInboundChannelAdapter(
        pubSubTemplate, REGISTRANT_SUBSCRIPTION)
    adapter.outputChannel = inputChannel
    adapter.ackMode = AckMode.MANUAL
    adapter.payloadType = Person::class.java
    return adapter
  }

  @ServiceActivator(inputChannel = "pubsubInputChannel")
  fun messageReceiver(
      payload: Person,
      @Header(GcpPubSubHeaders.ORIGINAL_MESSAGE) message: BasicAcknowledgeablePubsubMessage) {
    personRepository.save(payload)
    print("Message arrived! Payload: $payload")
    message.ack()
  }

  // ObjectMapper bean from previous step
  @Bean
  fun jacksonPubSubMessageConverter(objectMapper: ObjectMapper) = JacksonPubSubMessageConverter(objectMapper)
}

fun main(args: Array<String>) {
        runApplication<DemoApplication>(*args)
}

Na tym etapie konfiguracja aplikacji została ukończona. Aby sprawdzić, czy aplikacja działa prawidłowo, uruchom polecenie:

$ ./mvnw spring-boot:run

Ponownie kliknij przycisk Podgląd i spróbuj zarejestrować użytkownika, wypełniając i przesyłając formularz.

e0d0b0f0c94120c2.png

Kliknij link Zarejestrowane osoby, aby sprawdzić, czy nowy abonent wyświetla się w tabeli.

ab3b980423d0c51.png

Gratulacje, to już wszystko! Zakończ aplikację, naciskając CTRL+C w oknie terminala.

10. Czyszczenie

Aby wyczyścić środowisko, musisz usunąć temat Pub/Sub i utworzoną instancję Cloud MySQL.

Usuwanie instancji Cloud MySQL

$ gcloud sql instances delete codelab-instance

Usuwanie zasobów Pub/Sub

$ gcloud pubsub subscriptions delete registrations-sub
$ gcloud pubsub topics delete registrations

11. Gratulacje!

Udało Ci się napisać aplikację Spring Kotlin, która integruje się z Cloud Pub/Sub i Cloud SQL (MySQL).

Więcej informacji

Licencja

To zadanie jest licencjonowane na podstawie ogólnej licencji Creative Commons Attribution 2.0.