Google Cloud Services - Firestore

This extension allows to inject a com.google.cloud.firestore.Firestore object inside your Quarkus application.

Be sure to have read the Google Cloud Services extension pack global documentation before this one, it contains general configuration and information.

Bootstrapping the project

First, we need a new project. Create a new project with the following command (replace the version placeholder with the correct one):

mvn io.quarkus:quarkus-maven-plugin:<quarkusVersion>:create \
    -DprojectGroupId=org.acme \
    -DprojectArtifactId=firestore-quickstart \
    -Dextensions="resteasy-reactive-jackson,quarkus-google-cloud-firestore"
cd firestore-quickstart

This command generates a Maven project, importing the Google Cloud Firestore extension.

If you already have your Quarkus project configured, you can add the quarkus-google-cloud-firestore extension to your project by running the following command in your project base directory:

./mvnw quarkus:add-extension -Dextensions="quarkus-google-cloud-firestore"

This will add the following to your pom.xml:

<dependency>
    <groupId>io.quarkiverse.googlecloudservices</groupId>
    <artifactId>quarkus-google-cloud-firestore</artifactId>
</dependency>

Some example

This is an example usage of the extension: we create a REST resource with a single endpoint that creates a 'persons' collection, inserts three persons in it, then search for persons with last name Doe and returns them.

import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.ExecutionException;
import java.util.stream.Collectors;

import javax.inject.Inject;
import javax.ws.rs.GET;
import javax.ws.rs.Path;
import javax.ws.rs.Produces;
import javax.ws.rs.core.MediaType;

import com.google.api.core.ApiFuture;
import com.google.api.core.ApiFutures;
import com.google.cloud.firestore.CollectionReference;
import com.google.cloud.firestore.Firestore;
import com.google.cloud.firestore.Query;
import com.google.cloud.firestore.QuerySnapshot;
import com.google.cloud.firestore.WriteResult;

@Path("/firestore")
public class FirestoreResource {
    @Inject
    Firestore firestore; // Inject Firestore

    @GET
    @Produces(MediaType.TEXT_PLAIN)
    public String firestore() throws ExecutionException, InterruptedException {
        // Insert 3 persons
        CollectionReference persons = firestore.collection("persons");
        List<ApiFuture<WriteResult>> futures = new ArrayList<>();
        futures.add(persons.document("1").set(new Person(1L, "John", "Doe")));
        futures.add(persons.document("2").set(new Person(2L, "Jane", "Doe")));
        futures.add(persons.document("3").set(new Person(3L, "Charles", "Baudelaire")));
        ApiFutures.allAsList(futures).get();

        // Search for lastname=Doe
        Query query = persons.whereEqualTo("lastname", "Doe");
        ApiFuture<QuerySnapshot> querySnapshot = query.get();
        return querySnapshot.get().getDocuments().stream()
                .map(document -> document.getId() + " - " + document.getString("firstname") + " "
                        + document.getString("lastname") + "\n")
                .collect(Collectors.joining());
    }
}
Here we let Firestore serialize the Person object, Firestore will use reflection for this. So if you deploy your application as a GraalVM native image you will need to register the Person class for reflection. This can be done by annotating it with @RegisterForReflection.

Dev Service

Configuring the Dev Service

The extension provides a Dev Service that can be used to run a local Firestore emulator. This is useful for testing purposes, so you don’t have to rely on a real Firestore instance. By default, the Dev Service is disabled, but you can enable it by setting the

  • quarkus.google.cloud.firestore.devservice.enabled property to true

You can also set the

  • quarkus.google.cloud.firestore.devservice.port property to change the port on which the emulator will be started (by default there is no port set, so the emulator will use a random port)

Using the Dev Service

Once the Dev Service is enabled, the Firestore client which you can @Inject in your application will be configured to use the emulator.

Configuration Reference

Configuration property fixed at build time - All other configuration properties are overridable at runtime

Configuration property

Type

Default

Indicates to use the dev service for Firebase. The default value is not setup unless the firebase module is included. In that case, the Firebase devservices will by default be preferred and the DevService for PubSub will be disabled.

Environment variable: QUARKUS_GOOGLE_CLOUD_FIREBASE_DEVSERVICE_PREFER_FIREBASE_DEV_SERVICES

boolean

Indicates whether the Firestore service should be enabled or not. The default value is 'false'.

Environment variable: QUARKUS_GOOGLE_CLOUD_FIRESTORE_DEVSERVICE_ENABLED

boolean

false

Sets the Docker image name for the Google Cloud SDK. This image is used to emulate the Firestore service in the development environment. The default value is 'gcr.io/google.com/cloudsdktool/google-cloud-cli'.

Environment variable: QUARKUS_GOOGLE_CLOUD_FIRESTORE_DEVSERVICE_IMAGE_NAME

string

gcr.io/google.com/cloudsdktool/google-cloud-cli

Specifies the emulatorPort on which the Firestore service should run in the development environment.

Environment variable: QUARKUS_GOOGLE_CLOUD_FIRESTORE_DEVSERVICE_EMULATOR_PORT

int

Overrides the default service host. This is most commonly used for development or testing activities with a local Google Cloud Firestore emulator instance.

Environment variable: QUARKUS_GOOGLE_CLOUD_FIRESTORE_HOST_OVERRIDE

string

Forces the usage of emulator credentials. The logic automatically uses emulator credentials in case the host running the library uses "localhost". This behaviour can be overridden by specifying this configuration property:

  • If true: force usage of emulator credentials

  • If false: force not using emulator credentials If not present: keep the automatic behaviour

Environment variable: QUARKUS_GOOGLE_CLOUD_FIRESTORE_USE_EMULATOR_CREDENTIALS

boolean

Total timeout for all retries.

Environment variable: QUARKUS_GOOGLE_CLOUD_FIRESTORE_RETRY_TOTAL_TIMEOUT

Duration 

Delay before the first retry.

Environment variable: QUARKUS_GOOGLE_CLOUD_FIRESTORE_RETRY_INITIAL_RETRY_DELAY

Duration 

Controls the rate of change of the delay. Next retry is multiplied by this factor.

Environment variable: QUARKUS_GOOGLE_CLOUD_FIRESTORE_RETRY_RETRY_DELAY_MULTIPLIER

double

Limits the maximum retry delay.

Environment variable: QUARKUS_GOOGLE_CLOUD_FIRESTORE_RETRY_MAX_RETRY_DELAY

Duration 

Determines the maximum number of attempts. When number of attempts reach this limit they stop retrying.

Environment variable: QUARKUS_GOOGLE_CLOUD_FIRESTORE_RETRY_MAX_ATTEMPTS

int

Timeout for the initial RPC.

Environment variable: QUARKUS_GOOGLE_CLOUD_FIRESTORE_RETRY_INITIAL_RPC_TIMEOUT

Duration 

Controls the rate of change of the RPC timeout. Next timeout is multiplied by this factor.

Environment variable: QUARKUS_GOOGLE_CLOUD_FIRESTORE_RETRY_RPC_TIMEOUT_MULTIPLIER

double

Limits the maximum RPC timeout.

Environment variable: QUARKUS_GOOGLE_CLOUD_FIRESTORE_RETRY_MAX_RPC_TIMEOUT

Duration 

The firestore database identifier. It not set, the default will be used.

Environment variable: QUARKUS_GOOGLE_CLOUD_FIRESTORE_DATABASE_ID

string

About the Duration format

To write duration values, use the standard java.time.Duration format. See the Duration#parse() Java API documentation for more information.

You can also use a simplified format, starting with a number:

  • If the value is only a number, it represents time in seconds.

  • If the value is a number followed by ms, it represents time in milliseconds.

In other cases, the simplified format is translated to the java.time.Duration format for parsing:

  • If the value is a number followed by h, m, or s, it is prefixed with PT.

  • If the value is a number followed by d, it is prefixed with P.