Build Systems — Maven & Gradle
Java-র build system — Maven ও Gradle
1. What Is a Build System?
A build system takes your source code, a list of dependencies, and a few rules — and produces a runnable artifact: a JAR, a WAR, a Docker image, whatever. It compiles, runs tests, packages, and if you like, deploys. In the Java world, two tools dominate: Maven (declarative XML, convention-driven) and Gradle (programmable DSL, performance-tuned).
2. Maven — pom.xml as a Contract
Maven's core idea is convention over configuration. Put code in
src/main/java, tests in src/test/java, declare dependencies in a
pom.xml, and everything just works. A single file describes the whole project.
src/main/java-তে, test src/test/java-তে রাখবেন, dependency pom.xml-এ ঘোষণা করবেন — বাকিটা Maven নিজেই সামলাবে। একটি ফাইলেই পুরো project-এর description।
<!-- Minimal pom.xml for a Java 21 project -->
<project xmlns="http://maven.apache.org/POM/4.0.0">
<modelVersion>4.0.0</modelVersion>
<groupId>com.abcltech</groupId>
<artifactId>bkash-demo</artifactId>
<version>1.0.0</version>
<packaging>jar</packaging>
<properties>
<maven.compiler.source>21</maven.compiler.source>
<maven.compiler.target>21</maven.compiler.target>
</properties>
<dependencies>
<dependency>
<groupId>org.junit.jupiter</groupId>
<artifactId>junit-jupiter</artifactId>
<version>5.10.1</version>
<scope>test</scope>
</dependency>
</dependencies>
</project>
Common commands (run in the project directory):
| Command | Does | বাংলায় |
|---|---|---|
mvn compile | Compile src/main/java. | Main source compile করে। |
mvn test | Compile + run all tests. | Compile করে সব test চালায়। |
mvn package | Produce the .jar (or .war). | JAR বা WAR তৈরি করে। |
mvn install | Install into your local Maven repo (~/.m2). | Local Maven repo-তে install করে। |
mvn clean | Delete the target/ folder. | target/ folder মুছে দেয়। |
3. Maven Build Lifecycle
mvn install চালালে আগের সব phase (validate → compile → test → package → verify) স্বয়ংক্রিয়ভাবে চলে। তাই আলাদা-আলাদা chain করার দরকার নেই।
4. Gradle — Code as Configuration
Where Maven is declarative XML, Gradle is a real programming language (Groovy originally, Kotlin today). Build logic becomes expressive — you can write conditionals, loops, and functions in the build script. Gradle is also much faster than Maven on incremental builds, thanks to build caching.
// Gradle build in Kotlin DSL
plugins {
java
application
}
group = "com.abcltech"
version = "1.0.0"
java {
toolchain { languageVersion.set(JavaLanguageVersion.of(21)) }
}
repositories { mavenCentral() }
dependencies {
implementation("com.google.guava:guava:33.0.0-jre")
testImplementation("org.junit.jupiter:junit-jupiter:5.10.1")
}
application {
mainClass.set("com.abcltech.bkash.Main")
}
tasks.test { useJUnitPlatform() }
Typical commands:
| Command | Does | বাংলায় |
|---|---|---|
./gradlew build | Compile + test + package. | Compile, test, package — একসাথে। |
./gradlew run | Run the app's main class. | App-এর main class চালায়। |
./gradlew test | Run just the tests. | শুধু test চালায়। |
./gradlew tasks | List every available task. | সব available task দেখায়। |
5. Dependency Scopes (dependency-র ধরন)
Not every dependency belongs at runtime. Scopes let the build system decide where each dependency should appear: on the compile classpath, the test classpath, the runtime classpath, or all three.
| Maven scope | Gradle keyword | When visible |
|---|---|---|
compile (default) | implementation | Compile + runtime. Most libraries. |
provided | compileOnly | Compile only — container provides at runtime (e.g. Servlet API). |
runtime | runtimeOnly | Runtime only — JDBC drivers, logging backends. |
test | testImplementation | Test classpath only — JUnit, Mockito. |
বাংলাদেশের একটি সুস্থ fintech microservice project-এ প্রতিটি service-এর জন্য একটি Maven/Gradle ফাইল থাকে, scope সঠিকভাবে পরিচালিত — তাই deploy আকার ছোট থাকে এবং test কোড ভুল করে production-এ যায় না।
6. When to Choose Which?
✅ Pick Maven When…
- The team wants predictability & convention
- Spring Boot starter templates (default is Maven)
- Simple apps, small teams, no custom build logic
- Legacy enterprise environments
⚡ Pick Gradle When…
- You need fast incremental/parallel builds
- Custom build logic (code generation, packaging, etc.)
- Android projects — Gradle is mandatory
- Multi-language projects (Java + Kotlin + Scala)
7. Vocabulary
| Term | Meaning | বাংলায় |
|---|---|---|
| Artifact | Output of a build — a JAR, WAR, or ZIP. | Build-এর output — JAR, WAR ইত্যাদি। |
| Coordinate | groupId:artifactId:version — unique address of a library. | একটি library-র unique address। |
| Transitive dep | A dep pulled in indirectly through another. | পরোক্ষভাবে আসা dependency। |
| Local repo | Your machine's cached JARs — ~/.m2 or ~/.gradle. | আপনার মেশিনের cached JAR। |
| Central | Maven Central — the world's shared Java library server. | Maven Central — পৃথিবীর shared Java library server। |
| Wrapper | mvnw / gradlew — reproducible tool version per project. | প্রতি project-এ নির্দিষ্ট build-tool সংস্করণ। |
8. Practice Problems
Most answers are text or configuration — some are runnable Java demos of the underlying concept.
-
Write a Java program that prints the three parts of a Maven coordinate given a combined string like
"com.google.guava:guava:33.0.0-jre"."com.google.guava:guava:33.0.0-jre"-এর মতো string থেকে groupId, artifactId, version আলাদা করে প্রিন্ট করুন।✨ Show Answer
Main.javaclass Main { public static void main(String[] args) { String coord = "com.google.guava:guava:33.0.0-jre"; String[] parts = coord.split(":"); System.out.println("groupId = " + parts[0]); System.out.println("artifactId = " + parts[1]); System.out.println("version = " + parts[2]); } } -
What does
mvn installdo thatmvn packagedoesn't?mvn installযা করে কিন্তুmvn packageকরে না — সেটি কী?✨ Show Answer
Answer:
mvn packagebuilds the JAR/WAR intarget/.mvn installdoes everythingpackagedoes AND then copies the artifact into your local Maven cache at~/.m2/repository, so that other local projects on your machine can resolve it by coordinate.mvn packageশুধুtarget/-এ JAR/WAR তৈরি করে;mvn installসেটিকে আরো local Maven cache (~/.m2/repository)-এ copy করে — যাতে একই মেশিনের অন্য project সেটিকে dependency হিসেবে পায়। -
Write a Java program that simulates a tiny "build" — it prints the phases
compile → test → package → installin order, skipping any phase named as a command-line argument.একটি ছোট "build" simulator বানান —compile → test → package → installপ্রিন্ট করবে, কিন্তু command-line-এ যে phase দেওয়া হবে সেটি skip করবে।✨ Show Answer
Main.javaclass Main { public static void main(String[] args) { String[] phases = {"compile", "test", "package", "install"}; String skip = args.length > 0 ? args[0] : ""; for (String p : phases) { if (p.equals(skip)) { System.out.println("[SKIP] " + p); continue; } System.out.println("[RUN ] " + p); } } } -
Which scope would you use for (a) JUnit, (b) a PostgreSQL JDBC driver, (c) the Servlet API (Tomcat provides it)?কোন scope লাগবে — (ক) JUnit, (খ) PostgreSQL JDBC driver, (গ) Servlet API (Tomcat দেবে)?
✨ Show Answer
Answer: (a)
test/testImplementation— JUnit only exists during tests. (b)runtime/runtimeOnly— you neverimporta driver class in your code; it is loaded reflectively at runtime. (c)provided/compileOnly— you need it to compile your servlet but the container provides it, so shipping it in your WAR would conflict. -
Explain "transitive dependency" and why version conflicts are possible."Transitive dependency" কী, এবং কেন version conflict হতে পারে — ব্যাখ্যা করুন।
✨ Show Answer
Answer: If your project depends on
A, andAdepends onB, thenBis a transitive dependency — you did not name it, but it arrives on your classpath anyway. Version conflicts happen when two direct dependencies pull in different versions of the same transitive dep (Maven picks "nearest" in the dependency tree; Gradle picks "highest" by default). Resolve with thedependencyManagementsection in Maven or a GradleresolutionStrategyto force a version.
Summary — Module 44
Maven gives you convention, predictability, and XML. Gradle gives you
programmable, fast, incremental builds. Both share the same mental model: source → compile → test →
package → install. Pick one, master its lifecycle, and keep your pom.xml or
build.gradle.kts clean — it is the contract between your code and the rest of the team.