Ravindra BagaleCourses & study guides मराठी

Chapter 22: Jenkins Language Projects — Java to Python

22.3 Java (Maven) — start to end

Why: the problem

Think of the HDFC Bank internet banking team. Most of their backend is Java, and Java projects are built with Maven. A developer says: it works on my laptop. But the release manager needs proof from a clean machine, every time, with tests. Maven reads one file, pom.xml, which lists the Java version, the libraries and the test tool. One command, mvn package, compiles the code, runs the tests and makes a jar file. A jar is a zip of compiled Java classes that the server runs with java -jar. In this lesson you build the badge rule in Java, test it with JUnit, run it, then push it so Jenkins does the same on an agent and keeps the jar as an artifact.

What we will build

You will create badge-java with Maven, write Badge.java and a JUnit test, run mvn package locally, push with a Jenkinsfile, see green, then break a test to see red, and finally publish test reports in Jenkins.

What: every term in plain English

  • Maven — The Java build tool. Reads pom.xml.
  • pom.xml — Project Object Model. Lists name, version, Java version and libraries.
  • groupId / artifactId — The company name and the project name, like com.example and badge-java.
  • JUnit — The common Java test library.
  • Surefire — The Maven plugin that runs tests and writes XML reports.
  • jar — The packaged app: a zip of .class files.
  • target/ — The folder where Maven writes classes, reports and the jar.
  • ~/.m2 — Maven cache of downloaded libraries on the machine.
Make the project Write the files Test and package See the jar Run it Push with Jenkinsfile Build in Jenkins
Java with Maven: push to jar

How: step by step

  1. Make the project

    mkdir -p ~/devops-lab/ch22/badge-java/src/main/java/lab ~/devops-lab/ch22/badge-java/src/test/java/lab && cd ~/devops-lab/ch22/badge-java
    

    What it does: Standard Maven folders.

    Output

    (no output)
    
  2. Write the files

    Create pom.xml, Badge.java, BadgeTest.java from Example 1
    

    What it does: Copy exactly.

    Output

    (no output)
    
  3. Test and package

    mvn -B -q package
    

    What it does: Compile, test, jar.

    Output

    (quiet: no output on success)
    
  4. See the jar

    ls -l target/*.jar
    

    What it does: The artifact.

    Output

    -rw-r--r-- 1 ravi ravi 3712 Oct 25 10:12 target/badge-java-1.0.0.jar
    
  5. Run it

    java -jar target/badge-java-1.0.0.jar 120
    

    What it does: Our rule in Java.

    Output

    gold
    
  6. Push with Jenkinsfile

    git init -q -b main && git add . && git commit -qm "Java badge" && git remote add origin GIT_URL && git push -q -u origin main
    

    What it does: GIT_URL is your lab repo.

    Output

    (no output)
    
  7. Build in Jenkins

    badge-java-pipeline, Build Now
    

    What it does: Same commands on the agent.

    Output

    Tests run: 3, Failures: 0
    BUILD SUCCESS
    Finished: SUCCESS
    

Example 1: The full Maven project

Stack. Java 17, Maven, JUnit 5

Goal. The full Maven project.

pom.xml

<project xmlns="http://maven.apache.org/POM/4.0.0">
  <modelVersion>4.0.0</modelVersion>
  <groupId>com.example</groupId>
  <artifactId>badge-java</artifactId>
  <version>1.0.0</version>
  <properties>
    <maven.compiler.release>17</maven.compiler.release>
    <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
  </properties>
  <dependencies>
    <dependency>
      <groupId>org.junit.jupiter</groupId>
      <artifactId>junit-jupiter</artifactId>
      <version>5.10.2</version>
      <scope>test</scope>
    </dependency>
  </dependencies>
  <build>
    <plugins>
      <plugin>
        <groupId>org.apache.maven.plugins</groupId>
        <artifactId>maven-surefire-plugin</artifactId>
        <version>3.2.5</version>
      </plugin>
      <plugin>
        <groupId>org.apache.maven.plugins</groupId>
        <artifactId>maven-jar-plugin</artifactId>
        <version>3.4.1</version>
        <configuration>
          <archive><manifest><mainClass>lab.Badge</mainClass></manifest></archive>
        </configuration>
      </plugin>
    </plugins>
  </build>
</project>

src/main/java/lab/Badge.java

package lab;

public class Badge {
    public static String level(int points) {
        if (points >= 100) return "gold";
        if (points >= 50) return "silver";
        return "bronze";
    }
    public static void main(String[] args) {
        int p = args.length == 0 ? 0 : Integer.parseInt(args[0]);
        System.out.println(level(p));
    }
}

src/test/java/lab/BadgeTest.java

package lab;

import static org.junit.jupiter.api.Assertions.assertEquals;
import org.junit.jupiter.api.Test;

class BadgeTest {
    @Test void gold()   { assertEquals("gold", Badge.level(100)); }
    @Test void silver() { assertEquals("silver", Badge.level(50)); }
    @Test void bronze() { assertEquals("bronze", Badge.level(0)); }
}

What each line does

  • maven.compiler.release 17 — Compile for Java 17.
  • scope test — JUnit is only for tests, not shipped in the jar.
  • surefire 3.2.5 — A version that finds JUnit 5 tests.
  • mainClass — So java -jar knows where to start.
  • assertEquals — Test fails if the two values differ.

Green output

[INFO] Tests run: 3, Failures: 0, Errors: 0, Skipped: 0
[INFO] Building jar: /home/ravi/devops-lab/ch22/badge-java/target/badge-java-1.0.0.jar
[INFO] BUILD SUCCESS

Expected result. A tested jar from one command.

Example 2: The Jenkinsfile with test reports and artifact

Stack. Jenkins, Maven

Goal. The Jenkinsfile with test reports and artifact.

Jenkinsfile

pipeline {
  agent any
  tools { maven 'M3'; jdk 'jdk17' }
  options { timestamps(); buildDiscarder(logRotator(numToKeepStr: '20')) }
  stages {
    stage('Checkout') { steps { checkout scm } }
    stage('Build')    { steps { sh 'mvn -B -DskipTests compile' } }
    stage('Test')     { steps { sh 'mvn -B test' } }
    stage('Package')  { steps { sh 'mvn -B -DskipTests package' } }
    stage('Live') {
      steps {
        sh 'mkdir -p "$HOME/lab-live/badge-java" && cp target/*.jar "$HOME/lab-live/badge-java/"'
        sh 'java -jar "$HOME/lab-live/badge-java/badge-java-1.0.0.jar" 120'
      }
    }
  }
  post {
    always  { junit 'target/surefire-reports/*.xml' }
    success { archiveArtifacts artifacts: 'target/*.jar', fingerprint: true }
  }
}

What each line does

  • tools — Use Maven and JDK set in Manage Jenkins, Tools.
  • logRotator — Keep only 20 builds so the disk does not fill.
  • junit — Reads Surefire XML and shows a test trend chart.
  • fingerprint — Tracks which build made this jar.
  • Live java -jar — Smoke test: the jar really runs.

Green output

[Pipeline] stage (Test)
[INFO] Tests run: 3, Failures: 0, Errors: 0, Skipped: 0
[Pipeline] stage (Live)
gold
Recording test results
Archiving artifacts
Finished: SUCCESS

Expected result. The job page shows Test Result: 0 failures and a download link for the jar.

Example 3: Break a test and read the red build

Stack. Maven

Goal. Break a test and read the red build.

change

sed -i 's/points >= 100/points > 100/' src/main/java/lab/Badge.java
git commit -qam "Bug: 100 is no longer gold" && git push -q

What each line does

  • >= to > — Now exactly 100 points gives silver.
  • push — Jenkins runs again.

Green output

[ERROR] Tests run: 3, Failures: 1, Errors: 0, Skipped: 0
[ERROR] BadgeTest.gold:7 expected: [gold] but was: [silver]
[ERROR] BUILD FAILURE
Finished: FAILURE

Expected result. Test stage red, Package and Live skipped. Read the expected and was values, fix the code, push again.

Example 4: Speed up Maven builds with a cache in a Docker agent

Stack. Jenkins, Docker, Maven

Goal. Speed up Maven builds with a cache in a Docker agent.

Jenkinsfile

pipeline {
  agent {
    docker {
      image 'maven:3.9-eclipse-temurin-17'
      args '-v $HOME/.m2:/root/.m2'
    }
  }
  stages {
    stage('Package') { steps { sh 'mvn -B package' } }
  }
}

What each line does

  • maven:3.9-eclipse-temurin-17 — Official image with Maven and Java 17. No install on the agent.
  • -v $HOME/.m2:/root/.m2 — Keep downloaded libraries between builds.

Green output

First build:  Total time:  41.203 s
Second build: Total time:  6.118 s

Expected result. Libraries download once. Builds get about 6 times faster.

Verify: did it work?

  1. Jar exists

    ls target/badge-java-1.0.0.jar
    

    What it does: Built.

    Output

    target/badge-java-1.0.0.jar
    
  2. Reports exist

    ls target/surefire-reports/*.xml
    

    What it does: For the junit step.

    Output

    target/surefire-reports/TEST-lab.BadgeTest.xml
    
  3. Live copy runs

    java -jar ~/lab-live/badge-java/badge-java-1.0.0.jar 60
    

    What it does: Copied by Jenkins.

    Output

    silver
    

When it is red 1

[ERROR] Source option 5 is no longer supported. Use 7 or later.

Cause. No Java version in pom.xml.

Fix, step by step

  1. Add maven.compiler.release 17 in properties.

When it is red 2

Tests run: 0, Failures: 0

Cause. Old Surefire does not see JUnit 5 tests.

Fix, step by step

  1. Set maven-surefire-plugin to 3.2.5 or newer.
  2. Test class names must end with Test.

When it is red 3

no main manifest attribute, in target/badge-java-1.0.0.jar

Cause. The jar does not say which class to start.

Fix, step by step

  1. Add mainClass in maven-jar-plugin configuration.

When it is red 4

Could not transfer artifact ... from/to central: Connect timed out

Cause. The agent cannot reach Maven Central.

Fix, step by step

  1. Check proxy or firewall.
  2. Use a company mirror like Nexus in settings.xml.

Cleanup

  1. Clean build files

    mvn -q clean
    

    What it does: Removes target/.

    Output

    (no output)
    

Ravindra Bagale's Tip

mvn package local la green zala tarach push kara. Jenkins madhe red aala tar pahila [ERROR] line vacha!

Practice tasks

Easy Run the jar three ways

Why: Know the app before CI.

What to do: Run with 0, 60 and 150.

How:
  1. java -jar target/badge-java-1.0.0.jar 150

Check: bronze, silver, gold.

Medium Publish test trend

Why: Managers love charts.

What to do: Add junit in post always and run three builds.

How:
  1. Push three commits.

Check: The trend chart shows three points.

Hard Docker agent build

Why: No tools on agent.

What to do: Use the maven Docker agent.

How:
  1. Install Docker Pipeline plugin.

Check: Build green with no Maven on the host.

Easy Say Java Maven pipelines in two lines

Why: If you can say it simply, you understand it. Interviewers want the short version first.

What to do: Write two short lines about Java Maven pipelines for a fresher who knows only basic Linux.

How:
  1. Write the problem it solves.
  2. Write one real command or file that shows it.
  3. Read it aloud to a friend.

Check: A fresher understands it without asking a question.

Easy Make a safe lab folder

Why: Practice needs a place you can throw away. Then mistakes cost nothing.

What to do: Create a lab folder for this chapter and work only inside it.

How:
  1. mkdir -p ~/devops-lab && cd ~/devops-lab
  2. Run every command of this lesson from here.
  3. Check with pwd before you delete anything.

Check: All lab files live in ~/devops-lab.

Medium Repeat it in a container

Why: Your laptop is not the server. A clean Ubuntu container shows what a fresh server needs.

What to do: Run the main steps of this lesson again inside an Ubuntu container.

How:
  1. docker run --rm -it -v "$PWD":/lab -w /lab ubuntu:24.04 bash
  2. apt update and install what is missing.
  3. Note every missing tool.

Check: Same result inside the container, or a list of what you had to install.

Medium Break it on purpose

Why: You must know the red message by face. In an outage there is no time to read slowly.

What to do: Cause one error from the "When it is red" part of this lesson and fix it.

How:
  1. Follow the error section.
  2. Copy the exact message into your notes.
  3. Write the fix in one line.

Check: You fixed it using only the steps, without searching the web.

Medium Write a one-page runbook

Why: At 2 a.m. nobody remembers the right command. A short page saves the on-call person.

What to do: Write a runbook page for this lesson.

How:
  1. Title, when to use, exact command, how to check, how to undo.

Check: A teammate can follow it alone.

Hard Explain it like an interview

Why: Interviewers want real stories, not definitions.

What to do: Record a 60 second answer about this lesson.

How:
  1. Say the problem, the command or file you used, and one error you hit.

Check: Your answer has a real command and a real error message.

Hard Draw the flow top to bottom

Why: A drawing shows who does what and in which order.

What to do: Draw this lesson as boxes from top to bottom.

How:
  1. Start at the developer laptop, end at the user on the website.

Check: Each box matches a real thing you ran.

Homework: try at home

Try at home

Add a fourth test for 99 points. It must be silver. Push it and check the Test Result page shows 4 tests.

Recap

  • Maven reads pom.xml.
  • mvn package compiles, tests and makes a jar.
  • Publish JUnit XML with junit.
  • Archive the jar with a fingerprint.
  • Cache ~/.m2 for speed.

FAQ

What is the difference between mvn install and mvn package?

package makes the jar in target. install also copies it to ~/.m2 for other local projects.

Should CI use -B?

Yes. Batch mode removes colours and prompts.

Should I skip tests in CI?

Never in the Test stage. Skip only when you package after tests already ran.

Where do company libraries come from?

A private repository like Nexus or Artifactory set in settings.xml.

What is mvn verify?

Runs tests plus extra checks after package, like integration tests.

Why is the first build slow?

Maven downloads all libraries once.

Interview questions

  1. Explain the Maven lifecycle.

    validate, compile, test, package, verify, install, deploy; each phase runs the ones before it.

  2. How do you show test results in Jenkins?

    junit step on Surefire XML.

  3. How do you speed up Maven in CI?

    Cache ~/.m2, use a mirror, run in parallel with -T.

  4. What is a SNAPSHOT version?

    A changing development version; releases have fixed versions.

  5. How do you trace which build made a jar?

    archiveArtifacts with fingerprint.

  6. What does BUILD FAILURE with Tests run: 0 suggest?

    Surefire did not detect tests: version or naming problem.

Quick quiz

Q1. Which file does Maven read?

pom.xml

Q2. Where is the jar written?

target/

Q3. Which plugin runs tests?

Surefire.

Q4. What does the junit step read?

target/surefire-reports/*.xml

Q5. Why mount ~/.m2?

Cache libraries between builds.

Samajla ka?

Ravi Sir's Cards for this lesson

मराठी cards