In a microservice architecture, it's common for multiple services to share common functionality or utility classes. To handle this effectively, I manage these shared components as a reusable library (like libs.jar) that each service can depend on. In this post, I’ll show you how I use GCP Artifact Registry to efficiently manage and distribute a shared library across microservices.
Step 1: Enable the Artifact Registry API
$ gcloud services enable artifactregistry.googleapis.com --project=[PROJECT_ID]
Step 2: Create a Maven Repository in GCP Artifact Registry
$ gcloud artifacts repositories create maven-repo \
--repository-format=maven \
--location=us-central1 \
--description="Shared Maven Repo for common libraries"
$ gcloud artifacts repositories list --location=us-central1
REPOSITORY FORMAT LOCATION DESCRIPTION
maven-repo MAVEN us-central1 Shared Maven repo
Step 3: Configure pom.xml for the Shared Library Project
In the shared library (libs) project's pom.xml, I define the following:
- groupId: A unique identifier for my organization or project (e.g.,
com.example.libs) - artifactId: The name of the library (e.g.,
libs) - version: The library version (e.g.,
1.0.1) - packaging: The packaging type (
jaris recommended for reusable libraries)
If the packaging tag is missing or incorrect, Maven may mistakenly treat the library as pom, war, or another type — leading to problems when uploading to Artifact Registry or importing it into other projects.
<groupId>com.example.libs</groupId>
<artifactId>libs</artifactId>
<version>1.0.1</version>
<packaging>jar</packaging>
GCP Artifact Registry for Maven requires using the artifactregistry:// protocol instead of https://. Otherwise, authentication and upload may not work properly.
For snapshot versions (e.g., 0.0.1-SNAPSHOT), Maven appends a timestamp to ensure uniqueness. Release versions remain fixed.
<distributionManagement>
<snapshotRepository>
<id>artifact-registry</id>
<url>artifactregistry://us-central1-maven.pkg.dev/[PROJECT_ID]/maven-repo</url>
</snapshotRepository>
<repository>
<id>artifact-registry</id>
<url>artifactregistry://us-central1-maven.pkg.dev/[PROJECT_ID]/maven-repo</url>
</repository>
</distributionManagement>
| Version Type | Example | Description |
|---|---|---|
<releases> |
1.0.0 |
Stable release; cannot be overwritten once uploaded |
<snapshots> |
0.0.1-SNAPSHOT |
Development version; overwritten with timestamped versions |
<repositories>
<repository>
<id>artifact-registry</id>
<url>artifactregistry://us-central1-maven.pkg.dev/[PROJECT_ID]/maven-repo</url>
<releases><enabled>true</enabled></releases>
<snapshots><enabled>true</enabled></snapshots>
</repository>
</repositories>
Add Artifact Registry Maven Wagon Extension
To allow Maven to understand the artifactregistry://... protocol, I include the official Google Artifact Registry Maven Wagon extension.
<build>
<extensions>
<extension>
<groupId>com.google.cloud.artifactregistry</groupId>
<artifactId>artifactregistry-maven-wagon</artifactId>
<version>2.2.5</version>
</extension>
</extensions>
</build>
Step 4: Configure application.yaml for the Shared Library
I disable unnecessary auto-configuration to avoid errors — especially since the shared library doesn't require a database.
spring:
application:
name: libs
autoconfigure:
exclude:
- org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration
- org.springframework.boot.autoconfigure.orm.jpa.HibernateJpaAutoConfiguration
Step 5: Maven Authentication Configuration
Using the Credential Helper
Artifact Registry requires authentication. Since the access token from gcloud auth print-access-token only lasts 1 hour, I use the credential helper provided by gcloud to handle automatic token renewal for Maven.
On Windows, the credentials are stored in:
C:\Users\[USER]\AppData\Roaming\gcloud\application_default_credentials.json
I run the following command to enable this:
$ gcloud auth application-default login
Grant Cloud Build Access
In CI/CD environments like Cloud Build, I make sure the service account has the necessary roles to access Artifact Registry.
gcloud projects add-iam-policy-binding [PROJECT_ID] \
--member="serviceAccount:[PROJECT_NUMBER]-compute@developer.gserviceaccount.com" \
--role="roles/artifactregistry.reader"
gcloud projects add-iam-policy-binding [PROJECT_ID] \
--member="serviceAccount:[PROJECT_NUMBER]-compute@developer.gserviceaccount.com" \
--role="roles/artifactregistry.writer"
Step 6: Provide a Custom settings.xml for Maven
Since Cloud Build runs on a remote server and doesn't have access to my local ~/.m2/settings.xml, I include a settings.xml file in the build context (the project's root directory) and explicitly specify it using the -s option.
<settings>
<servers>
<server>
<id>artifact-registry</id>
<username>oauth2accesstoken</username>
<password>
<!-- empty is fine; gcloud helper will inject the token -->
</password>
</server>
</servers>
</settings>
On my local machine, Maven uses:
C:\Users\[USER]\.m2\settings.xml
Step 7: Create cloudbuild.yaml
- I use
-DskipTeststo skip running tests, which speeds up the build process. This is especially useful for shared libraries that are frequently updated and published. - Cloud Build automatically mounts the build context (e.g.,
.) to/workspaceinside the build container. - I add
-Bto enable batch mode, which makes the Maven output cleaner.
steps:
# 1. Build the JAR without running tests
- name: 'gcr.io/cloud-builders/mvn'
entrypoint: 'mvn'
args: ['clean', 'package', '-DskipTests']
# 2. Deploy the JAR to Artifact Registry
- name: 'gcr.io/cloud-builders/mvn'
args: ['deploy',
'-B',
'-s', '/workspace/settings.xml']
Step 8: Modify pom.xml of Each Services
In this step, I configure each microservice (a-service, b-service, etc.) to use the shared library.
1. Add the shared library dependency
<dependency>
<groupId>com.example.libs</groupId>
<artifactId>libs</artifactId>
<version>1.0.1</version>
</dependency>
- The values must exactly match those used in the
libsproject.
2. Add the Artifact Registry Maven extension
<extension>
<groupId>com.google.cloud.artifactregistry</groupId>
<artifactId>artifactregistry-maven-wagon</artifactId>
<version>2.2.5</version>
</extension>
- This is required so Maven can resolve
artifactregistry://URLs.
3. Add the repository information
<repositories>
<repository>
<id>artifact-registry</id>
<url>artifactregistry://us-central1-maven.pkg.dev/[PROJECT_ID]/maven-repo</url>
<releases><enabled>true</enabled></releases>
<snapshots><enabled>true</enabled></snapshots>
</repository>
</repositories>
- Replace
[PROJECT_ID]with your actual GCP project ID. - Ensure the region (
us-central1) matches where your Artifact Registry is located. - This tells Maven where to look for the shared library.
Step 9: Add settings.xml in the service's root directory
To enable Maven to authenticate with GCP Artifact Registry during the build the services, the following command to configure authentication for gcloud:
$ gcloud auth application-default login
Next, I place a settings.xml file in the root directory of the service. This file provides the necessary credentials using oauth2accesstoken, allowing Maven to access the GCP Artifact Registry and retrieve the shared library during the build.
<settings>
<servers>
<server>
<id>artifact-registry</id>
<username>oauth2accesstoken</username>
<password>
<!-- empty is fine; gcloud helper will inject the token -->
</password>
</server>
</servers>
</settings>
Then, I reference this file explicitly in the cloudbuild.yaml using the -s flag:
steps:
# 1. Java Build
- name: 'gcr.io/cloud-builders/mvn'
args: ['clean', 'package',
'-DskipTests',
'-B',
'-s', '/workspace/settings.xml']

Post a Comment