Operations 16 min read

Automated Deployment of Java Projects Using Jenkins Pipeline

This article explains how to use Jenkins Pipeline to automate the deployment of a Java backend project, covering pipeline basics, parameterized builds, GitLab branch checkout, Maven compilation, JAR packaging, remote file transfer, backup, update, and service restart with Docker Swarm.

Wukong Talks Architecture
Wukong Talks Architecture
Wukong Talks Architecture
Automated Deployment of Java Projects Using Jenkins Pipeline

This tutorial demonstrates how to achieve fully automated deployment of a Java backend application by writing Jenkins Pipeline code. It starts with an overview of pipelines, their advantages, and drawbacks, then walks through creating a pipeline job, defining parameters, and configuring environment variables.

Pipeline Basics

A Jenkins pipeline is a declarative Groovy script that defines stages such as checkout, build, test, and deploy. The basic structure includes pipeline { agent any; stages { ... } }, where each stage contains steps that execute specific commands.

Parameterizing the Build

Parameters allow users to select the GitLab branch and the micro‑services to deploy. Example:

pipeline {
    parameters {
        string(name: 'GIT_BRANCH', defaultValue: 'dev-01.30', description: '请选择部署的分支')
    }
    environment {
        GIT_URL = 'https://xxx/xxx.git'
    }
    ...
}

The selected branch is accessed via params.GIT_BRANCH and the repository URL via ${GIT_URL}.

Checkout Code

The pipeline checks out the specified branch using the Git plugin:

checkout([
    $class: 'GitSCM',
    branches: [[name: "${params.GIT_BRANCH}"]],
    userRemoteConfigs: [[url: "${GIT_URL}", credentialsId: 'gitlab-cred-id']]
])

Compile with Maven

Compilation is performed on a Windows agent using a batch command:

stage('编译代码') {
    steps {
        script {
            echo "--------------- 步骤:开始编译 ---------------"
            bat 'mvn clean package'
            echo "--------------- 步骤:编译完成 ---------------"
        }
    }
}

Upload JAR Files

Selected services are uploaded via the sshPublisher plugin. The script iterates over filesToCopy and transfers each JAR to the remote apps/temp/ directory.

filesToCopy.eachWithIndex { file, index ->
    echo "开始上传 JAR 包 ${file} ..."
    sshPublisher(
        failOnError: true,
        publishers: [sshPublisherDesc(
            configName: "${SSH_URL}",
            transfers: [sshTransfer(
                remoteDirectory: 'apps/temp/',
                sourceFiles: file,
                removePrefix: removePrefixs[index]
            )]
        )]
    )
    echo "完成上传 JAR 包 ${file}"
}

Backup Existing JARs

Before overwriting, each service's current JAR is backed up with a timestamp:

serviceNameList.each { service ->
    echo "开始备份微服务 ${service} 包"
    sshPublisher(
        failOnError: true,
        publishers: [sshPublisherDesc(
            configName: "${SSH_URL}",
            transfers: [sshTransfer(
                execCommand: "mkdir -p /nfs-data/wukong/apps/bak/${timestamp} && mv ${service}.jar /nfs-data/wukong/apps/bak/${timestamp}/${service}-${timestamp}.jar"
            )]
        )]
    )]
)

Update JAR Files

After uploading, the new JARs are moved into place:

serviceNameList.eachWithIndex { service, index ->
    echo "开始更新第 ${index+1} 个 JAR 包,/nfs-data/wukong/apps/temp/${service}.jar ..."
    sshPublisher(
        failOnError: true,
        publishers: [sshPublisherDesc(
            configName: "${SSH_URL}",
            transfers: [sshTransfer(
                execCommand: "cd /nfs-data/wukong/apps && mv -f ./temp/${service}.jar ${service}.jar"
            )]
        )]
    )
    echo "----- 完成更新 JAR 包 -----"
}

Restart Services

Finally, each Docker Swarm service is forced to restart so the new JAR takes effect:

serviceNameList.eachWithIndex { service, index ->
    echo "开始重启第 ${index+1} 个微服务,${service} ..."
    sshPublisher(
        failOnError: true,
        publishers: [sshPublisherDesc(
            configName: "${SSH_URL}",
            transfers: [sshTransfer(
                execCommand: "sudo docker service update --force ${commands[service]}"
            )]
        )]
    )
    echo "----- 完成重启微服务 -----"
}

Conclusion

The article shows that using Jenkins Pipeline for Java project deployment provides flexibility, version control, and better collaboration, while also highlighting the need for proper credential management and potential drawbacks such as higher learning curve.

JavaCI/CDAutomationPipelineJenkins
Wukong Talks Architecture
Written by

Wukong Talks Architecture

Explaining distributed systems and architecture through stories. Author of the "JVM Performance Tuning in Practice" column, open-source author of "Spring Cloud in Practice PassJava", and independently developed a PMP practice quiz mini-program.

0 followers
Reader feedback

How this landed with the community

Sign in to like

Rate this article

Was this worth your time?

Sign in to rate
Discussion

0 Comments

Thoughtful readers leave field notes, pushback, and hard-won operational detail here.