פיתוח אפליקציית 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 Console ויוצרים פרויקט חדש או משתמשים בפרויקט קיים. (אם עדיין אין לכם חשבון Gmail או G Suite, אתם צריכים ליצור חשבון).

dMbN6g9RawQj_VXCSYpdYncY-DbaRzr2GbnwoV7jFf1u3avxJtmGPmKpMYgiaMH-qu80a_NJ9p2IIXFppYk8x3wyymZXavjglNLJJhuXieCem56H30hwXtd8PvXGpXJO9gEUDu3cZw

ci9Oe6PgnbNuSYlMyvbXF1JdQyiHoEgnhl4PlV_MFagm2ppzhueRkqX4eLjJllZco_2zCp0V0bpTupUSKji9KkQyWqj11pqit1K1faS1V6aFxLGQdkuzGp4rsQTan7F01iePL5DtqQ

8-tA_Lheyo8SscAVKrGii2coplQp2_D1Iosb2ViABY0UUO1A8cimXUu6Wf1R9zJIRExL5OB2j946aIiFtyKTzxDcNnuznmR45vZ2HMoK3o67jxuoUJCAnqvEX6NgPGFjCVNgASc-lg

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

  1. לאחר מכן, תצטרכו להפעיל את החיוב ב-Cloud Console כדי להשתמש במשאבים של Google Cloud.

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

Google Cloud Shell

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

הפעלת Cloud Shell

  1. ב-Cloud Console, לוחצים על Activate Cloud Shell H7JlbhKGHITmsxhQIcLwoe5HXZMhDlYue4K-SPszMxUxDjIeWfOHBfxDHYpmLQTzUmQ7Xx8o6OJUlANnQF0iBuUyfp1RzVad_4nCa0Zz5LtwBlUZFXFCWFrmrWZLqg1MkZz2LdgUDQ.

zlNW0HehB_AFW1qZ4AyebSQUdWm95n7TbnOr7UVm3j9dFcg6oWApJRlC0jnU1Mvb-IQp-trP1Px8xKNwt6o3pP6fyih947sEhOFI4IRF0W7WZk6hFqZDUGXQQXrw21GuMm2ecHrbzQ

אם זו הפעם הראשונה שאתם מפעילים את Cloud Shell, יוצג לכם מסך ביניים (בחלק הנגלל) עם תיאור של 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. אתחול אפליקציית Spring Boot

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

קודם כל, נשתמש ב-Initializr כדי ליצור את קוד ה-scaffolding של הפרויקט. בחלון 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 וגם קוד scaffolding לאפליקציה בספרייה registrations-codelab/. בקטעים הבאים מתוארות עריכות הקוד שצריך לבצע כדי ליצור אפליקציה תקינה.

עורך הקוד של Cloud Shell

הדרך הקלה ביותר להתחיל לשנות ולהציג קוד בסביבת Cloud Shell היא באמצעות עורך הקוד המובנה של Cloud Shell.

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

cce293b40119c37b.png

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

קודם כל, מגדירים את האפליקציה כך שתוכל להתחבר למסד הנתונים של Cloud MySQL שהגדרתם. ספריות Spring Cloud GCP מציעות Cloud MySQL starter, שכולל את התלות הנדרשת לחיבור למכונת 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 הוא framework ליצירת תבניות שמשמש אותנו ליצירה ולהצגה של 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 Data 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>

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

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

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

יוצרים את המחלקה Controller הבאה בחבילת ההדגמה:

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

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

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

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

$ ./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 שמותנה בייחוס 2.0 כללי.