ืชื—ื™ืœืช ื”ืขื‘ื•ื“ื” ืขื Java

ื”ืžื“ืจื™ืš ื”ื–ื” ืžื™ื•ืขื“ ืœืžืฉืชืžืฉื™ื ื—ื“ืฉื™ื ื‘ืคื™ืชื•ื— ืืคืœื™ืงืฆื™ื•ืช ื‘ืขื ืŸ, ื›ืžื• ืžื”ื ื“ืกื™ื ื•ืžืคืชื—ื™ ืืชืจื™ื, ืฉืจื•ืฆื™ื ืœืœืžื•ื“ ืžื•ืฉื’ื™ ืžืคืชื— ื‘ืคื™ืชื•ื— ืืคืœื™ืงืฆื™ื•ืช ื‘ื”ืงืฉืจ ืฉืœ Google Cloud.

ืžื˜ืจื•ืช

  • ืœื•ืžื“ื™ื ืขืœ Google Cloud ื›ืœื™ื ื‘ืกื™ืกื™ื™ื, ื›ืžื• Google Cloud ืžืกื•ืฃ ื•-gcloud.
  • ืคื•ืจืกื™ื ืืช ื”ืืคืœื™ืงืฆื™ื” ื‘-Cloud Run.
  • ืฉืžื™ืจืช ื”ื ืชื•ื ื™ื ื‘ืืžืฆืขื•ืช Firestore.
  • ืื—ืกื•ืŸ ืฉืœ ืงื‘ืฆื™ื ืฉื”ื•ืขืœื• ื‘-Cloud Storage.
  • ืขื•ืงื‘ื™ื ืื—ืจื™ ื”ืืคืœื™ืงืฆื™ื” ื‘ืืžืฆืขื•ืช Google Cloud Observability.

ืขืœื•ื™ื•ืช

ื‘ืžืกืžืš ื”ื–ื” ืžืฉืชืžืฉื™ื ื‘ืจื›ื™ื‘ื™ื ื”ื‘ืื™ื ืฉืœ Google Cloud, ื•ื”ืฉื™ืžื•ืฉ ื‘ื”ื ื›ืจื•ืš ื‘ืชืฉืœื•ื:

ื”ื”ื•ืจืื•ืช ื‘ืžืกืžืš ื”ื–ื” ื ื•ืขื“ื• ืœื•ื•ื“ื ืฉื”ืฉื™ืžื•ืฉ ื‘ืžืฉืื‘ื™ื ื™ื”ื™ื” ื‘ืžืกื’ืจืช ื”ืžื’ื‘ืœื•ืช ืฉืœ ื”ืชื•ื›ื ื™ืช ื‘ื—ื™ื ื ืฉืœ Google Cloud. ื›ื“ื™ ืœื”ืขืจื™ืš ืืช ื”ื”ื•ืฆืื•ืช ื‘ื”ืชืื ืœืชื—ื–ื™ืช ื”ืฉื™ืžื•ืฉ ืฉืœื›ื, ืืชื ื™ื›ื•ืœื™ื ืœื”ื™ืขื–ืจ ื‘ืžื—ืฉื‘ื•ืŸ ื”ืขืœื•ื™ื•ืช.

ืžืฉืชืžืฉื™ื ื—ื“ืฉื™ื ืฉืœ Google Cloud ? ื™ื›ื•ืœ ืœื”ื™ื•ืช ืฉืืชื ื–ื›ืื™ื ืœืชืงื•ืคืช ื ื™ืกื™ื•ืŸ ื‘ื—ื™ื ื.

ื›ืฉืžืกื™ื™ืžื™ื ืืช ื”ืžืฉื™ืžื•ืช ืฉืžืชื•ืืจื•ืช ื‘ืžืกืžืš ื”ื–ื” ืืคืฉืจ ืœืžื—ื•ืง ืืช ื”ืžืฉืื‘ื™ื ืฉื™ืฆืจืชื ื›ื“ื™ ืœื”ื™ืžื ืข ืžื—ื™ื•ื‘ื™ื ื ื•ืกืคื™ื. ืžื™ื“ืข ื ื•ืกืฃ ื–ืžื™ืŸ ื‘ืงื˜ืข ื”ืกืจืช ื”ืžืฉืื‘ื™ื.

ืœืคื ื™ ืฉืžืชื—ื™ืœื™ื

  1. ื ื›ื ืกื™ื ืœื—ืฉื‘ื•ืŸ Google Cloud . ืื ืืชื ืžืฉืชืžืฉื™ื ื—ื“ืฉื™ื ื‘- Google Cloud, ืฆืจื• ื—ืฉื‘ื•ืŸ ื›ื“ื™ ืฉืชื•ื›ืœื• ืœื”ืขืจื™ืš ืืช ื”ื‘ื™ืฆื•ืขื™ื ืฉืœ ื”ืžื•ืฆืจื™ื ืฉืœื ื• ื‘ืชืจื—ื™ืฉื™ื ืžื”ืขื•ืœื ื”ืืžื™ืชื™. ืœืงื•ื—ื•ืช ื—ื“ืฉื™ื ืžืงื‘ืœื™ื ื‘ื—ื™ื ื ื’ื ืงืจื“ื™ื˜ ื‘ืฉื•ื•ื™ 300$ ืœื”ืจืฆื”, ืœื‘ื“ื™ืงื” ื•ืœืคืจื™ืกื” ืฉืœ ืขื•ืžืกื™ ื”ืขื‘ื•ื“ื”.
  2. In the Google Cloud console, on the project selector page, select or create a Google Cloud project.

    Roles required to select or create a project

    • Select a project: Selecting a project doesn't require a specific IAM role—you can select any project that you've been granted a role on.
    • Create a project: To create a project, you need the Project Creator role (roles/resourcemanager.projectCreator), which contains the resourcemanager.projects.create permission. Learn how to grant roles.

    Go to project selector

  3. Verify that billing is enabled for your Google Cloud project.

  4. In the Google Cloud console, on the project selector page, select or create a Google Cloud project.

    Roles required to select or create a project

    • Select a project: Selecting a project doesn't require a specific IAM role—you can select any project that you've been granted a role on.
    • Create a project: To create a project, you need the Project Creator role (roles/resourcemanager.projectCreator), which contains the resourcemanager.projects.create permission. Learn how to grant roles.

    Go to project selector

  5. Verify that billing is enabled for your Google Cloud project.

  6. ื›ื“ื™ ืœื™ืฆื•ืจ ืžืกื“ ื ืชื•ื ื™ื ืฉืœ Firestore ื‘ืžืฆื‘ Native, ืคื•ืขืœื™ื ืœืคื™ ื”ืฉืœื‘ื™ื ื”ื‘ืื™ื:
    1. ื ื›ื ืกื™ื ืœื“ืฃ Firestore create database ื‘ืžืกื•ืฃ Google Cloud .

      ืžืขื‘ืจ ืืœ ื™ืฆื™ืจืช ืžืกื“ ื ืชื•ื ื™ื ื‘-Firestore

    2. ื‘ืžืกืš Select a Cloud Firestore mode (ื‘ื—ื™ืจืช ืžืฆื‘ Cloud Firestore), ืœื•ื—ืฆื™ื ืขืœ Select Native Mode (ื‘ื—ื™ืจืช ืžืฆื‘ ืžืงื•ืจื™).
    3. ื‘ื•ื—ืจื™ื ืžื™ืงื•ื ืœืžืกื“ ื”ื ืชื•ื ื™ื ืฉืœ Firestore. ื”ื’ื“ืจืช ื”ืžื™ืงื•ื ื”ื–ื• ื”ื™ื ืžื™ืงื•ื ื‘ืจื™ืจืช ื”ืžื—ื“ืœ Google Cloud ืฉืœ ืžืฉืื‘ื™ื ื‘ Google Cloud ืคืจื•ื™ืงื˜ . ื”ืžื™ืงื•ื ื”ื–ื” ืžืฉืžืฉ ืืช Google Cloud ื”ืฉื™ืจื•ืชื™ื ื‘ืคืจื•ื™ืงื˜ Google Cloud ืฉื“ื•ืจืฉื™ื ื”ื’ื“ืจืช ืžื™ืงื•ื, ื‘ืžื™ื•ื—ื“ ืืช ืงื˜ื’ื•ืจื™ื™ืช Cloud Storage ืฉืžื•ื’ื“ืจืช ื›ื‘ืจื™ืจืช ืžื—ื“ืœ ื•ืืช ืืคืœื™ืงืฆื™ื™ืช Cloud Run.
    4. ืœื•ื—ืฆื™ื ืขืœ ื™ืฆื™ืจืช ืžืกื“ ื ืชื•ื ื™ื.
  7. ืžืคืขื™ืœื™ื ืืช Cloud Run Admin,โ€ Cloud Storage,โ€ Cloud Logging ื•-Error Reporting APIs, ืื ืื—ื“ ืžื”ื ืขื“ื™ื™ืŸ ืœื ืžื•ืคืขืœ.

    ืชืคืงื™ื“ื™ื ืฉื ื“ืจืฉื™ื ืœื”ืคืขืœืช ืžืžืฉืงื™ API

    ื›ื“ื™ ืœื”ืคืขื™ืœ ืžืžืฉืงื™ API, ื ื“ืจืฉืช ื”ื”ืจืฉืื” serviceusage.services.enable. ืื ื™ืฆืจืชื ืืช ื”ืคืจื•ื™ืงื˜, ืกื‘ื™ืจ ืœื”ื ื™ื— ืฉื›ื‘ืจ ื™ืฉ ืœื›ื ืืช ื”ื”ืจืฉืื” ื”ื–ื• ื“ืจืš ื”ืชืคืงื™ื“ 'ื‘ืขืœื™ื' (roles/owner). ืื—ืจืช, ืชื•ื›ืœื• ืœืงื‘ืœ ืืช ื”ื”ืจืฉืื” ื”ื–ื• ื“ืจืš ื”ืชืคืงื™ื“ 'ืื“ืžื™ืŸ ื‘ืžืžืฉืง Service Usage' (roles/serviceusage.serviceUsageAdmin). ืื™ืš ืžืงืฆื™ื ืชืคืงื™ื“ื™ื

    ื”ืคืขืœืช ืžืžืฉืงื™ ื”-API

  8. ืžืฉื›ืคืœื™ื ืืช ืžืื’ืจ ื”ื“ื•ื’ืžื” ื•ืคื•ืชื—ื™ื ืืช ืืคืœื™ืงืฆื™ื™ืช ื”ื“ื•ื’ืžื” ื‘-Cloud Shell:
    ืžืขื‘ืจ ืืœ Cloud Shell

    โ€ซCloud Shell ื ื•ืชืŸ ื’ื™ืฉื” ืœืžืฉืื‘ื™ื Google Cloud ืฉืœื›ื ื‘-Google Cloud ื‘ืžืžืฉืง ืฉื•ืจืช ืคืงื•ื“ื” ื™ืฉื™ืจื•ืช ืžื”ื“ืคื“ืคืŸ.

  9. ื›ืฉืžื•ืคื™ืขื” ื”ื”ื•ื“ืขื” ืขืœ ืฉื™ื‘ื•ื˜ ื”ืžืื’ืจ, ืœื•ื—ืฆื™ื ืขืœ ืื™ืฉื•ืจ.
  10. ื‘-Cloud Shell, ืžื’ื“ื™ืจื™ื ืืช ื”ื›ืœื™ gcloud ื›ืš ืฉื™ืฉืชืžืฉ ื‘ืคืจื•ื™ืงื˜ ื”ื—ื“ืฉ Google Cloud :

    # Configure gcloud for your project
    gcloud config set project PROJECT_ID

    ืžื—ืœื™ืคื™ื ืืช PROJECT_ID ื‘ืžื–ื”ื” Google Cloud ื”ืคืจื•ื™ืงื˜ ืฉื™ืฆืจืชื ื‘ืืžืฆืขื•ืช ืžืกื•ืฃ Google Cloud .

    โ€ซGoogle Cloud CLI ื”ื™ื ื”ื“ืจืš ื”ืขื™ืงืจื™ืช ืœืื™ื ื˜ืจืืงืฆื™ื” ืขื ืžืฉืื‘ื™ Google Cloud ืžืฉื•ืจืช ื”ืคืงื•ื“ื”. ื‘ืžื“ืจื™ืš ื”ื–ื” ื ืฉืชืžืฉ ื‘ื›ืœื™ gcloud ื›ื“ื™ ืœืคืจื•ืก ืืช ื”ืืคืœื™ืงืฆื™ื” ื•ืœืขืงื•ื‘ ืื—ืจื™ื”.

ื”ืคืขืœืช ื”ืืคืœื™ืงืฆื™ื”

  1. ืื ืืชื ื›ื‘ืจ ืžืฉืชืžืฉื™ื ื‘-Cloud Shell ื•ื”ื’ื“ืจืชื ืื•ืชื• ืœืฉื™ืžื•ืฉ ื‘-Java 11, ืชืฆื˜ืจื›ื• ืœืขื“ื›ืŸ ืืช ืžืฉืชื ื™ ื”ืกื‘ื™ื‘ื” ืฉืœ ื—ืœื•ืคื•ืช Java, โ€ JAVA_HOME ื•-PATH, ื›ื“ื™ ืœืฆื™ื™ืŸ ืืช Java 8.
  2. ืขื•ื‘ืจื™ื ืœืกืคืจื™ื™ื” bookshelf/1-cloud-run ื•ืžืจื™ืฆื™ื ืืช ื”ืืคืœื™ืงืฆื™ื”:
    โ€ซ
    GOOGLE_CLOUD_PROJECT=PROJECT_ID mvn -Plocal clean jetty:run-exploded
    
    ืžื—ืœื™ืคื™ื ืืช PROJECT_ID ื‘ืžื–ื”ื” ืฉืœ Google Cloud ื”ืคืจื•ื™ืงื˜ ืฉื™ืฆืจืชื.
  3. ื‘-Cloud Shell, ืœื•ื—ืฆื™ื ืขืœ ืชืฆื•ื’ื” ืžืงื“ื™ืžื” ื‘ืื™ื ื˜ืจื ื˜ , ื•ื‘ื•ื—ืจื™ื ื‘ืืคืฉืจื•ืช ืชืฆื•ื’ื” ืžืงื“ื™ืžื” ื‘ื™ืฆื™ืื” 8080. ื™ื™ืคืชื— ื—ืœื•ืŸ ื—ื“ืฉ ืขื ื”ืืคืœื™ืงืฆื™ื” ื”ืคื•ืขืœืช.

ืคืจื™ืกืช ื”ืืคืœื™ืงืฆื™ื” ื‘-Cloud Run

Google Cloud ื™ืฉ ื›ืžื” ืืคืฉืจื•ื™ื•ืช ืœื”ืจืฆืช ื”ืงื•ื“. ื‘ื“ื•ื’ืžื” ื”ื–ื•, ืžืฉืชืžืฉื™ื ื‘-Cloud Run ื›ื“ื™ ืœืคืจื•ืก ืืคืœื™ืงืฆื™ื” ื ื™ืชื ืช ืœื”ืจื—ื‘ื” ื‘- Google Cloud. โ€ซCloud Run ืœื ืžื—ื™ื™ื‘ ืืชื›ื ืœื ื”ืœ ืฉืจืชื™ื, ื•ื”ื•ื ืžืชืจื—ื‘ ืื•ื˜ื•ืžื˜ื™ืช ื›ื“ื™ ืœืชืžื•ืš ื‘ืขืœื™ื•ืช ื—ื“ื•ืช ื‘ืชื ื•ืขืช ื”ื’ื•ืœืฉื™ื.

ืคื•ืขืœื™ื ืœืคื™ ื”ื”ื•ืจืื•ืช ื‘ืžืืžืจ ืคืจื™ืกืช ื”ืืคืœื™ืงืฆื™ื” ื‘-Cloud Run.

ืื ื”ืคืจื™ืกื” ืžืฆืœื™ื—ื”, ืžื•ืฆื’ืช ื ืงื•ื“ืช ืงืฆื” ืœืืคืœื™ืงืฆื™ื” ืฉืคื•ืขืœืช ื‘-Cloud Run, ื‘ืคื•ืจืžื˜ ื”ื‘ื:

https://bookshelf-abcdefghij-uc.a.run.app

ื”ืืคืœื™ืงืฆื™ื” ืฉืœืš ื–ืžื™ื ื” ืขื›ืฉื™ื• ื‘ืงื™ืฉื•ืจ ื”ื–ื”, ืฉื ืงืจื ืžืขื›ืฉื™ื• YOUR_CLOUD_RUN_URL. ื‘ื“ืคื“ืคืŸ ื”ืื™ื ื˜ืจื ื˜, ืžื–ื™ื ื™ื ืืช ื›ืชื•ื‘ืช ื”-URL ื›ื“ื™ ืœื”ืฆื™ื’ ืืช ื”ืืคืœื™ืงืฆื™ื”.

ื“ืฃ ื”ื‘ื™ืช ืฉืœ ืืคืœื™ืงืฆื™ื™ืช ืžื“ืฃ ื”ืกืคืจื™ื

ืฉืžื™ืจืช ื”ื ืชื•ื ื™ื ื‘ืืžืฆืขื•ืช Firestore

ืื™ ืืคืฉืจ ืœืื—ืกืŸ ืžื™ื“ืข ื‘ืžื•ืคืขื™ื ืฉืœ Cloud Run, ื›ื™ ื”ืžื™ื“ืข ื”ื–ื” ืื•ื‘ื“ ืื ื”ืžื•ืคืข ืžื•ืคืขืœ ืžื—ื“ืฉ, ื•ื”ื•ื ืœื ืงื™ื™ื ื›ืฉื™ื•ืฆืจื™ื ืžื•ืคืขื™ื ื—ื“ืฉื™ื. ื‘ืžืงื•ื ื–ืืช, ืžืฉืชืžืฉื™ื ื‘ืžืกื“ ื ืชื•ื ื™ื ืฉื›ืœ ื”ืžื•ืคืขื™ื ืงื•ืจืื™ื ืžืžื ื• ื•ื›ื•ืชื‘ื™ื ืืœื™ื•.

โ€ซGoogle Cloud ื™ืฉ ื›ืžื” ืืคืฉืจื•ื™ื•ืช ืœืื—ืกื•ืŸ ื”ื ืชื•ื ื™ื. ื‘ื“ื•ื’ืžื” ื”ื–ื•, ืžืฉืชืžืฉื™ื ื‘-Firestore ื›ื“ื™ ืœืื—ืกืŸ ืืช ื”ื ืชื•ื ื™ื ืฉืœ ื›ืœ ืกืคืจ. โ€ซFirestore ื”ื•ื ืžืกื“ ื ืชื•ื ื™ื ืžื ื•ื”ืœ, ืœืœื ืฉืจืช (serverless) ื•ืœื ื™ื—ืกื™ (NoSQL) ืฉืœ ืžืกืžื›ื™ื, ืฉืžืืคืฉืจ ืœืื—ืกืŸ ื ืชื•ื ื™ื ื•ืœืฉืื•ืœ ืขืœื™ื”ื ืฉืื™ืœืชื•ืช. โ€ซFirestore ืžืชืจื—ื‘ ื‘ืื•ืคืŸ ืื•ื˜ื•ืžื˜ื™ ื›ื“ื™ ืœืขื ื•ืช ืขืœ ื”ืฆืจื›ื™ื ืฉืœ ื”ืืคืœื™ืงืฆื™ื”, ื•ืžืชื›ื•ื•ืฅ ืœืืคืก ื›ืฉืœื ืžืฉืชืžืฉื™ื ื‘ื•. ืžื•ืกื™ืคื™ื ืืช ื”ืกืคืจ ื”ืจืืฉื•ืŸ.

  1. ื‘ื“ืคื“ืคืŸ ื”ืื™ื ื˜ืจื ื˜, ืขื•ื‘ืจื™ื ืืœ YOUR_CLOUD_RUN_URL.
  2. ื›ื“ื™ ืœื™ืฆื•ืจ ืกืคืจ ืœืืคืœื™ืงืฆื™ื” ืฉืคืจืกืชื, ืœื•ื—ืฆื™ื ืขืœ ื”ื•ืกืคืช ืกืคืจ.

    ื”ื•ืกืคืช ืกืคืจ ืœืืคืœื™ืงืฆื™ื™ืช ืžื“ืฃ ื”ืกืคืจื™ื
  3. ื‘ืฉื“ื” Title, ืžื–ื™ื ื™ื Moby Dick.
  4. ื‘ืฉื“ื” Author (ืžื—ื‘ืจ), ืžื–ื™ื ื™ื Herman Melville.
  5. ืœื•ื—ืฆื™ื ืขืœ Save. ืขื›ืฉื™ื• ื™ืฉ ืจืฉื•ืžื” ืœืืคืœื™ืงืฆื™ื™ืช ืžื“ืฃ ื”ืกืคืจื™ื.

    ืจืฉื•ืžื” ื‘ืืคืœื™ืงืฆื™ื™ืช ืžื“ืฃ ื”ืกืคืจื™ื ืฉืœ ืžื•ื‘ื™ ื“ื™ืง
  6. ื‘ืžืกื•ืฃ Google Cloud , ื›ื“ื™ ืœืจืขื ืŸ ืืช ื”ื“ืฃ ืฉืœ Firestore, ืœื•ื—ืฆื™ื ืขืœ Refresh . ื”ื ืชื•ื ื™ื ืžื•ืคื™ืขื™ื ื‘-Firestore. ืืคืœื™ืงืฆื™ื™ืช Bookshelf ืžืื—ืกื ืช ื›ืœ ืกืคืจ ื›ืžืกืžืš Firestore ืขื ืžื–ื”ื” ื™ื™ื—ื•ื“ื™, ื•ื›ืœ ื”ืžืกืžื›ื™ื ื”ืืœื” ืžืื•ื—ืกื ื™ื ื‘ืื•ืกืฃ Firestore. ืœืฆื•ืจืš ื”ืžื“ืจื™ืš ื”ื–ื”, ื”ืื•ืกืฃ ื ืงืจื books. ื“ื•ื’ืžื” ืœืžืกืžืš Firestore.

โ€ซFirestore ืžืื—ืกืŸ ืืช ื”ืกืคืจื™ื ื‘ืืžืฆืขื•ืช ืกืคืจื™ื™ืช ื”ืœืงื•ื— ืฉืœ Firestore. ื“ื•ื’ืžื” ืœืื—ื–ื•ืจ ืžืกืžืš Firestore:

public class FirestoreDao implements BookDao {
  private CollectionReference booksCollection;

  public FirestoreDao() {
    Firestore firestore = FirestoreOptions.getDefaultInstance().getService();
    booksCollection = firestore.collection("books");
  }

  private Book documentToBook(DocumentSnapshot document) {
    Map<String, Object> data = document.getData();
    if (data == null) {
      System.out.println("No data in document " + document.getId());
      return null;
    }

    return new Book.Builder()
        .author((String) data.get(Book.AUTHOR))
        .description((String) data.get(Book.DESCRIPTION))
        .publishedDate((String) data.get(Book.PUBLISHED_DATE))
        .imageUrl((String) data.get(Book.IMAGE_URL))
        .createdBy((String) data.get(Book.CREATED_BY))
        .createdById((String) data.get(Book.CREATED_BY_ID))
        .title((String) data.get(Book.TITLE))
        .id(document.getId())
        .build();
  }

  @Override
  public String createBook(Book book) {
    String id = UUID.randomUUID().toString();
    DocumentReference document = booksCollection.document(id);
    Map<String, Object> data = Maps.newHashMap();

    data.put(Book.AUTHOR, book.getAuthor());
    data.put(Book.DESCRIPTION, book.getDescription());
    data.put(Book.PUBLISHED_DATE, book.getPublishedDate());
    data.put(Book.TITLE, book.getTitle());
    data.put(Book.IMAGE_URL, book.getImageUrl());
    data.put(Book.CREATED_BY, book.getCreatedBy());
    data.put(Book.CREATED_BY_ID, book.getCreatedById());
    try {
      document.set(data).get();
    } catch (InterruptedException | ExecutionException e) {
      e.printStackTrace();
    }

    return id;
  }

  @Override
  public Book readBook(String bookId) {
    try {
      DocumentSnapshot document = booksCollection.document(bookId).get().get();

      return documentToBook(document);
    } catch (InterruptedException | ExecutionException e) {
      e.printStackTrace();
    }
    return null;
  }

  @Override
  public void updateBook(Book book) {
    DocumentReference document = booksCollection.document(book.getId());
    Map<String, Object> data = Maps.newHashMap();

    data.put(Book.AUTHOR, book.getAuthor());
    data.put(Book.DESCRIPTION, book.getDescription());
    data.put(Book.PUBLISHED_DATE, book.getPublishedDate());
    data.put(Book.TITLE, book.getTitle());
    data.put(Book.IMAGE_URL, book.getImageUrl());
    data.put(Book.CREATED_BY, book.getCreatedBy());
    data.put(Book.CREATED_BY_ID, book.getCreatedById());
    try {
      document.set(data).get();
    } catch (InterruptedException | ExecutionException e) {
      e.printStackTrace();
    }
  }

  @Override
  public void deleteBook(String bookId) {
    try {
      booksCollection.document(bookId).delete().get();
    } catch (InterruptedException | ExecutionException e) {
      e.printStackTrace();
    }
  }

  private List<Book> documentsToBooks(List<QueryDocumentSnapshot> documents) {
    List<Book> resultBooks = new ArrayList<>();
    for (QueryDocumentSnapshot snapshot : documents) {
      resultBooks.add(documentToBook(snapshot));
    }
    return resultBooks;
  }

  @Override
  public Result<Book> listBooks(String startTitle) {
    Query booksQuery = booksCollection.orderBy("title").limit(10);
    if (startTitle != null) {
      booksQuery = booksQuery.startAfter(startTitle);
    }
    try {
      QuerySnapshot snapshot = booksQuery.get().get();
      List<Book> results = documentsToBooks(snapshot.getDocuments());
      String newCursor = null;
      if (results.size() > 0) {
        newCursor = results.get(results.size() - 1).getTitle();
      }
      return new Result<>(results, newCursor);
    } catch (InterruptedException | ExecutionException e) {
      e.printStackTrace();
    }
    return new Result<>(Lists.newArrayList(), null);
  }

  @Override
  public Result<Book> listBooksByUser(String userId, String startTitle) {
    Query booksQuery =
        booksCollection.orderBy("title").whereEqualTo(Book.CREATED_BY_ID, userId).limit(10);
    if (startTitle != null) {
      booksQuery = booksQuery.startAfter(startTitle);
    }
    try {
      QuerySnapshot snapshot = booksQuery.get().get();
      List<Book> results = documentsToBooks(snapshot.getDocuments());
      String newCursor = null;
      if (results.size() > 0) {
        newCursor = results.get(results.size() - 1).getTitle();
      }
      return new Result<>(results, newCursor);
    } catch (InterruptedException | ExecutionException e) {
      e.printStackTrace();
    }
    return new Result<>(Lists.newArrayList(), null);
  }
}

ืžื™ื“ืข ื ื•ืกืฃ ืขืœ ืฉื™ืžื•ืฉ ื‘-Firestore ื–ืžื™ืŸ ื‘ืžืืžืจ ื‘ื ื•ืฉื ื”ื•ืกืคืช ื ืชื•ื ื™ื ืœ-Firestore.

ืื—ืกื•ืŸ ืฉืœ ืงื‘ืฆื™ื ืฉื”ื•ืขืœื• ื‘-Cloud Storage

ืื—ืจื™ ืฉืžื•ืกื™ืคื™ื ืกืคืจ, ืฆืจื™ืš ืœื”ื•ืกื™ืฃ ืืช ืชืžื•ื ืช ื”ืฉืขืจ ืฉืœื•. ืื™ ืืคืฉืจ ืœืื—ืกืŸ ืงื‘ืฆื™ื ื‘ืžื•ืคืขื™ื. ืžืกื“ ื ืชื•ื ื™ื ื”ื•ื ืœื ื”ื‘ื—ื™ืจื” ื”ื ื›ื•ื ื” ืœืงื•ื‘ืฆื™ ืชืžื•ื ื•ืช. ื‘ืžืงื•ื ื–ืืช, ืžืฉืชืžืฉื™ื ื‘-Cloud Storage.

โ€ซCloud Storage ื”ื•ื ืžืื’ืจ ื”-Blob ื”ืจืืฉื™ ืฉืœ Google Cloud. ืืชื ื™ื›ื•ืœื™ื ืœื”ืฉืชืžืฉ ื‘-Cloud Storage ื›ื“ื™ ืœืืจื— ื ื›ืกื™ ืืคืœื™ืงืฆื™ื•ืช ืฉืืชื ืจื•ืฆื™ื ืœืฉืชืฃ ื‘- Google Cloud. ื›ื“ื™ ืœื”ืฉืชืžืฉ ื‘-Cloud Storage, ืฆืจื™ืš ืœื™ืฆื•ืจ ืงื˜ื’ื•ืจื™ื” ืฉืœ Cloud Storage, ืฉื”ื™ื ืงื•ื ื˜ื™ื™ื ืจ ื‘ืกื™ืกื™ ืœืื—ืกื•ืŸ ื”ื ืชื•ื ื™ื.

  1. ื ื›ื ืกื™ื ืœื“ืฃ Cloud Storage Browser ื‘ืžืกื•ืฃ Google Cloud .

    ื›ื ื™ืกื” ืœื“ืฃ Cloud Storage Browser

  2. ืœื•ื—ืฆื™ื ืขืœ Create bucket.
  3. ื‘ืชื™ื‘ืช ื”ื“ื•-ืฉื™ื— Create bucket, ืžื–ื™ื ื™ื ืฉื ืœืงื˜ื’ื•ืจื™ื” ืขืœ ื™ื“ื™ ื”ื•ืกืคืช ืžื–ื”ื” ื”ืคืจื•ื™ืงื˜ Google Cloud ืœืžื—ืจื•ื–ืช _bucket, ื›ืš ืฉื”ืฉื ื™ื™ืจืื” ื›ืžื• YOUR_PROJECT_ID_bucket. ื”ืฉื ื”ื–ื” ืฆืจื™ืš ืœืขืžื•ื“ ื‘ื“ืจื™ืฉื•ืช ืœืžืชืŸ ืฉืžื•ืช ืฉืœ ืงื˜ื’ื•ืจื™ื•ืช. ืืคืฉืจ ืœื”ืฉืื™ืจ ืืช ื›ืœ ืฉืืจ ื”ืฉื“ื•ืช ื‘ืขืจื›ื™ ื‘ืจื™ืจืช ื”ืžื—ื“ืœ ืฉืœื”ื.
  4. ืœื•ื—ืฆื™ื ืขืœ ื™ืฆื™ืจื”.
  5. ืื—ืจื™ ืฉื™ื•ืฆืจื™ื ืืช ื”ืงื˜ื’ื•ืจื™ื”, ืฆืจื™ืš ืœื”ื’ื“ื™ืจ ืืช ื”ืื•ื‘ื™ื™ืงื˜ื™ื ื›ืš ืฉื™ื”ื™ื• ื ื’ื™ืฉื™ื ืœื›ื•ืœื ื›ื“ื™ ืฉื”ืžืฉืชืžืฉื™ื ื™ื•ื›ืœื• ืœืจืื•ืช ืื•ืชื. ื‘ืžืืžืจ ื”ื’ื“ืจืช ื ืชื•ื ื™ื ื›ืฆื™ื‘ื•ืจื™ื™ื ืžื•ืกื‘ืจ ืื™ืš ืœื”ื’ื“ื™ืจ ืืช ื”ืื•ื‘ื™ื™ืงื˜ื™ื ื›ื ื’ื™ืฉื™ื ื‘ืื•ืคืŸ ืฆื™ื‘ื•ืจื™.
  6. ืœื•ื—ืฆื™ื ืขืœ ืขืจื™ื›ืช ื”ืกืคืจ ื•ื‘ื•ื—ืจื™ื ืชืžื•ื ื” ืœื”ืขืœืื” ื›ื›ืจื™ื›ืช ื”ืกืคืจ. ืœื“ื•ื’ืžื”, ืืคืฉืจ ืœื”ืฉืชืžืฉ ื‘ืชืžื•ื ื” ื”ื–ื• ืฉืœ ื“ื•ืžื™ื™ืŸ ืฆื™ื‘ื•ืจื™:
    ื›ืจื™ื›ื” ืฉืœ ื”ืกืคืจ Moby Dick
  7. ืœื•ื—ืฆื™ื ืขืœ Save. ืชื•ืขื‘ืจื• ืœื“ืฃ ื”ื‘ื™ืช, ืฉื‘ื• ื™ืฉ ืจืฉื•ืžื” ืฉืœ ืืคืœื™ืงืฆื™ื™ืช ืžื“ืฃ ื”ืกืคืจื™ื.
    ืจืฉื•ืžื” ื‘ืืคืœื™ืงืฆื™ื™ืช ืžื“ืฃ ื”ืกืคืจื™ื ืฉืœ ืžื•ื‘ื™ ื“ื™ืง

ืืคืœื™ืงืฆื™ื™ืช ืžื“ืฃ ื”ืกืคืจื™ื ืฉื•ืœื—ืช ืงื‘ืฆื™ื ืฉื”ื•ืขืœื• ืœ-Cloud Storage ื‘ืืžืฆืขื•ืช ืกืคืจื™ื™ืช ื”ืœืงื•ื— ืฉืœ Cloud Storage.

public class CloudStorageHelper {

  private final Logger logger = Logger.getLogger(CloudStorageHelper.class.getName());
  private static Storage storage = null;

  static {
    storage = StorageOptions.getDefaultInstance().getService();
  }


  /**
   * Uploads a file to Google Cloud Storage to the bucket specified in the BUCKET_NAME environment
   * variable, appending a timestamp to end of the uploaded filename.
   */
  public String uploadFile(FileItemStream fileStream, final String bucketName)
      throws IOException, ServletException {
    checkFileExtension(fileStream.getName());

    System.out.println("FileStream name: " + fileStream.getName() + "\nBucket name: " + bucketName);

    DateTimeFormatter dtf = DateTimeFormat.forPattern("-YYYY-MM-dd-HHmmssSSS");
    DateTime dt = DateTime.now(DateTimeZone.UTC);
    String dtString = dt.toString(dtf);
    final String fileName = fileStream.getName() + dtString;

    // the inputstream is closed by default, so we don't need to close it here
    @SuppressWarnings("deprecation")
    BlobInfo blobInfo =
        storage.create(
            BlobInfo.newBuilder(bucketName, fileName)
                // Modify access list to allow all users with link to read file
                .setAcl(new ArrayList<>(Arrays.asList(Acl.of(User.ofAllUsers(), Role.READER))))
                .build(),
            fileStream.openStream());
    logger.log(
        Level.INFO, "Uploaded file {0} as {1}", new Object[] {fileStream.getName(), fileName});
    // return the public download link
    return blobInfo.getMediaLink();
  }


  /** Checks that the file extension is supported. */
  private void checkFileExtension(String fileName) throws ServletException {
    if (fileName != null && !fileName.isEmpty() && fileName.contains(".")) {
      String[] allowedExt = {".jpg", ".jpeg", ".png", ".gif"};
      for (String ext : allowedExt) {
        if (fileName.endsWith(ext)) {
          return;
        }
      }
      throw new ServletException("file must be an image");
    }
  }
}

ืžื™ื“ืข ื ื•ืกืฃ ืขืœ ื”ืฉื™ืžื•ืฉ ื‘-Cloud Storage ื–ืžื™ืŸ ื‘ืžืืžืจ ืžื‘ื•ื ืœ-Cloud Storage.

ืžืขืงื‘ ืื—ืจื™ ื”ืืคืœื™ืงืฆื™ื” ื‘ืืžืฆืขื•ืช Google Cloud Observability

ืคืจืกืชื ืืช ื”ืืคืœื™ืงืฆื™ื”, ื•ื™ืฆืจืชื ื•ืฉื™ื ื™ืชื ืกืคืจื™ื. ื›ื“ื™ ืœืขืงื•ื‘ ืื—ืจื™ ื”ืื™ืจื•ืขื™ื ื”ืืœื” ืืฆืœ ื”ืžืฉืชืžืฉื™ื, ืฆืจื™ืš ืœื”ืฉืชืžืฉ ื‘ื ื™ื”ื•ืœ ื‘ื™ืฆื•ืขื™ ืืคืœื™ืงืฆื™ื•ืช.

ืžืขืงื‘ ืื—ืจื™ ื™ื•ืžื ื™ื ื‘ืืžืฆืขื•ืช Cloud Logging

  1. ื‘ Google Cloud, ืขื•ื‘ืจื™ื ืืœ Logs Explorer.

    ื›ื ื™ืกื” ืœื“ืฃ Logs Explorer

    ืืชื ื™ื›ื•ืœื™ื ืœืขืงื•ื‘ ืื—ืจื™ ื”ืืคืœื™ืงืฆื™ื” ื‘ื–ืžืŸ ืืžืช. ืื ื ืชืงืœืชื ื‘ื‘ืขื™ื•ืช ื‘ืืคืœื™ืงืฆื™ื”, ื–ื” ืื—ื“ ื”ืžืงื•ืžื•ืช ื”ืจืืฉื•ื ื™ื ืฉื›ื“ืื™ ืœื‘ื“ื•ืง.

    Stackdriver Log Viewer
  2. ื‘ืจืฉื™ืžื” ื”ื ืคืชื—ืช Resource, ื‘ื•ื—ืจื™ื ื‘ืืคืฉืจื•ืช Cloud Run Revision, bookshelf.

ืžืขืงื‘ ืื—ืจ ืฉื’ื™ืื•ืช ื‘ืืžืฆืขื•ืช Error Reporting

  1. ื ื›ื ืกื™ื ืœื“ืฃ Error Reporting ื‘ืžืกื•ืฃ Google Cloud .
    ืžืขื‘ืจ ืœื“ืฃ Error Reporting
    ื‘ื“ืฃ Error Reporting ืžื•ืฆื’ื•ืช ืฉื’ื™ืื•ืช ื•ื—ืจื™ื’ื™ื ื‘ืืคืœื™ืงืฆื™ื”, ื•ืืคืฉืจ ืœื”ื’ื“ื™ืจ ื”ืชืจืื•ืช ืœื’ื‘ื™ื”ื.
  2. ื‘ื“ืคื“ืคืŸ, ืขื•ื‘ืจื™ื ืืœ /errors ื›ืชื•ื‘ืช ื”-URL ื‘ืืคืœื™ืงืฆื™ื”.
    YOUR_CLOUD_RUN_URL/errors

    ืคืขื•ืœื” ื–ื• ื™ื•ืฆืจืช ื—ืจื™ื’ื” ื—ื“ืฉื” ืœื‘ื“ื™ืงื” ื•ืฉื•ืœื—ืช ืื•ืชื” ืืœ Google Cloud Observability.

  3. ื‘ืžืกื•ืฃ Google Cloud , ื—ื•ื–ืจื™ื ืœื“ืฃ Error Reporting, ื•ืื—ืจื™ ื›ืžื” ืจื’ืขื™ื ื”ืฉื’ื™ืื” ื”ื—ื“ืฉื” ืชื•ืคื™ืข. ืœื•ื—ืฆื™ื ืขืœ ื˜ืขื™ื ื” ืื•ื˜ื•ืžื˜ื™ืช ืžื—ื“ืฉ ื›ื“ื™ ืฉืœื ืชืฆื˜ืจื›ื• ืœืจืขื ืŸ ืืช ื”ื“ืฃ ื‘ืื•ืคืŸ ื™ื“ื ื™.

    ื”ื•ื“ืขืช ืฉื’ื™ืื” ืž-Error Reporting.

ื”ืกืจืช ื”ืžืฉืื‘ื™ื

ื›ื“ื™ ืœื”ื™ืžื ืข ืžื—ื™ื•ื‘ื™ื ื‘ื—ืฉื‘ื•ืŸ Google Cloud ื‘ื’ืœืœ ื”ืฉื™ืžื•ืฉ ื‘ืžืฉืื‘ื™ื ืฉื ืขืฉื” ื‘ืžืกื’ืจืช ื”ืžื“ืจื™ืš ื”ื–ื”, ืืคืฉืจ ืœืžื—ื•ืง ืืช ื”ืคืจื•ื™ืงื˜ ืฉืžื›ื™ืœ ืืช ื”ืžืฉืื‘ื™ื, ืื• ืœื”ืฉืื™ืจ ืืช ื”ืคืจื•ื™ืงื˜ ื•ืœืžื—ื•ืง ืืช ื”ืžืฉืื‘ื™ื ื‘ื ืคืจื“.

ืžื—ื™ืงืช ื”ืคืจื•ื™ืงื˜

  1. ื‘ืžืกื•ืฃ Google Cloud , ื ื›ื ืกื™ื ืœื“ืฃ Manage resources.

    ื›ื ื™ืกื” ืœื“ืฃ Manage resources

  2. ื‘ืจืฉื™ืžืช ื”ืคืจื•ื™ืงื˜ื™ื, ื‘ื•ื—ืจื™ื ืืช ื”ืคืจื•ื™ืงื˜ ืฉืจื•ืฆื™ื ืœืžื—ื•ืง ื•ืœื•ื—ืฆื™ื ืขืœ Delete.
  3. ื›ื“ื™ ืœืžื—ื•ืง ืืช ื”ืคืจื•ื™ืงื˜, ื›ื•ืชื‘ื™ื ืืช ืžื–ื”ื” ื”ืคืจื•ื™ืงื˜ ื‘ืชื™ื‘ืช ื”ื“ื•-ืฉื™ื— ื•ืœื•ื—ืฆื™ื ืขืœ Shut down.

ื”ืžืืžืจื™ื ื”ื‘ืื™ื