In this lab, you develop a backend service for an online Quiz application to process user feedback and save scores.
The Quiz application has two parts, the web application that will run in the first Cloud shell window and the worker application that runs in the second Cloud Shell window.
Web application: manages the logic of sending the user's feedback to a pub/sub topic.
Worker application: listens to the feedback provided by the user to eventually perform sentiment analysis and store them in a database (Cloud Spanner).
This process takes advantage of Google Cloud Platform (GCP) products and services:
Cloud Pub/Sub: The Topic alerts and provides the subscribing worker application to new scores and feedback for analysis.
Cloud Natural Language: Provides sentiment analysis on the feedback.
Cloud Spanner: Database for the Quiz application.
Objectives
In this lab, you will learn how to perform the following tasks:
Create and publish messages to a Cloud Pub/Sub topic.
Subscribe to the topic to receive messages in a separate worker application.
Perform sentiment analysis on feedback.
Create a Cloud Spanner database instance and schema, then insert data into the database.
Setup and requirements
For each lab, you get a new Google Cloud project and set of resources for a fixed time at no cost.
Sign in to Qwiklabs using an incognito window.
Note the lab's access time (for example, 1:15:00), and make sure you can finish within that time.
There is no pause feature. You can restart if needed, but you have to start at the beginning.
When ready, click Start lab.
Note your lab credentials (Username and Password). You will use them to sign in to the Google Cloud Console.
Click Open Google Console.
Click Use another account and copy/paste credentials for this lab into the prompts.
If you use other credentials, you'll receive errors or incur charges.
Accept the terms and skip the recovery resource page.
Activate Google Cloud Shell
Google Cloud Shell is a virtual machine that is loaded with development tools. It offers a persistent 5GB home directory and runs on the Google Cloud.
Google Cloud Shell provides command-line access to your Google Cloud resources.
In Cloud console, on the top right toolbar, click the Open Cloud Shell button.
Click Continue.
It takes a few moments to provision and connect to the environment. When you are connected, you are already authenticated, and the project is set to your PROJECT_ID. For example:
gcloud is the command-line tool for Google Cloud. It comes pre-installed on Cloud Shell and supports tab-completion.
You can list the active account name with this command:
[core]
project = qwiklabs-gcp-44776a13dea667a6
Note:
Full documentation of gcloud is available in the
gcloud CLI overview guide
.
Task 1. Prepare the Quiz application
In this section, you access Cloud Shell, clone the git repository containing the Quiz application, configure environment variables, and run the application.
Clone source code in Cloud Shell
Enter the following command to clone the repository for the class:
The application is running when you see output similar to the following:
20:55:20.756 [restartedMain] INFO c.g.training.appdev.QuizApplication - Started QuizApplication in 20:55:20.756
Set up the worker application
Click Open a new tab on the right of the Cloud Shell tab to open a second Cloud Shell window.
Enter the following command to change the working directory:
cd ~/pubsub-languageapi-spanner/start
Prepare the environment in the second Cloud Shell window:
. prepare_worker_environment.sh
This script file:
Exports environment variables GCLOUD_PROJECT and GCLOUD_BUCKET.
Creates and configures a GCP Service Account.
Prints out the Google Cloud Platform Project ID.
Now start the worker application:
mvn exec:java@worker
Review the Quiz application
Still in the second Cloud Shell window, click Web preview > Preview on port 8080 to preview the Quiz application.
In the navigation bar, click Take Test.
Click Places.
Answer the question.
After you answer the question, you should see a final screen inviting you to submit feedback.
Quiz takers can select a rating and enter feedback.
Return Cloud Shell. Press Ctrl+C in the first and second windows to stop the web and worker applications.
Task 2. Examine the Quiz application code
In this section you examine the file structure and the files that impact the Quiz application.
In this lab you'll view and edit files. You can use the shell editors that are installed on Cloud Shell, such as nano or vim, or use the Cloud Shell code editor. This lab uses the Cloud Shell code editor.
Launch the Cloud Shell Editor
In the Cloud Shell, click Open Editor.
Review the GCP application code structure
Navigate to the /pubsub-languageapi-spanner/start folder using the file browser panel on the left side of the editor.
Now expand the /src/main/java/com/google/training/appdev folder. All Java code paths are relative to this folder.
Select the Feedback.java file in the .../services/gcp/domain folder.
This file contains a model class that represents the feedback submitted by quiz takers.
Select the PublishService.java file in the .../services/gcp/pubsub folder.
This file contains a service class that allows applications to publish feedback messages to a Cloud Pub/Sub topic.
Select the LanguageService.java file in the .../services/gcp/languageapi folder.
This file contains a service class that allows users to send text to the Cloud Natural Language ML API and to receive the sentiment score from the API.
Select the SpannerService.java file in the .../services/gcp/spanner folder.
This file contains a service class that allows users to save the feedback and Natural Language API response data in a Cloud Spanner database instance.
Review the web and backend application code
Select the QuizEndpoint.java file in the .../apifolder.
The handler for POST messages sent to the /api/quizzes/feedback/:quiz route publishes the feedback data received from the client to Pub/Sub.
Select the ConsoleApp.java file in the .../backend folder.
This file runs as a separate console application to consume the messages delivered to a Pub/Sub subscription.
Task 3. Working with Cloud Pub/Sub
The Quiz application uses a Pub/Sub function to retrieve answers and feedback that a user inputs through the quiz interface.
In this section, you create a Cloud Pub/Sub topic and subscription in your GCP project, then publish and retrieve a message.
Create a Cloud Pub/Sub topic
In the Console, open the Navigation menu > View All Products. In the Analytics section, click Pub/Sub > Topics, and then click Create topic.
Set the Topic ID to feedback, and then click Create.
The Topic details view opens:
Create a Cloud Pub/Sub subscription
Return to the second Cloud Shell window.
Enter the following command to create a Cloud Pub/Sub subscription named cloud-shell-subscription against the feedback topic:
gcloud pubsub subscriptions create cloud-shell-subscription --topic feedback
Note: If you receive an error about the active account not having valid credentials, wait for a minute and try the command again.
Publish a message to a Cloud Pub/Sub topic
Publish a "Hello World" message into the feedback topic in the second Cloud Shell window:
gcloud pubsub topics publish feedback --message="Hello World"
Retrieve a message from a Cloud Pub/Sub subscription
To pull the message from the feedback topic with automatic acknowledgement of the message in the second Cloud Shell window:
Task 4. Publish messages to Cloud Pub/Sub programmatically
In this section, you write code to publish messages to Cloud Pub/Sub.
Note: Update code within the sections marked as follows:
// TODO
// END TODO
To maximize your learning, review the code, inline comments, and related API documentation.
Publish a Pub/Sub message
Open the .../services/gcp/pubsub/PublishService.java file in the code editor.
Update the file by adding code as directed.
Declare two static final strings for the PROJECT_ID and TOPIC_NAME:
// TODO: Declare and initialize two Strings,
// PROJECT_ID and TOPIC_NAME
private static final String PROJECT_ID = ServiceOptions.getDefaultProjectId();
private static final String TOPIC_NAME = "feedback";
// END TODO
Move to the publishFeedback(...) methodand create a TopicName object using the PROJECT_ID and TOPIC_NAME strings.
The topic name references the Cloud Pub/Sub topic you just created:
// TODO: Create a TopicName object
// for the feedback topic in the project
TopicName topicName = TopicName.of(PROJECT_ID, TOPIC_NAME);
// END TODO
Declare a Publisher object and set it to null:
// TODO: Declare a publisher for the topic
Publisher publisher = null;
// END TODO
It will be initialized in the try block that follows.
Move to the try block, and initialize the publisher object using its builder:
// TODO: Initialize the publisher
// using a builder and the topicName
publisher = Publisher.newBuilder(topicName).build();
// END TODO
Copy the JSON serialized feedbackMessage string to a ByteString:
// TODO: Copy the serialized message
// to a byte string
ByteString data = ByteString.copyFromUtf8(feedbackMessage);
// END TODO
Declare a PubsubMessage object; initialize the message using its builder:
// TODO: Create a Pub/Sub message using a
// builder; set the message data
PubsubMessage pubsubMessage = PubsubMessage.newBuilder().setData(data).build();
// END TODO
Use the publisher to publish the message, assign the return value to the message ID future object:
// TODO: Publish the message,
// assign to the messageIdFuture
messageIdFuture = publisher.publish(pubsubMessage);
// END TODO
Move to the finally block and retrieve the Pub/Sub messageId from the message ID future object:
// TODO: Get the messageId from
// the messageIdFuture
String messageId = messageIdFuture.get();
// END TODO
Complete the publishing code by shutting down the publisher:
// TODO: Shutdown the publisher
// to free up resources
if (publisher != null) {
publisher.shutdown();
}
// END TODO
Save services/gcp/pubsub/PublishService.java .
Write code to use the Pub/Sub publish functionality
In the .../api/QuizEndpoint.java file, declare a new PublishService field named publishService.
Apply the Spring @Autowired annotation:
// TODO: Declare the publishService
@Autowired
private PublishService publishService;
// END TODO
In the processFeedback(...) method that handles POST requests to the '/feedback/:quiz' route, invoke the publishService.publishFeedback(feedback) method:
// TODO: Publish the feedback to Pub/Sub
publishService.publishFeedback(feedback);
// END TODO
Save /api/QuizEndpoint.java.
Run the application and create a Pub/Sub message
In the first Cloud Shell window, restart the web application (if it is running, stop and start it):
mvn spring-boot:run
Preview the web application, click Take Test > Places.
Answer the question, select the rating, enter some feedback text, and click Send Feedback.
In the second Cloud Shell window, to pull a message from the cloud-shell-subscription:
Task 5. Subscribing to Cloud Pub/Sub topics programmatically
In this section you write the code to create a subscription and receive message notifications from a Cloud Pub/Sub topic to the worker application.
Write code to create a Cloud Pub/Sub subscription and receive messages
In the code editor open the ...backend/ConsoleApp.java file.
Update the file by adding code as directed.
Skip over the TODO blocks for languageService and spannerService. You'll return for those later.
In the main()method, create a SubscriptionName object representing a new subscription named "worker1-subscription":
// TODO: Create the Pub/Sub subscription name
ProjectSubscriptionName subscription =
ProjectSubscriptionName.of(projectId,
"worker1-subscription");
// END TODO
Create a SubscriptionAdminClient object using a try block:
// TODO: Create the subscriptionAdminClient
try (SubscriptionAdminClient subscriptionAdminClient =
SubscriptionAdminClient.create()) {
// TODO: create the Pub/Sub subscription
// using the subscription name and topic
subscriptionAdminClient.createSubscription(
subscription, topic,
PushConfig.getDefaultInstance(), 0);
// END TODO
}
// END TODO
Note: Also in the try block, use the subscription admin client to create a new subscription against the feedback topic. Don't forget the closing brace.
Move to the code that creates a MessageReceiver, and in the receiveMessage(...) override, extract the message data into a String:
// TODO: Extract the message data as a JSON String
String fb = message.getData().toStringUtf8();
// END TODO
Use the consumer to acknowledge the message:
// TODO: Ack the message
consumer.ack();
// END TODO
After the code that initializes an ObjectMapper, deserialize the JSON String message data into a feedback object:
// TODO: Deserialize the JSON String
// representing the feedback
// Print out the feedback
Feedback feedback = mapper.readValue(
fb, Feedback.class);
System.out.println("Feedback received: "
+ feedback);
// END TODO
After the block that creates the MessageReceiver, declare a Subscriber and initialize it to null.
Skip over a few TODO blocks and look for this one:
// TODO: Declare a subscriber
Subscriber subscriber = null;
// END TODO
Move to the try block, and initialize the Subscriber using its default builder. This requires the subscription and receiver:
// TODO: Initialize the subscriber using
// its default builder
// with a subscription and receiver
subscriber = Subscriber.newBuilder(
subscription, receiver).build();
// END TODO
Add a listener to the subscriber to display errors:
// TODO: Add a listener to the subscriber
subscriber.addListener(
new Subscriber.Listener() {
@Override
public void failed(
Subscriber.State from,
Throwable failure) {
System.err.println(failure);
}
},
MoreExecutors.directExecutor());
// END TODO
Start the subscriber:
// TODO: Start subscribing
subscriber.startAsync().awaitRunning();
// END TODO
Move to the final block. Write the code to stop the subscriber, and delete the subscription:
// TODO: Stop subscribing
if (subscriber != null) {
subscriber.stopAsync().awaitTerminated();
}
// END TODO
// TODO: Delete the subscription
try (SubscriptionAdminClient
subscriptionAdminClient =
SubscriptionAdminClient.create()) {
subscriptionAdminClient.deleteSubscription(
subscription);
}
// END TODO
Save backend/ConsoleApp.java.
Run the web and worker application and create a Pub/Sub message
In the first Cloud Shell window, stop and start the web application:
mvn spring-boot:run
In the second Cloud Shell window, start the worker application:
mvn compile exec:java@worker
In Cloud Shell, click Web preview > Preview on port 8080 to preview the quiz application.
Click Take Test.
Click Places.
Answer the question, select the rating, enter some feedback text, and then click Send Feedback.
Return to the second Cloud Shell window.
You should see that the worker application has received the feedback message via its handler and displayed it in the second Cloud Shell window. An example of a feedback message is as follows:
Feedback received: Feedback{email='app.dev.student@dummy.org', quiz='places', feedback='love the test', rating=5, timestamp=1527564677609, sentimentScore=0.0}
Note: You can safely ignore WARNING output related to An illegal reflective access operation.
Stop the web and console applications.
Task 6. Use the Cloud Natural Language API
In this section you write the code to perform sentiment analysis on the feedback text submitted by the user. For more information refer to Google Cloud Natural Language API.
Write code to invoke the Cloud Natural Language API
Return to the editor and open the LanguageService.java file in the services/gcp/languageapi folder.
Move to the analyzeSentiment(...) method, and create a LanguageServiceClient object in a try block.
In this step note that there is not a // END TODO in the content that you copy into the file:
// TODO: Create the LanguageServiceClient object
try (LanguageServiceClient language =
LanguageServiceClient.create()) {
Create a new Document object using its builder, and configure this object with the document content and type:
// TODO: Create a new Document object
// using the builder
// Set the content and type
Document doc = Document.newBuilder()
.setContent(feedback)
.setType(Document.Type.PLAIN_TEXT)
.build();
// END TODO
Use the Natural Language client object to analyze the sentiment of the document, assigning the result to a Sentiment object:
// TODO: Use the client to analyze
// the sentiment of the feedback
Sentiment sentiment = language
.analyzeSentiment(doc)
.getDocumentSentiment();
// END TODO
Then, return the sentiment score from the sentiment object:
// TODO: Return the sentiment score
return sentiment.getScore();
// END TODO
}
Don't forget the closing brace.
Save the file.
Write code to use the Natural Language API functionality
Return to the backend/ConsoleApp.java file.
Move to the main(...) method.
In the main()method, create a SubscriptionName object representing a new subscription named "worker2-subscription".
This replaces the "worker1-subscription".
// TODO: Create the Pub/Sub subscription name
ProjectSubscriptionName subscription =
ProjectSubscriptionName.of(projectId,
"worker2-subscription");
// END TODO
At the point indicated by the comments, create the LanguageService instance using its static create() method:
// TODO: Create the languageService
LanguageService languageService = LanguageService.create();
// END TODO
At the point indicated by the comments, use the languageService object to perform sentiment detection on the feedback:
// TODO: Use the Natural Language API to analyze sentiment
float sentimentScore = languageService.analyzeSentiment(
feedback.getFeedback());
// END TODO
Then, log the score to the console and assign a new score property to the feedback object:
// TODO: Set the feedback object sentiment score
feedback.setSentimentScore(sentimentScore);
System.out.println("Score is: " + sentimentScore);
// END TODO
Save the file.
Run the web and worker application and test the Natural Language API
Return to the first Cloud Shell window and restart the web application.
Switch to the second Cloud Shell window and restart the worker application.
Preview the web application, then click Take Test > Places.
Answer the questions, select the rating, enter some feedback text, and then click Send Feedback.
Return to the second Cloud Shell window.
The output shows the worker application invoked the Cloud Natural Language API and displays the sentiment score in the console next to Score is:.
For example:
Feedback received: Feedback{email='app.dev.student@dummy.org', quiz='places', feedback='loved the test', rating=1, timestamp=1570116062687, sentimentScore=0.0}
Score is: 0.8
Stop the web and worker applications.
Task 7. Persist data to Cloud Spanner
In this section you create a Cloud Spanner instance, database, and table. You then write the code to persist the feedback data into the database.
Create a Cloud Spanner instance
Return to the Cloud Console.
Open the Navigation menu > View All Products. In the Databases section, click Spanner.
Click CREATE A PROVISIONED INSTANCE.
Set Instance name to quiz-instance.
In the Choose a configuration section, select Region from the select a configuration dropdown menu.
Click Create.
Create a Cloud Spanner database and table
On the Instance details page for quiz-instance, click CREATE DATABASE.
For Database name, type quiz-database.
Under Define your schema in the text box, type the following SQL statement:
Note: Learn more about Cloud Spanner APIs from the APIs & reference reference.
For information about the specific APIs used in this section, on the left pane of the APIs & reference page, in the APIs and reference section, click Client libraries > Java reference.
Return to the code editor, and move to the insertFeedback(...) method in the ...services/gcp/spanner/SpannerService.java file.
Get a reference to Cloud Spanner:
// TODO: Get a reference to the Spanner API
SpannerOptions options =
SpannerOptions.newBuilder().build();
Spanner spanner = options.getService();
// END TODO
Get a reference to the Spanner database via the Database Id:
// TODO: Get a reference to the quiz-instance
// and its quiz-database
DatabaseId db = DatabaseId.of(
options.getProjectId(),
"quiz-instance",
"quiz-database");
// END TODO
Get a reference to the Cloud Spanner Database client:
// TODO: Get a client for the quiz-database
DatabaseClient dbClient =
spanner.getDatabaseClient(db);
// END TODO
Create a new List<Mutation> to reference all the changes that will be made to the database:
// TODO: Create a list to hold mutations
// against the database
List<Mutation> mutations = new ArrayList<>();
// END TODO
// END TODO
Add the Mutation that represents an insert against the feedback table, using data from the feedback object:
// TODO: Add an insert mutation
mutations.add(
// TODO: Build a new insert mutation
Mutation.newInsertBuilder("Feedback")
.set("feedbackId")
.to(feedback.getEmail() + '_' +
feedback.getQuiz() + "_" +
feedback.getTimestamp())
.set("email")
.to(feedback.getEmail())
.set("quiz")
.to(feedback.getQuiz())
.set("feedback")
.to(feedback.getFeedback())
.set("rating")
.to(feedback.getRating())
.set("score")
.to(
feedback.getSentimentScore())
.set("timestamp")
.to(feedback.getTimestamp())
.build());
// END TODO
Use the database client to write the mutations:
// TODO: Write the change to Spanner
dbClient.write(mutations);
// END TODO
Save the file.
Write code to use the Cloud Spanner functionality
Move to the main(...) method in the backend/ConsoleApp.java file.
In the main()method, create a SubscriptionName object representing a new subscription named "worker3-subscription".
This replaces the "worker2-subscription":
// TODO: Create the Pub/Sub subscription name
ProjectSubscriptionName subscription =
ProjectSubscriptionName.of(projectId,
"worker3-subscription");
// END TODO
At the point indicated by the comments, create the SpannerService instance:
// TODO: Create the spannerService
SpannerService spannerService = SpannerService.create();
// END TODO
At the point indicated by the comments, use the spannerService object to insert the feedback into the database and print out a message to the console:
// TODO: Insert the feedback into Cloud Spanner
spannerService.insertFeedback(feedback);
System.out.println("Feedback saved");
// END TODO
Save the file.
Run the web and worker application and test Cloud Spanner
Return to the first Cloud Shell window, start the web application.
Switch to the second Cloud Shell window, restart the worker application.
Preview the Quiz application, click Take Test > Places.
Answer the questions, select the rating, enter some feedback text, and then click Send Feedback.
Return to the second Cloud Shell window.
You should see that the worker application has invoked the Cloud Spanner API and displayed the message in the console window.
Return to the Console. Click Navigation menu > Spanner.
Select quiz-instance > quiz-database and click Spanner Studio from the left pane .
To execute a query, in the Query dialog, type SELECT * FROM Feedback, and then click Run:
SELECT * FROM Feedback
You should see the new feedback record in the Cloud Spanner database, including the message data from Cloud Pub/Sub and the Quiz score from the Cloud Natural Language API.
End your lab
When you have completed your lab, click End Lab. Google Cloud Skills Boost removes the resources you’ve used and cleans the account for you.
You will be given an opportunity to rate the lab experience. Select the applicable number of stars, type a comment, and then click Submit.
The number of stars indicates the following:
1 star = Very dissatisfied
2 stars = Dissatisfied
3 stars = Neutral
4 stars = Satisfied
5 stars = Very satisfied
You can close the dialog box if you don't want to provide feedback.
For feedback, suggestions, or corrections, please use the Support tab.
Copyright 2022 Google LLC All rights reserved. Google and the Google logo are trademarks of Google LLC. All other company and product names may be trademarks of the respective companies with which they are associated.
Moduły tworzą projekt Google Cloud i zasoby na określony czas.
Moduły mają ograniczenie czasowe i nie mają funkcji wstrzymywania. Jeśli zakończysz moduł, musisz go zacząć od początku.
Aby rozpocząć, w lewym górnym rogu ekranu kliknij Rozpocznij moduł.
Użyj przeglądania prywatnego
Skopiuj podaną nazwę użytkownika i hasło do modułu.
Kliknij Otwórz konsolę w trybie prywatnym.
Zaloguj się w konsoli
Zaloguj się z użyciem danych logowania do modułu. Użycie innych danych logowania może spowodować błędy lub naliczanie opłat.
Zaakceptuj warunki i pomiń stronę zasobów przywracania.
Nie klikaj Zakończ moduł, chyba że właśnie został przez Ciebie zakończony lub chcesz go uruchomić ponownie, ponieważ spowoduje to usunięcie wyników i projektu.
Ta treść jest obecnie niedostępna
Kiedy dostępność się zmieni, wyślemy Ci e-maila z powiadomieniem
Świetnie
Kiedy dostępność się zmieni, skontaktujemy się z Tobą e-mailem
Jeden moduł, a potem drugi
Potwierdź, aby zakończyć wszystkie istniejące moduły i rozpocząć ten
Aby uruchomić moduł, użyj przeglądania prywatnego
Uruchom ten moduł w oknie incognito lub przeglądania prywatnego. Dzięki temu unikniesz konfliktu między swoim kontem osobistym a kontem do nauki, co mogłoby spowodować naliczanie dodatkowych opłat na koncie osobistym.
In this lab, you enhance the online Quiz application by developing a backend service to process user feedback and save scores.
Czas trwania:
Konfiguracja: 1 min
·
Dostęp na 120 min
·
Ukończono w 120 min