פיתוח אפליקציית Kotlin Spring באמצעות Google Cloud Platform

1. מבוא

Spring Framework 5.0 הוסיפה תמיכה ייעודית ב-Kotlin כדי להקל על מפתחי Kotlin להשתמש ב-Spring. המשמעות של השינויים האלה היא שהשילובים עם Google Cloud שמסופקים על ידי Spring Cloud GCP יפעלו בצורה חלקה ב-Kotlin. ב-Codelab הזה תראו כמה קל להתחיל להשתמש בשירותי Google Cloud באפליקציות של Kotlin!

ב-Codelab הזה תלמד להגדיר אפליקציה פשוטה לרישום ב-Kotlin לצורך שימוש בשירותי GCP, כולל Cloud Pub/Sub ו-Cloud SQL.

מה תפַתחו

ב-Codelab הזה, מגדירים אפליקציית Kotlin Spring Boot שמקבלת פרטים של רושם הדומיין, מפרסמת אותם בנושא Cloud Pub/Sub ושומרת אותם על מסד נתונים של Cloud MySQL.

מה תלמדו

איך משלבים את שירותי Google Cloud באפליקציית Kotlin Spring.

מה נדרש

  • פרויקט ב-Google Cloud Platform
  • דפדפן, למשל Chrome או Firefox

איך תשתמשו במדריך הזה?

לקריאה בלבד לקרוא אותו ולבצע את התרגילים

איזה דירוג מגיע לחוויה שלך עם בניית אפליקציות אינטרנט מסוג HTML/CSS?

מתחילים בינונית בקיאים

איזה דירוג מגיע לדעתך לחוויית השימוש בשירותי Google Cloud Platform?

מתחילים בינונית בקיאים

2. הגדרה ודרישות

הגדרת סביבה בקצב עצמאי

  1. נכנסים למסוף Cloud ויוצרים פרויקט חדש או עושים שימוש חוזר בפרויקט קיים. (אם עדיין אין לכם חשבון Gmail או G Suite, עליכם ליצור חשבון).

dMbN6g9RawQj_VXCSYpdYncY-DbaRzr2GbnwoV7jFf1u3avxJtmGPmKpMYgiaMH-qu80a_NJ9p2IIXFppYk8x3wyymZXavjglNLJJhuXieCem56H30hwXtd8PvXGpXJO9gEUDu3cZw

ci9Oe6PgnbNuSYlMyvbXF1JdQyiHoEgnhl4PlV_MFagm2ppzhueRkqX4eLjJllZco_2zCp0V0bpTupUSKji9KkQyWqj11pqit1K1faS1V6aFxLGQdkuzGp4rsQTan7F01iePL5DtqQ

8-tA_Lheyo8SscAVKrGii2coplQp2_D1Iosb2ViABY0UUO1A8cimXUu6Wf1R9zJIRExL5OB2j946aIiFtyKTzxDcNnuznmR45vZ2HMoK3o67jxuoUJCAnqvEX6NgPGFjCVNgASc-lg

חשוב לזכור את מזהה הפרויקט, שם ייחודי לכל הפרויקטים ב-Google Cloud (השם שלמעלה כבר תפוס ולא מתאים לכם, סליחה). בהמשך ב-Codelab הזה, היא תיקרא PROJECT_ID.

  1. בשלב הבא צריך להפעיל את החיוב במסוף Cloud כדי להשתמש במשאבים של Google Cloud.

מעבר ב-Codelab הזה לא אמור לעלות הרבה, אם בכלל. חשוב לבצע את כל ההוראות בקטע 'ניקוי' שמסביר איך להשבית משאבים כדי שלא תצברו חיובים מעבר למדריך הזה. משתמשים חדשים ב-Google Cloud זכאים להשתתף בתוכנית תקופת ניסיון בחינם בשווי 1,200 ש"ח.

Google Cloud Shell

אומנם אפשר להפעיל את Google Cloud מרחוק מהמחשב הנייד, אבל ב-Codelab הזה נשתמש ב-Google Cloud Shell, סביבת שורת הפקודה שפועלת ב-Cloud.

הפעלת Cloud Shell

  1. במסוף Cloud, לוחצים על Activate Cloud Shell H7JlbhKGHITmsxhQIcLwoe5HXZMhDlYue4K-SPszMxUxDjIeWfOHBfxDHYpmLQTzUmQ7Xx8o6OJUlANnQF0iBuUyfp1RWzVad_4nCwUyfp1RWzVad_4nCwlZUDZ5LtFCZUHBfxDHYpmLQTzUmQ7Xx8o6OJUlANnQF0iBuUyfp1RWzVad_4nCwZlZ5Lt.

zlNW0HehB_AFW1qZ4AyebSQUdWm95n7TbnOr7UVm3j9dFcg6oWApJRlC0jnU1Mvb-IQp-trP1Px8xKNwt6o3pP6fyih947sEhOFI4IRF0W7WZk6hFqZDUGXQQXrw21GuMm2ecHrbzQ

אם זו הפעם הראשונה שאתם מפעילים את Cloud Shell, יוצג לכם מסך ביניים (בחלק הנגלל) שמתאר מהו. במקרה כזה, לוחצים על המשך (וזה לא יקרה שוב). כך נראה המסך החד-פעמי:

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

ההקצאה וההתחברות ל-Cloud Shell נמשכת כמה דקות.

pTv5mEKzWMWp5VBrg2eGcuRPv9dLInPToS-mohlrqDASyYGWnZ_SwE-MzOWHe76ZdCSmw0kgWogSJv27lrQE8pvA5OD6P1I47nz8vrAdK7yR1NseZKJvcxAZrPb8wRxoqyTpD-gbhA

למכונה הווירטואלית הזו נטען כל כלי הפיתוח הדרושים. יש בה ספריית בית בנפח מתמיד של 5GB והיא פועלת ב-Google Cloud, מה שמשפר משמעותית את ביצועי הרשת והאימות. אם לא את כולן, ניתן לבצע חלק גדול מהעבודה ב-Codelab הזה באמצעות דפדפן או Chromebook.

אחרי ההתחברות ל-Cloud Shell, אתם אמורים לראות שכבר בוצע אימות ושהפרויקט כבר מוגדר למזהה הפרויקט שלכם.

  1. מריצים את הפקודה הבאה ב-Cloud Shell כדי לוודא שהאימות בוצע:
gcloud auth list

פלט הפקודה

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

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

פלט הפקודה

[core]
project = <PROJECT_ID>

אם היא לא נמצאת שם, תוכלו להגדיר אותה באמצעות הפקודה הבאה:

gcloud config set project <PROJECT_ID>

פלט הפקודה

Updated property [core/project].

3. הקצאת משאבי Pub/Sub

קודם כול צריך להגדיר נושא Cloud Pub/Sub ומינוי. באפליקציה הזו, נפרסם פרטי רישום לנושא Pub/Sub. לאחר מכן קוראים את המידע מהנושא הזה ונשמרים במסד הנתונים.

במדריך הזה נשתמש ב-Cloud Shell כדי להקצות את המשאבים שלנו. שימו לב שאפשר להגדיר משאבי Pub/Sub גם דרך הקטע Cloud Pub/Sub במסוף Google Cloud.

בטרמינל של Cloud Shell, מפעילים קודם את Pub/Sub API.

$ gcloud services enable pubsub.googleapis.com

בשלב הבא ניצור נושא Pub/Sub בשם registrations לאפליקציה הזו. פרטי ההרשמה שנשלחו דרך הבקשה יפורסמו בנושא הזה.

$ gcloud pubsub topics create registrations

לסיום, יוצרים מינוי לנושא. מינוי Pub/Sub מאפשר לקבל הודעות מנושא מסוים.

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

סיימת ליצור נושא Cloud Pub/Sub ומינוי לאפליקציה.

4. יצירת מכונה ומסד נתונים של Cloud SQL (MySQL)

עבור האפליקציה לדוגמה שלנו, אנחנו צריכים גם להגדיר מופע של מסד נתונים שמכיל את פרטי רושם הדומיין. השלב הזה יסתמך גם על הטרמינל של Cloud Shell להקצאת משאבים ב-Cloud SQL. שימו לב: אפשר גם להציג את המכונות של Cloud SQL ולהגדיר אותן דרך מסוף Google Cloud.

קודם כול, מפעילים את Cloud SQL Admin API.

$ gcloud services enable sqladmin.googleapis.com

בשלב הבא, נקצה מכונה של Cloud SQL (MySQL). יכול להיות שייקח קצת זמן לפקודה הזו.

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

אחרי שיצרתם את המכונה של Cloud SQL, אתם צריכים ליצור במכונה מסד נתונים חדש בשם registrants.

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

סיימתם להגדיר את המכונה של Cloud SQL ואת מסד הנתונים באפליקציה.

5. אתחול אפליקציה של 'אתחול קפיץ'

עכשיו אנחנו מוכנים להתחיל בכתיבת הבקשה. השלבים הבאים ימשיכו להשתמש ב-Cloud Shell שמתוארת בשלבי ההגדרה.

בשלב הראשון נשתמש ב-Initializr כדי ליצור את קוד הפיגועים של הפרויקט. בחלון Cloud Shell, מריצים את:

$ 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

הפקודה הזו יוצרת הגדרה ראשונית של פרויקט Maven וגם קוד פיגוע (scaffling) לאפליקציה בספרייה registrations-codelab/. בקטעים הבאים מתוארות פעולות העריכה בקוד שנדרשות כדי ליצור אפליקציה פעילה.

עורך קוד ב-Cloud Shell

הדרך הקלה ביותר להתחיל לשנות את הקוד ולצפות בו בסביבת Cloud Shell היא להשתמש ב-Cloud Shell Code Editor המובנה.

אחרי שפותחים מופע של Cloud Shell, לוחצים על סמל העיפרון כדי לפתוח את עורך הקוד. העורך צריך לאפשר לך לשנות ישירות את קובצי הפרויקט שהופקו על ידי Initialzr.

cce293b40119c37b.png

6. הגדרת מסד הנתונים

קודם כול, מגדירים את האפליקציה כך שהיא תוכל להתחבר למסד הנתונים ב-Cloud MySQL שהגדרתם. ספריות Spring Cloud GCP כוללות סימן לתחילת פעולה של Cloud MySQL, שמספק את יחסי התלות הנדרשים לחיבור למכונה של Cloud MySQL.

מוסיפים את התלות spring-cloud-gcp-starter-sql-mysql לפרויקט pom.xml:

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>

בנוסף, עליך לשנות את קובץ התצורה application.properties כך שיתאר את תצורת מסד הנתונים שלך. מעתיקים את המאפיינים הבאים לקובץ application.properties.

מוצאים את שם החיבור של המכונה למסד הנתונים:

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

הפלט של זה ישמש בקובץ application.properties כדי להגדיר את פרטי החיבור.

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

המאפיין היחיד שצריך לשנות הוא שם החיבור של המכונה. צריך להזין את הערך בפורמט הבא: YOUR_GCP_PROJECT_ID:REGION:DATABASE_INSTANCE_NAME, שמופרד בנקודתיים.

7. יצירת התוכן הסטטי

קודם כל ניצור את החזית עבור האפליקציה. האפליקציה צריכה לכלול טופס שמאפשר לאנשים לרשום אנשים פרטיים וגם תצוגה שמציגה את כל הנרשמים בהצלחה.

לדף הבית, יוצרים index.html שמכיל את טופס הרישום.

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>

בשלב הבא ניצור תבנית Thymeleaf בשם registrants.html להצגת המשתמשים הרשומים. Thymeleaf היא מסגרת ליצירת תבניות שבה אנחנו משתמשים כדי לבנות ולהציג HTML שנוצר באופן דינמי. אתם תראו שהתבנית נראית כמו HTML, אבל היא כוללת כמה רכיבי Markdown נוספים שמשמשים לטיפול בתוכן דינמי. התבנית הזו מקבלת פרמטר יחיד בשם personsList שמכיל את כל רושם הדומיין שנרשמו באמצעות האפליקציה.

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>

בשלב הזה, תוכלו לוודא שהתוכן הסטטי מוצג.

יצירה והפעלה של האפליקציה באמצעות Maven:

$ ./mvnw spring-boot:run

לוחצים על לחצן התצוגה המקדימה בחלון Cloud Shell ומוודאים שדף הבית עובר עיבוד. עם זאת, אף אחת מהפונקציות בממשק המשתמש לא תפעל כי חסר לנו בקר אינטרנט. המידע הזה יתווסף בשלב הבא.

5e38bb0d0e93002e.png

אחרי תצוגה מקדימה של האפליקציה, לוחצים על CTRL+C כדי לסיים את האפליקציה.

8. שליחת רושם הדומיין לנושא Pub/Sub

בשלב הזה נטמיע את התכונה שבה נרשמים שנשלחו באמצעות טופס האינטרנט יפורסמו לנושא ב-Cloud Pub/Sub.

הוספת קטגוריות הנתונים

קודם כל, ניצור כמה מחלקות נתונים ב-Kotlin; אלה יהיו ישויות ה-JPA שלנו והן ישמשו גם כנציגים מתווכים של הנרשמים שנשלחו באמצעות הטופס.

בחבילת ההדגמה, מוסיפים שני קבצים חדשים: מחלקה Person ונתוני Spring PersonRepository. שני הסוגים האלה יאפשרו לנו לאחסן ולאחזר בקלות רשומות רישום ממסד הנתונים MySQL באמצעות 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>

הוספת בקר האינטרנט

בשלב הבא ניצור מחלקה של נאמן מידע שתטפל בנרשמים מהטופס ותשלח את המידע לנושא Cloud Pub/Sub שיצרתם קודם. השלט רחוק הזה יוצר שתי נקודות קצה:

  • /registerPerson: נקודת הקצה ב-POST שבה הפרטים של רושם הדומיין נשלחים לנושא Pub/Sub. בפונקציה registerPerson(..), פרטי רושם הדומיין נשלחים לנושא Pub/Sub באמצעות PubSubTemplate, סיווג נוחות משילובי Pub/Sub של Spring Cloud GCP שמצמצמים את הקוד הסטנדרטי שנדרש כדי להתחיל ליצור אינטראקציה עם Cloud Pub/Sub.
  • /registrants: בעמודה הזו מוצגים כל רושם הדומיין שנרשמו בהצלחה במסד הנתונים. המידע הזה מאוחזר ממכונת MySQL באמצעות מאגר נתוני Spring שיצרנו בשלב הקודם.

יוצרים את מחלקה הבאה של נאמן מידע בחבילת ההדגמה:

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

נאמן המידע קורא את פרטי רושם הדומיין שנשלחו באמצעות טופס האינטרנט, ולאחר מכן מפרסם את הפרטים בנושא Pub/Sub.

הוספת Bean של אובייקט JSON

יכול להיות שהבחנתם בנאמן המידע שאנחנו מפרסמים אובייקט Person לנושא Pub/Sub ולא למחרוזת. זה מתאפשר כי אנחנו מנצלים את התמיכה של Spring Cloud GCP לשליחה של מטענים ייעודיים (payloads) מותאמים אישית של JSON לנושאים. הספריות מאפשרות לבצע סריאליזציה של אובייקטים ל-JSON, לשלוח מטענים ייעודיים של JSON לנושא, ולבצע פעולת deserialize של המטען הייעודי (payload) כשהוא מתקבל.

כדי ליהנות מהיתרונות של התכונה הזו, צריך להוסיף הייתה ObjectMapper להקשר של האפליקציה שלך. ה-ObjectMapper הזה ישמש ליצירת סריאליזציה של אובייקטים ל-JSON וממנו בזמן שהאפליקציה שולחת ומקבלת הודעות. בכיתה DemoApplication.kt, מוסיפים את שעועית האביב 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)
}

בשלב הזה, תוכלו לנסות להפעיל את האפליקציה שוב על ידי הרצת:

$ ./mvnw spring-boot:run

מטופס האינטרנט שבדף הראשי, האפליקציה תשלח עכשיו את המידע לנושא Pub/Sub שיצרתם. עם זאת, הכלי עדיין לא מועיל כי אנחנו עדיין צריכים לקרוא מהנושא הזה ב-Pub/Sub. ניתן לעשות זאת בשלב הבא.

9. קריאת נרשמים מנושא Pub/Sub

בשלב האחרון, נעבד את פרטי רושם הדומיין מהנושא Pub/Sub ונשמור את המידע למסד הנתונים של Cloud MySQL. השלמת הבקשה תאפשר לך לשלוח נרשמים חדשים באמצעות הטופס ולהציג את כל המשתמשים הרשומים דרך נקודת הקצה של /registrants.

האפליקציה הזו תפיק תועלת מ-Spring Integration, שמציע פשטות נוחות רבות להתמודדות עם העברת הודעות. נוסיף PubSubInboundChannelAdapter כדי לאפשר לנו לקרוא הודעות בנושא Pub/Sub ונעביר אותן אל pubsubInputChannel לצורך עיבוד נוסף. לאחר מכן נגדיר את הפונקציה messageReceiver באמצעות @ServiceActivator כך שתפעיל את ההודעות שיתקבלו ב-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)
}

בשלב הזה השלמתם את הגדרת האפליקציה. כדי לוודא שהאפליקציה פועלת כראוי, מריצים את:

$ ./mvnw spring-boot:run

לוחצים שוב על הלחצן תצוגה מקדימה ומנסים לרשום משתמש על ידי מילוי הטופס ושליחה.

e0d0b0f0c94120c2.png

לוחצים על הקישור אנשים רשומים כדי לוודא שרושם הדומיין החדש מופיע בטבלה.

ab3b980423d0c51.png

ברכותינו, סיימת! כדי לסגור את האפליקציה, לוחצים על CTRL+C בחלון הטרמינל.

10. הסרת המשאבים

כדי לנקות את הסביבה שלכם, עליכם למחוק את נושא Pub/Sub ואת המכונה של Cloud MySQL שיצרתם.

מחיקת המופע של Cloud MySQL

$ gcloud sql instances delete codelab-instance

מחיקת משאבי Pub/Sub

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

11. מעולה!

סיימתם לכתוב אפליקציית Spring Kotlin שמשתלבת עם Cloud Pub/Sub ו-Cloud SQL (MySQL).

מידע נוסף

רישיון

היצירה הזו בשימוש ברישיון Creative Commons Attribution 2.0 גנרי.