Tworzenie aplikacji wiosennej Kotlin w Google Cloud Platform

1. Wprowadzenie

W Spring Framework 5.0 dodano specjalną obsługę języka Kotlin, dzięki czemu deweloperzy Kotlin mogą łatwo korzystać z Spring. W rezultacie te zmiany sprawiły, że integracje Google Cloud udostępniane przez Spring Cloud GCP działają bezproblemowo również w Kotlinie. Z tego laboratorium dowiesz się, jak łatwo zacząć korzystać z usług Google Cloud w aplikacjach Kotlin.

W tym laboratorium kodowania pokazujemy, jak skonfigurować prostą aplikację do rejestracji w języku Kotlin, która demonstruje korzystanie z usług GCP, takich jak Cloud Pub/SubCloud SQL.

Co utworzysz

W tym laboratorium nauczysz się konfigurować aplikację Kotlin Spring Boot, która akceptuje informacje o rejestrujących się osobach, publikuje je w temacie Cloud Pub/Sub i zapisuje w bazie danych Cloud MySQL.

Czego się nauczysz

Jak przeprowadzić integrację z usługami Google Cloud w aplikacji Kotlin Spring.

Czego potrzebujesz

  • Projekt Google Cloud Platform
  • przeglądarkę, np. Chrome lub Firefox;

Jak zamierzasz korzystać z tego samouczka?

Tylko przeczytaj Przeczytaj i wykonaj ćwiczenia

Jak oceniasz swoje doświadczenie w tworzeniu aplikacji internetowych w HTML/CSS?

Początkujący Średnio zaawansowany Zaawansowany

Jak oceniasz korzystanie z usług Google Cloud Platform?

Początkujący Średnio zaawansowany Zaawansowany

2. Konfiguracja i wymagania

Samodzielne konfigurowanie środowiska

  1. Zaloguj się w konsoli Google Cloud i utwórz nowy projekt lub użyj istniejącego. (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, czyli unikalną nazwę we wszystkich projektach Google Cloud (podana powyżej nazwa jest już zajęta i nie będzie działać w Twoim przypadku). W dalszej części tego laboratorium będzie on nazywany PROJECT_ID.

  1. Następnie musisz włączyć rozliczenia w konsoli Cloud, aby korzystać z zasobów Google Cloud.

Ukończenie tego laboratorium nie powinno wiązać się z dużymi kosztami, a nawet z żadnymi. Wykonaj instrukcje z sekcji „Czyszczenie”, w której znajdziesz informacje o tym, jak wyłączyć zasoby, aby uniknąć naliczenia opłat po zakończeniu tego samouczka. Nowi użytkownicy Google Cloud mogą skorzystać z programu bezpłatnego okresu próbnego, w którym mają do dyspozycji środki w wysokości 300 USD.

Google Cloud Shell

Z Google Cloud można korzystać zdalnie na laptopie, ale w tym module użyjemy Google Cloud Shell, czyli środowiska wiersza poleceń działającego w chmurze.

Aktywowanie Cloud Shell

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

zlNW0HehB_AFW1qZ4AyebSQUdWm95n7TbnOr7UVm3j9dFcg6oWApJRlC0jnU1Mvb-IQp-trP1Px8xKNwt6o3pP6fyih947sEhOFI4IRF0W7WZk6hFqZDUGXQQXrw21GuMm2ecHrbzQ

Jeśli uruchamiasz Cloud Shell po raz pierwszy, zobaczysz ekran pośredni (część strony widoczna po przewinięciu) z opisem tego środowiska. W takim przypadku kliknij Dalej, a ten ekran nie będzie się już wyświetlać. Ten wyświetlany jednorazowo ekran wygląda tak:

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

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

pTv5mEKzWMWp5VBrg2eGcuRPv9dLInPToS-mohlrqDASyYGWnZ_SwE-MzOWHe76ZdCSmw0kgWogSJv27lrQE8pvA5OD6P1I47nz8vrAdK7yR1NseZKJvcxAZrPb8wRxoqyTpD-gbhA

Ta maszyna wirtualna zawiera wszystkie potrzebne narzędzia dla programistów. Zawiera również stały katalog domowy o pojemności 5 GB i działa w Google Cloud, co znacznie zwiększa wydajność sieci i usprawnia proces uwierzytelniania. Większość zadań w tym module, a być może wszystkie, możesz wykonać w przeglądarce lub na Chromebooku.

Po połączeniu z Cloud Shell zobaczysz, że uwierzytelnianie zostało już przeprowadzone, a projekt jest już ustawiony na Twój identyfikator projektu.

  1. Aby potwierdzić, że uwierzytelnianie zostało przeprowadzone, uruchom w Cloud Shell to polecenie:
gcloud auth list

Wynik 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

Wynik polecenia

[core]
project = <PROJECT_ID>

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

gcloud config set project <PROJECT_ID>

Wynik polecenia

Updated property [core/project].

3. Provision Pub/Sub resources

Najpierw musimy skonfigurować temat i subskrypcję Cloud Pub/Sub. W tej aplikacji będziemy publikować informacje o rejestracji w temacie Pub/Sub. Informacje te będą następnie odczytywane z tego tematu i zapisywane w bazie danych.

W tym samouczku do udostępniania zasobów będziemy używać Cloud Shell. Pamiętaj, że zasoby Pub/Sub możesz też skonfigurować 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ą aplikacji zostaną opublikowane w tym temacie.

$ gcloud pubsub topics create registrations

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

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

Temat i subskrypcja Cloud Pub/Sub dla aplikacji zostały utworzone.

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 osobach rejestrujących się. W tym kroku do aprowizacji zasobów Cloud SQL użyjesz też terminala Cloud Shell. Pamiętaj, że instancje Cloud SQL możesz też wyświetlać i konfigurować w konsoli Google Cloud.

Najpierw włącz interfejs Cloud SQL Admin API.

$ gcloud services enable sqladmin.googleapis.com

Następnie udostępnimy instancję Cloud SQL (MySQL). Wykonanie tego polecenia może trochę potrwać.

$ 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

Konfigurowanie instancji i bazy danych Cloud SQL dla aplikacji zostało zakończone.

5. Inicjowanie aplikacji Spring Boot

Możemy teraz zacząć pisać aplikację. W dalszych krokach będziemy korzystać z Cloud Shell opisanego w instrukcji konfiguracji.

Najpierw użyjemy Initializr, aby wygenerować kod szkieletowy projektu. W oknie Cloud Shell uruchom:

$ 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 początkową konfigurację projektu Maven oraz kod szkieletowy aplikacji w katalogu registrations-codelab/. W sekcjach poniżej opisujemy zmiany w kodzie, które są niezbędne do utworzenia działającej aplikacji.

Edytor kodu Cloud Shell

Najprostszym sposobem na rozpoczęcie 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 umożliwiać bezpośrednie modyfikowanie plików projektu utworzonych przez Initialzr.

cce293b40119c37b.png

6. Konfiguracja bazy danych

Najpierw skonfiguruj aplikację, aby mogła łączyć się z bazą danych Cloud MySQL, którą skonfigurowano. Biblioteki Spring Cloud GCP oferują Cloud MySQL Starter, który zapewnia zależności niezbędne do łączenia się 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>

Musisz też zmodyfikować plik konfiguracyjny 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 tego polecenia 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 z instancją. Ta wartość musi być sformatowana jako wartość rozdzielona dwukropkiem w formacie YOUR_GCP_PROJECT_ID:REGION:DATABASE_INSTANCE_NAME.

7. Tworzenie treści statycznych

Najpierw utworzymy interfejs aplikacji. Aplikacja powinna zawierać formularz umożliwiający rejestrację osób oraz widok, w którym wyświetlają się wszystkie zarejestrowane osoby.

Na stronie głównej utwórz element index.html zawierający formularz rejestracji.

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, który będzie wyświetlać zarejestrowanych użytkowników. Thymeleaf to platforma szablonów, której używamy do tworzenia i wyświetlania dynamicznie generowanego kodu HTML. Szablon wygląda jak HTML, ale zawiera dodatkowe elementy Markdown do obsługi treści dynamicznych. Ten szablon akceptuje jeden parametr o nazwie personsList, który zawiera wszystkich zarejestrowanych użytkowników.

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ę za pomocą Maven:

$ ./mvnw spring-boot:run

Kliknij przycisk podglądu w oknie Cloud Shell i sprawdź, czy wyświetla się strona główna. Żadna funkcja interfejsu nie będzie działać, ponieważ nie mamy kontrolera internetowego. Zostanie on dodany 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 dane rejestrujących przesłane za pomocą formularza internetowego będą publikowane w temacie Cloud Pub/Sub.

Dodawanie kategorii danych

Najpierw utworzymy klasy danych w języku Kotlin. Będą one naszymi encjami JPA i pośrednią reprezentacją osób rejestrujących się za pomocą formularza.

W pakiecie demonstracyjnym dodaj 2 nowe pliki: klasę Person i interfejs Spring Data PersonRepository. Te 2 klasy pozwolą nam łatwo przechowywać i pobierać wpisy rejestracyjne z bazy danych MySQL za pomocą 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ę Controller, która przetwarza dane rejestrujących 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 przesyłane są informacje o rejestrującym, a następnie wysyłane do tematu Pub/Sub. W funkcji registerPerson(..) informacje o rejestrującym są wysyłane do tematu Pub/Sub za pomocą PubSubTemplate, 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, którzy zostali pomyślnie zarejestrowani w bazie danych. Te informacje są pobierane z instancji MySQL za pomocą repozytorium Spring Data, które zostało utworzone w poprzednim kroku.

W pakiecie demonstracyjnym utwórz tę klasę kontrolera:

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

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

Dodawanie komponentu JSON Object Mapper Bean

W kontrolerze możesz zauważyć, że publikujemy w temacie Pub/Sub obiekt Person, a nie ciąg znaków. Jest to możliwe, ponieważ korzystamy z obsługi niestandardowych ładunków JSON w Spring Cloud GCP, które można wysyłać do tematów. Biblioteki umożliwiają serializowanie obiektów do formatu JSON, wysyłanie ładunków JSON do tematu i deserializowanie ładunku po jego otrzymaniu.

Aby korzystać z tej funkcji, musimy dodać do kontekstu aplikacji komponent ObjectMapper. Ten komponent ObjectMapper będzie używany do serializacji obiektów do formatu JSON i z niego, gdy aplikacja będzie wysyłać i odbierać wiadomości. W klasie DemoApplication.kt dodaj komponent Spring: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)
}

W tym momencie możesz spróbować ponownie uruchomić aplikację, wpisując:

$ ./mvnw spring-boot:run

Formularz internetowy na stronie głównej będzie teraz wysyłać informacje do utworzonego przez Ciebie tematu Pub/Sub. Nie robi jednak jeszcze niczego przydatnego, ponieważ nadal musimy odczytywać dane z tego tematu Pub/Sub. Zrobisz to w następnym kroku.

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

W ostatnim kroku będziemy przetwarzać informacje o osobach rejestrujących się z tematu Pub/Sub i zapisywać je w bazie danych Cloud MySQL. Spowoduje to ukończenie aplikacji, co umożliwi przesyłanie nowych zgłoszeń rejestracyjnych za pomocą formularza i wyświetlanie wszystkich zarejestrowanych użytkowników za pomocą punktu końcowego /registrants.

Ta aplikacja będzie korzystać z Spring Integration, która oferuje wiele wygodnych abstrakcji do obsługi przesyłania wiadomości. Dodamy PubSubInboundChannelAdapter, aby umożliwić odczytywanie wiadomości z tematu Pub/Sub i umieszczanie ich w pubsubInputChannel w celu dalszego przetwarzania. Następnie skonfigurujemy funkcję messageReceiver za pomocą @ServiceActivator, aby była wywoływana w przypadku wiadomości docierających do 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)
}

W tym momencie konfiguracja aplikacji jest zakończona. Aby sprawdzić, czy aplikacja działa prawidłowo, uruchom:

$ ./mvnw spring-boot:run

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

e0d0b0f0c94120c2.png

Kliknij link Zarejestrowane osoby, aby sprawdzić, czy nowy uczestnik jest widoczny w tabeli.

ab3b980423d0c51.png

Gratulacje! Wszystko gotowe. Zatrzymaj aplikację, naciskając CTRL+C w oknie terminala.

10. Czyszczenie

Aby wyczyścić środowisko, musisz usunąć utworzony temat Pub/Sub i 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!

Aplikacja Spring Kotlin, która integruje się z Cloud Pub/Sub i Cloud SQL (MySQL), została napisana.

Więcej informacji

Licencja

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