Java
Dagger can be used to perform common CI tasks - testing, containerizing, publishing and more - for any Java application. Java developers can leverage an excellent Java module from the Daggerverse which provides various Dagger Functions to work with Java projects. These Dagger Functions make it easy to configure the Java/Maven versions to use, the Maven sub-commands for building and packaging the application, and the output target.
How it works
The integration depends on the java
Dagger module and is currently supported from SDKs that support Dagger modules and Functions.
To Daggerize a Java project using this integration, you must:
- Create a new Dagger module in your Java project
- Install the
java
Dagger module as a dependency - Implement your CI pipeline as one or more Dagger Function(s)
- Test your Dagger Function(s) locally and then transfer them to your CI environment
Prerequisites
Example
The following example demonstrates how to build and publish a Java application using this integration. It assumes:
- A Spring Boot Web application with Maven for dependency management. This example uses the Spring Petclinic application.
- Credentials to publish the containerized application image to a registry like Docker Hub.
Clone the application repository:
git clone https://github.com/spring-projects/spring-petclinic.git
cd spring-petclinic
- Go
- Python
- TypeScript
Bootstrap a new module:
dagger init --name=my-module --sdk=go --source=./dagger
Install the Java module from the Daggerverse:
dagger install github.com/jcsirot/daggerverse/java@c591e9e0b99def2fc8a67bb090fca5cd06cf6a1d
Update the generated dagger/main.go
file with the following code:
package main
import (
"context"
"fmt"
"dagger/my-module/internal/dagger"
)
type MyModule struct{}
func (m *MyModule) Build(ctx context.Context, source *dagger.Directory) *dagger.File {
return dag.Java().
WithJdk("17").
WithMaven("3.9.5").
WithProject(source.WithoutDirectory("dagger")).
Maven([]string{"package"}).
File("target/spring-petclinic-3.2.0-SNAPSHOT.jar")
}
func (m *MyModule) Publish(ctx context.Context, source *dagger.Directory, version string, registryAddress string, registryUsername string, registryPassword *dagger.Secret, imageName string) (string, error) {
return dag.Container(dagger.ContainerOpts{Platform: "linux/amd64"}).
From("eclipse-temurin:17-alpine").
WithLabel("org.opencontainers.image.title", "Java with Dagger").
WithLabel("org.opencontainers.image.version", version).
WithFile("/app/spring-petclinic-3.2.0-SNAPSHOT.jar", m.Build(ctx, source)).
WithEntrypoint([]string{"java", "-jar", "/app/spring-petclinic-3.2.0-SNAPSHOT.jar"}).
WithRegistryAuth(registryAddress, registryUsername, registryPassword).
Publish(ctx, fmt.Sprintf("%s/%s/%s", registryAddress, registryUsername, imageName))
}
Bootstrap a new module:
dagger init --name=my-module --sdk=python --source=./dagger
Install the Java module from the Daggerverse:
dagger install github.com/jcsirot/daggerverse/java@c591e9e0b99def2fc8a67bb090fca5cd06cf6a1d
Update the generated dagger/src/my_module/main.py
file with the following code:
import dagger
from dagger import dag, function, object_type
@object_type
class MyModule:
@function
def build(self, source: dagger.Directory) -> dagger.File:
return (
dag.java()
.with_jdk("17")
.with_maven("3.9.5")
.with_project(source.without_directory("dagger"))
.maven(["package"])
.file("target/spring-petclinic-3.2.0-SNAPSHOT.jar")
)
@function
async def publish(
self,
source: dagger.Directory,
version: str,
registry_address: str,
registry_username: str,
registry_password: dagger.Secret,
image_name: str,
) -> str:
return await (
dag.container(platform=dagger.Platform("linux/amd64"))
.from_("eclipse-temurin:17-alpine")
.with_label("org.opencontainers.image.title", "Java with Dagger")
.with_label("org.opencontainers.image.version", version)
.with_file("/app/spring-petclinic-3.2.0-SNAPSHOT.jar", self.build(source))
.with_entrypoint(
[
"java",
"-jar",
"/app/spring-petclinic-3.2.0-SNAPSHOT.jar",
]
)
.with_registry_auth(registry_address, registry_username, registry_password)
.publish(f"{registry_address}/{registry_username}/{image_name}")
)
Bootstrap a new module:
dagger init --name=my-module --sdk=typescript --source=./dagger
Install the Java module from the Daggerverse:
dagger install github.com/jcsirot/daggerverse/java@c591e9e0b99def2fc8a67bb090fca5cd06cf6a1d
Update the generated dagger/src/index.ts
file with the following code:
import {
dag,
File,
Directory,
Secret,
object,
func,
ClientContainerOpts,
} from "@dagger.io/dagger"
@object()
class MyModule {
@func()
build(source: Directory): File {
return dag
.java()
.withJdk("17")
.withMaven("3.9.5")
.withProject(source.withoutDirectory("dagger"))
.maven(["package"])
.file("target/spring-petclinic-3.2.0-SNAPSHOT.jar")
}
@func()
async publish(
source: Directory,
version: string,
registryAddress: string,
registryUsername: string,
registryPassword: Secret,
imageName: string,
): Promise<string> {
return await dag
.container({ platform: "linux/amd64" } as ClientContainerOpts)
.from("eclipse-temurin:17-alpine")
.withLabel("org.opencontainers.image.title", "Java with Dagger")
.withLabel("org.opencontainers.image.version", version)
.withFile("/app/spring-petclinic-3.2.0-SNAPSHOT.jar", this.build(source))
.withEntrypoint([
"java",
"-jar",
"/app/spring-petclinic-3.2.0-SNAPSHOT.jar",
])
.withRegistryAuth(registryAddress, registryUsername, registryPassword)
.publish(`${registryAddress}/${registryUsername}/${imageName}`)
}
}
The code sample above is illustrative only. Modify it to your application's specific requirements.
Here is an example of calling the Dagger Function to publish the application image to Docker Hub. Replace the DOCKER-HUB-USERNAME
and DOCKER-HUB-PASSWORD
placeholders with your Docker Hub credentials.
export REGISTRY_PASSWORD=DOCKER-HUB-PASSWORD
dagger call publish \
--source=. \
--version=0.1 \
--registry-address=docker.io \
--registry-username=DOCKER-HUB-USERNAME \
--registry-password=env:REGISTRY_PASSWORD \
--image-name=my-java-app
Java developers can also create application delivery pipelines with the experimental Java SDK, using the same language and tooling they use for their Java applications, and benefiting from faster local runs by using Dagger to cache Maven dependencies. This SDK is currently under development and therefore not yet documented. Interested early adopters can learn more by reviewing the source code or visiting our Java channel.
Resources
If you have any questions about additional ways to use Java with Dagger, join our Discord and ask your questions in our Java channel.
About Java
Java is an object-oriented programming language. Java applications are highly portable and can run on any platform for which a Java runtime environment (JRE) is available.