1. Pengantar
Spring Framework 5.0 menambahkan dukungan Kotlin khusus sehingga memudahkan developer Kotlin menggunakan Spring. Oleh karena itu, perubahan ini berarti bahwa integrasi Google Cloud yang disediakan oleh Spring Cloud GCP juga berfungsi dengan lancar di Kotlin. Dalam codelab ini, Anda akan melihat betapa mudahnya mulai menggunakan layanan Google Cloud di aplikasi Kotlin Anda.
Codelab ini membahas penyiapan aplikasi pendaftaran sederhana di Kotlin yang menunjukkan penggunaan layanan GCP, termasuk: Cloud Pub/Sub dan Cloud SQL.
Yang akan Anda build
Dalam codelab ini, Anda akan menyiapkan aplikasi Kotlin Spring Boot yang menerima informasi pendaftar, memublikasikannya ke topik Cloud Pub/Sub, dan menyimpannya ke database Cloud MySQL.
Yang akan Anda pelajari
Cara berintegrasi dengan layanan Google Cloud di aplikasi Spring Kotlin Anda.
Yang Anda butuhkan
- Project Google Cloud Platform
- Browser, seperti Chrome atau Firefox
Bagaimana Anda akan menggunakan tutorial ini?
Sejauh mana pengalaman Anda membuat aplikasi web HTML/CSS?
Bagaimana penilaian Anda terhadap pengalaman menggunakan layanan Google Cloud Platform?
2. Penyiapan dan Persyaratan
Penyiapan lingkungan mandiri
- Login ke Cloud Console dan buat project baru atau gunakan kembali project yang sudah ada. (Jika belum memiliki akun Gmail atau G Suite, Anda harus membuatnya.)
Ingat project ID, nama unik di semua project Google Cloud (maaf, nama di atas telah digunakan dan tidak akan berfungsi untuk Anda!) Project ID tersebut selanjutnya akan dirujuk di codelab ini sebagai PROJECT_ID.
- Selanjutnya, Anda harus mengaktifkan penagihan di Cloud Console untuk menggunakan resource Google Cloud.
Menjalankan operasi dalam codelab ini seharusnya tidak memerlukan banyak biaya, bahkan mungkin tidak sama sekali. Pastikan untuk mengikuti petunjuk yang ada di bagian "Membersihkan" yang memberi tahu Anda cara menonaktifkan resource sehingga tidak menimbulkan penagihan di luar tutorial ini. Pengguna baru Google Cloud memenuhi syarat untuk mengikuti program Uji Coba Gratis senilai $300 USD.
Google Cloud Shell
Meskipun Google Cloud dapat dioperasikan dari jarak jauh menggunakan laptop Anda, dalam codelab ini, kita akan menggunakan Google Cloud Shell, lingkungan command line yang berjalan di Cloud.
Mengaktifkan Cloud Shell
- Dari Cloud Console, klik Aktifkan Cloud Shell
.
Jika belum pernah memulai Cloud Shell, Anda akan melihat layar perantara (di paruh bawah) yang menjelaskan apa itu Cloud Shell. Jika demikian, klik Lanjutkan (dan Anda tidak akan pernah melihatnya lagi). Berikut tampilan layar sekali-tampil tersebut:
Perlu waktu beberapa saat untuk penyediaan dan terhubung ke Cloud Shell.
Mesin virtual ini berisi semua alat pengembangan yang Anda perlukan. Layanan ini menawarkan direktori beranda tetap sebesar 5 GB dan beroperasi di Google Cloud, sehingga sangat meningkatkan performa dan autentikasi jaringan. Sebagian besar pekerjaan Anda dalam codelab ini dapat dilakukan hanya dengan browser atau Chromebook.
Setelah terhubung ke Cloud Shell, Anda akan melihat bahwa Anda sudah diautentikasi dan project sudah ditetapkan ke project ID Anda.
- Jalankan perintah berikut di Cloud Shell untuk mengonfirmasi bahwa Anda telah diautentikasi:
gcloud auth list
Output perintah
Credentialed Accounts
ACTIVE ACCOUNT
* <my_account>@<my_domain.com>
To set the active account, run:
$ gcloud config set account `ACCOUNT`
gcloud config list project
Output perintah
[core] project = <PROJECT_ID>
Jika tidak, Anda dapat menyetelnya dengan perintah ini:
gcloud config set project <PROJECT_ID>
Output perintah
Updated property [core/project].
3. Menyediakan resource Pub/Sub
Pertama, kita perlu menyiapkan topik dan langganan Cloud Pub/Sub. Dalam aplikasi ini, kita akan memublikasikan info pendaftaran ke topik Pub/Sub; informasi tersebut kemudian dibaca dari topik ini dan dipertahankan ke database.
Dalam tutorial ini, kita akan mengandalkan Cloud Shell untuk menyediakan resource. Perhatikan bahwa pengguna juga dapat mengonfigurasi resource Pub/Sub melalui bagian Cloud Pub/Sub di Konsol Google Cloud.
Di terminal Cloud Shell, aktifkan terlebih dahulu Pub/Sub API.
$ gcloud services enable pubsub.googleapis.com
Selanjutnya, kita akan membuat topik Pub/Sub bernama registrations untuk aplikasi ini. Info pendaftaran yang dikirimkan melalui aplikasi akan dipublikasikan ke topik ini.
$ gcloud pubsub topics create registrations
Terakhir, buat langganan untuk topik. Langganan Pub/Sub memungkinkan Anda menerima pesan dari suatu topik.
$ gcloud pubsub subscriptions create registrations-sub --topic=registrations
Anda kini telah selesai membuat topik dan langganan Cloud Pub/Sub untuk aplikasi Anda.
4. Membuat Instance dan Database Cloud SQL (MySQL)
Untuk aplikasi contoh, kita juga perlu menyiapkan instance database untuk menyimpan informasi pendaftar. Langkah ini juga akan mengandalkan terminal Cloud Shell untuk menyediakan resource Cloud SQL. Perhatikan bahwa Anda juga dapat melihat dan mengonfigurasi instance Cloud SQL melalui Konsol Google Cloud.
Pertama, aktifkan Cloud SQL Admin API.
$ gcloud services enable sqladmin.googleapis.com
Selanjutnya, kita akan menyediakan instance Cloud SQL (MySQL). Perintah ini mungkin memerlukan waktu beberapa saat.
$ gcloud sql instances create codelab-instance --region=us-east1
Setelah berhasil membuat instance Cloud SQL, buat database baru di instance Anda yang bernama registrants.
$ gcloud sql databases create registrants --instance codelab-instance
Anda kini telah menyelesaikan penyiapan instance dan database Cloud SQL untuk aplikasi Anda.
5. Menginisialisasi Aplikasi Spring Boot
Sekarang kita siap untuk mulai menulis aplikasi. Langkah selanjutnya akan terus menggunakan Cloud Shell yang dijelaskan dalam langkah penyiapan.
Pertama, kita akan menggunakan Initializr untuk membuat kode kerangka project. Di jendela Cloud Shell, jalankan:
$ 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
Perintah ini menghasilkan penyiapan project Maven awal serta kode scaffolding untuk aplikasi Anda di direktori registrations-codelab/. Bagian berikut menjelaskan pengeditan kode yang diperlukan untuk menghasilkan aplikasi yang berfungsi.
Editor Kode Cloud Shell
Cara termudah untuk mulai mengubah dan melihat kode di lingkungan Cloud Shell adalah dengan menggunakan Editor Kode Cloud Shell bawaan.
Setelah Anda membuka instance Cloud Shell, klik ikon Pensil untuk membuka editor kode. Editor akan memungkinkan Anda mengubah file project yang dihasilkan oleh Initialzr secara langsung.

6. Konfigurasi Database
Pertama, konfigurasi aplikasi Anda agar dapat terhubung ke database Cloud MySQL yang Anda siapkan. Library Spring Cloud GCP menawarkan Cloud MySQL starter yang menyediakan dependensi yang diperlukan untuk terhubung ke instance Cloud MySQL.
Tambahkan dependensi spring-cloud-gcp-starter-sql-mysql ke pom.xml project:
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>
Selain itu, Anda perlu mengubah file konfigurasi application.properties untuk menjelaskan konfigurasi database Anda. Salin properti berikut ke dalam file application.properties Anda.
Temukan nama koneksi instance ke database Anda:
$ gcloud sql instances describe codelab-instance \ --format 'value(connectionName)'
Output ini akan digunakan dalam file application.properties untuk mengonfigurasi informasi koneksi.
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
Satu-satunya properti yang harus Anda ubah adalah nama koneksi instance. Nilai ini harus diformat sebagai nilai yang dipisahkan dengan tanda titik dua dengan format: YOUR_GCP_PROJECT_ID:REGION:DATABASE_INSTANCE_NAME.
7. Membuat Konten Statis
Pertama, kita akan membuat frontend untuk aplikasi kita. Aplikasi harus memiliki formulir yang memungkinkan seseorang mendaftarkan individu dan juga tampilan yang menampilkan semua pendaftar yang berhasil.
Untuk halaman beranda, buat index.html yang berisi formulir pendaftaran.
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>
Selanjutnya, kita akan membuat template Thymeleaf bernama registrants.html untuk menampilkan pengguna terdaftar. Thymeleaf adalah framework template yang kami gunakan untuk membuat dan menayangkan HTML yang dibuat secara dinamis. Anda akan melihat bahwa template terlihat seperti HTML, kecuali memiliki beberapa elemen markdown tambahan untuk menangani konten dinamis. Template ini menerima satu parameter bernama personsList yang berisi semua pendaftar yang terdaftar melalui aplikasi.
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>
Pada tahap ini, Anda dapat memverifikasi bahwa konten statis sedang ditayangkan.
Buat dan jalankan aplikasi menggunakan Maven:
$ ./mvnw spring-boot:run
Klik tombol pratinjau di jendela Cloud Shell dan pastikan Anda melihat halaman beranda dirender. Namun, tidak ada fungsi di UI yang akan berfungsi karena kita tidak memiliki pengontrol web. Hal ini akan ditambahkan pada langkah berikutnya.

Setelah melihat pratinjau aplikasi, tekan CTRL+C untuk menghentikan aplikasi.
8. Mengirim Pendaftar ke Topik Pub/Sub
Pada langkah ini, kita akan menerapkan fitur yang memublikasikan pendaftar yang dikirimkan melalui formulir web ke topik Cloud Pub/Sub.
Menambahkan Class Data
Pertama, kita akan membuat beberapa class data Kotlin; class ini akan menjadi entity JPA kita dan juga bertindak sebagai representasi perantara pendaftar yang dikirimkan melalui formulir.
Dalam paket demo, tambahkan dua file baru: class Person dan PersonRepository Spring Data. Kedua class ini akan memungkinkan kita menyimpan dan mengambil entri pendaftaran dengan mudah dari database MySQL menggunakan 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>
Menambahkan Pengontrol Web
Selanjutnya, kita akan membuat class Controller yang memproses pendaftar dari formulir dan mengirimkan informasi ke topik Cloud Pub/Sub yang Anda buat sebelumnya. Pengontrol ini membuat dua endpoint:
/registerPerson: Endpoint POST tempat info pendaftar dikirimkan, lalu dikirim ke topik Pub/Sub. Dalam fungsiregisterPerson(..), info pendaftar dikirim ke topik Pub/Sub menggunakanPubSubTemplate, class praktis dari integrasi Spring Cloud GCP Pub/Sub yang meminimalkan kode boilerplate yang diperlukan untuk mulai berinteraksi dengan Cloud Pub/Sub./registrants: Menampilkan semua pendaftar yang berhasil terdaftar dalam database. Informasi ini diambil dari instance MySQL menggunakan repositori Spring Data yang kita buat pada langkah sebelumnya.
Buat class Pengontrol berikut dalam paket demo:
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))
}
}
Pengontrol membaca informasi pendaftar yang dikirimkan melalui formulir web, lalu memublikasikan informasi tersebut ke topik Pub/Sub.
Menambahkan Bean Pemeta Objek JSON
Anda mungkin telah melihat di Pengontrol bahwa kita memublikasikan objek Person ke topik Pub/Sub, bukan String. Hal ini dapat dilakukan karena kita memanfaatkan dukungan Spring Cloud GCP untuk payload JSON kustom yang akan dikirim ke topik - library memungkinkan Anda menserialisasi objek ke JSON, mengirim payload JSON ke topik, dan mendeserialisasi payload saat diterima.
Untuk memanfaatkan fitur ini, kita harus menambahkan bean ObjectMapper ke konteks aplikasi Anda. Bean ObjectMapper ini akan digunakan untuk melakukan serialisasi objek ke dan dari JSON saat aplikasi Anda mengirim dan menerima pesan. Di class DemoApplication.kt, tambahkan 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)
}
Pada tahap ini, Anda dapat mencoba menjalankan aplikasi lagi dengan menjalankan:
$ ./mvnw spring-boot:run
Dari formulir web di halaman utama, aplikasi kini akan mengirimkan informasi ke topik Pub/Sub yang Anda buat. Namun, kode tersebut belum melakukan apa pun yang berguna karena kita masih perlu membaca dari topik Pub/Sub tersebut. Hal ini akan dilakukan pada langkah berikutnya.
9. Membaca Pendaftar dari Topik Pub/Sub
Pada langkah terakhir, kita akan memproses info pendaftar dari topik Pub/Sub dan menyimpan informasi ke database Cloud MySQL. Tindakan ini akan menyelesaikan aplikasi, sehingga Anda dapat mengirimkan pendaftar baru melalui formulir dan melihat semua pengguna terdaftar melalui endpoint /registrants.
Aplikasi ini akan memanfaatkan Spring Integration, yang menawarkan banyak abstraksi praktis untuk menangani pengiriman pesan. Kita akan menambahkan PubSubInboundChannelAdapter untuk memungkinkan kita membaca pesan dari topik Pub/Sub dan menempatkannya di pubsubInputChannel untuk diproses lebih lanjut. Kemudian, kita akan mengonfigurasi fungsi messageReceiver menggunakan @ServiceActivator agar dipanggil dengan pesan yang tiba di 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)
}
Pada tahap ini, Anda telah menyelesaikan penyiapan aplikasi. Untuk memverifikasi bahwa aplikasi berfungsi dengan benar, jalankan:
$ ./mvnw spring-boot:run
Klik tombol Pratinjau lagi dan coba daftarkan pengguna dengan mengisi formulir dan mengirimkannya.

Klik link Orang yang Terdaftar untuk memverifikasi bahwa pendaftar baru muncul dalam tabel.

Selamat, Anda sudah selesai! Hentikan aplikasi dengan menekan CTRL+C di jendela terminal.
10. Pembersihan
Untuk membersihkan lingkungan, Anda perlu menghapus topik Pub/Sub dan instance Cloud MySQL yang Anda buat.
Menghapus Instance Cloud MySQL
$ gcloud sql instances delete codelab-instance
Menghapus Resource Pub/Sub
$ gcloud pubsub subscriptions delete registrations-sub $ gcloud pubsub topics delete registrations
11. Selamat!
Anda kini telah menyelesaikan penulisan aplikasi Spring Kotlin yang terintegrasi dengan Cloud Pub/Sub dan Cloud SQL (MySQL).
Pelajari Lebih Lanjut
- Project Spring di GCP: http://cloud.spring.io/spring-cloud-gcp/
- Repositori GitHub Spring on GCP: https://github.com/GoogleCloudPlatform/spring-cloud-gcp
- Java di Google Cloud Platform: https://cloud.google.com/java/
- Contoh Aplikasi Kotlin menggunakan GCP: https://github.com/GoogleCloudPlatform/spring-cloud-gcp/tree/master/spring-cloud-gcp-kotlin-samples
Lisensi
Karya ini dilisensikan berdasarkan Lisensi Umum Creative Commons Attribution 2.0.