Spring Framework provides a ResourceLoader abstraction to easily read and write files from various sources, such as the filesystem, the classpath, or the web. You simply need to specify the URI to the resource using the well known protocol prefix. For example, to access a file on the local filesystem, you would specify a URI like file:/data/config.yaml.

In this exercise, you will write a Spring Boot application that will access files stored in Google Cloud Storage (GCS) using the Spring Resource abstraction and the gs: protocol prefix.

You will use Cloud Shell and the Cloud SDK gcloud command.

What you'll learn

What you'll need

How will you use use this tutorial?

Read it through only Read it and complete the exercises

How would you rate your experience with building HTML/CSS web apps?

Novice Intermediate Proficient

How would you rate your experience with using Google Cloud Platform services?

Novice Intermediate Proficient

Codelab-at-a-conference setup

If you see a "request account button" at the top of the main Codelabs window, click it to obtain a temporary account. Otherwise ask one of the staff for a coupon with username/password.

These temporary accounts have existing projects that are set up with billing so that there are no costs associated for you with running this codelab.

Note that all these accounts will be disabled soon after the codelab is over.

Use these credentials to log into the machine or to open a new Google Cloud Console window https://console.cloud.google.com/. Accept the new account Terms of Service and any updates to Terms of Service.

Here's what you should see once logged in:

When presented with this console landing page, please select the only project available. Alternatively, from the console home page, click on "Select a Project" :

Google Cloud Shell

While Google Cloud can be operated remotely from your laptop, in this codelab we will be using Google Cloud Shell, a command line environment running in the Cloud.

Activate Google Cloud Shell

From the GCP Console click the Cloud Shell icon on the top right toolbar:

Then click "Start Cloud Shell":

It should only take a few moments to provision and connect to the environment:

This virtual machine is loaded with all the development tools you'll need. It offers a persistent 5GB home directory, and runs on the Google Cloud, greatly enhancing network performance and authentication. Much, if not all, of your work in this lab can be done with simply a browser or your Google Chromebook.

Once connected to Cloud Shell, you should see that you are already authenticated and that the project is already set to your PROJECT_ID.

Run the following command in Cloud Shell to confirm that you are authenticated:

gcloud auth list

Command output

Credentialed accounts:
 - <myaccount>@<mydomain>.com (active)
gcloud config list project

Command output

project = <PROJECT_ID>

If it is not, you can set it with this command:

gcloud config set project <PROJECT_ID>

Command output

Updated property [core/project].

After the Cloud Shell launches, you can start creating files and transferring them to GCS.

Let's first create a file called my-file.txt:

$ echo "Hello World from GCS" > my-file.txt

Now let's create a new unique bucket in GCS and transfer the file there using gsutil.

$ BUCKET=spring-bucket-$USER
$ gsutil makebucket gs://$BUCKET
$ gsutil copy my-file.txt gs://$BUCKET

Navigate to the Storage Browser in the GCP Console and verify that the bucket and the file are there.

Let's start writing the app by using the command line to generate a new Spring Boot application with Spring Initializr:

$ curl https://start.spring.io/starter.tgz \
-d dependencies=web,cloud-gcp-storage -d baseDir=spring-gcs | tar -xzvf -

Note that the Initializr will automatically add the spring-boot-starter-web and spring-cloud-gcp-starter-storage to our dependencies in the pom.xml of the template app.

Change to the directory of the template app:

$ cd spring-gcs

Build and run the app using Maven:

$ ./mvnw spring-boot:run

The app will start listening on port 8080. Open up a new Cloud Shell tab and run curl to access the app.

$ curl localhost:8080

You should get back a 404 response because the app doesn't do anything useful yet. Return back to the previous Cloud Shell tab where the app is running and kill it with Ctrl+C.

Now let's modify our Spring Boot app to access the my-file.txt file we previously stored in GCS. Our goal is to simply return the contents of the file via HTTP.

In the instructions below, we'll be using Vim to edit the files, but you can also use Nano or Emacs, or the built-in web editor in Cloud Shell:

$ cd ~/spring-gcs

Add a REST controller GcsController to the app.

$ vi src/main/java/com/example/demo/GcsController.java

Paste the following code, and don't forget to fix the resource URI with the bucket that you created previously. You can check the bucket by running echo $BUCKET command.


package com.example.demo;

import java.io.IOException;
import java.nio.charset.Charset;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.core.io.Resource;
import org.springframework.util.StreamUtils;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;

public class GcsController {

  private Resource gcsFile;

  @RequestMapping(value = "/", method = RequestMethod.GET)
  public String readGcsFile() throws IOException {
    return StreamUtils.copyToString(
        Charset.defaultCharset()) + "\n";

Build and run the app using Maven:

$ ./mvnw spring-boot:run

The app will start listening on port 8080. Open up a new Cloud Shell tab and run curl to access the app.

$ curl localhost:8080

You should now see the contents of the file returned from the app. Go back to the previous Cloud Shell tab where the app is running and kill it with Ctrl+C.

We've read the contents of the file in GCS and exposed it through a Spring REST Controller. Now, let's change the contents of the file by posting the new file content to the same HTTP endpoint.

We need to add another method to GcsController that will respond to HTTP POST and write the data to our file in GCS. This time we will cast the Spring Resource to WritableResource.

Update the GcsController with additional imports that we'll need:


import java.io.OutputStream;
import org.springframework.core.io.WritableResource;
import org.springframework.web.bind.annotation.RequestBody;

And now, let's and the new endpoint method to the controller.


public class GcsController {
  @RequestMapping(value = "/", method = RequestMethod.POST)
  String writeGcs(@RequestBody String data) throws IOException {
    try (OutputStream os = ((WritableResource) gcsFile).getOutputStream()) {
    return "file was updated\n";

Build and run the app using Maven:

$ ./mvnw spring-boot:run

The application will start listening on port 8080. Open up a new Cloud Shell tab and run curl to post a message to the application.

$ curl -d 'new message' -H 'Content-Type: text/plain' localhost:8080

You should see a confirmation that the contents of the file were updated.

However, let's verify by doing a GET.

$ curl localhost:8080

You should see the updated contents of the file returned from the app. Return back to the previous Cloud Shell tab where the app is running and kill it with Ctrl+C.

You've learned how to use the Spring Resource Abstraction to easily access files in Google Cloud Storage. You wrote a Spring Boot web app that can read and write to a file in GCS. You also learned about the Spring Boot Starter for Google Cloud Storage that enables this functionality.

Learn More


This work is licensed under a Creative Commons Attribution 2.0 Generic License.