1. What problem do build tools solve?
Let us imagine a Java project with many source files, third-party libraries, tests, resources, configuration files, and packaging steps. If you try to manage everything manually, very soon you will have questions like these:
- How do I compile all source files in the correct order?
- Where do I keep external libraries?
- How do I run tests automatically?
- How do I create a JAR or WAR?
- How do I make sure another developer builds the project in the same way?
- How do I avoid downloading libraries manually every time?
2. What happens if you build manually?
At the smallest scale, you can write a single Java file and run:
javac Hello.java
java Hello
That works for one tiny program. But as soon as your project grows, you must manage:
Compilation order
Which files should be compiled? Where do compiled classes go?
Dependencies
How do you bring external libraries like JUnit, Spring, Jackson, or Hibernate?
Testing
How do you consistently run test code?
Packaging
How do you produce the final artifact for deployment?
3. What is a build tool?
A build tool is software that helps your project move from source code to usable output in a repeatable way. That output might be a JAR, WAR, test report, generated code, documentation, or published package.
| Action | Meaning |
|---|---|
| Compile | Convert source code into bytecode or another machine-usable form |
| Test | Run automated tests |
| Package | Create distributable artifacts like JARs |
| Resolve dependencies | Download required external libraries |
| Run plugins/tasks | Execute extra project actions like code generation or static analysis |
| Publish | Upload artifacts to repositories |
4. Big picture workflow
You describe your project
You declare name, version, dependencies, plugins, and build rules.
The build tool resolves dependencies
It downloads the libraries your project needs from repositories.
The build tool performs tasks or phases
For example compile, test, package, and publish.
Artifacts are produced
For example a JAR file inside the build output folder.
5. Maven from zero
Maven is one of the most widely used Java build tools. It is convention-heavy, XML-based, and designed around a standard project structure and a standard lifecycle.
What does “convention-heavy” mean?
Maven expects projects to follow a common structure, which reduces custom decisions.
What does Maven use for configuration?
Mostly the pom.xml file.
5.1 Standard Maven project structure
project-root/
pom.xml
src/
main/
java/
resources/
test/
java/
resources/
This structure is powerful because tools, IDEs, plugins, and team members all know what to expect.
6. Understanding pom.xml
The heart of a Maven project is usually the pom.xml file. POM means Project Object Model.
Think of it as the formal description of your project.
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0
http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.example</groupId>
<artifactId>demo-app</artifactId>
<version>1.0.0</version>
<properties>
<maven.compiler.source>17</maven.compiler.source>
<maven.compiler.target>17</maven.compiler.target>
</properties>
<dependencies>
<dependency>
<groupId>org.junit.jupiter</groupId>
<artifactId>junit-jupiter</artifactId>
<version>5.12.2</version>
<scope>test</scope>
</dependency>
</dependencies>
</project>
6.1 Important pom.xml concepts
| Element | Meaning |
|---|---|
groupId | The organization or logical group that owns the project |
artifactId | The name of the artifact |
version | The version of the artifact |
dependencies | Libraries required by the project |
properties | Reusable values such as Java version |
build | Plugins and build customization |
groupId : artifactId : version.
6.2 Dependency scope in Maven
| Scope | Meaning |
|---|---|
compile | Available during compilation, testing, and runtime |
test | Available only during testing |
provided | Needed to compile, but expected to be provided by runtime environment |
runtime | Not needed for compilation, needed at runtime |
7. Maven lifecycle
Maven is strongly associated with its lifecycle phases. The most commonly discussed lifecycle is the default build lifecycle.
| Phase | What it broadly means |
|---|---|
validate | Check whether project structure and configuration are valid |
compile | Compile source code |
test | Run tests |
package | Create JAR, WAR, or another artifact |
verify | Run additional checks |
install | Put artifact into local Maven repository |
deploy | Publish artifact to remote repository |
mvn package, Maven usually runs all earlier required phases first.
8. Maven plugins
Maven is plugin-driven. Many actions are performed by plugins bound to lifecycle phases.
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<version>3.5.2</version>
</plugin>
</plugins>
</build>
9. Maven advanced topics
Parent POM
A parent POM can centralize versions and configuration used by many modules.
Dependency Management
You can declare versions once in dependencyManagement and reuse them.
Profiles
Profiles let you switch configuration based on environment or need.
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.junit.jupiter</groupId>
<artifactId>junit-jupiter</artifactId>
<version>5.12.2</version>
</dependency>
</dependencies>
</dependencyManagement>
10. Gradle from zero
Gradle is another major build tool. It is very popular in Java, Kotlin, Android, and many modern ecosystems. It is known for flexibility, speed features, powerful dependency handling, and task-based design.
How is Gradle different in spirit?
Gradle is task-oriented and highly programmable.
What files does Gradle use?
Commonly build.gradle, settings.gradle, or Kotlin DSL versions like build.gradle.kts.
project-root/
build.gradle
settings.gradle
gradlew
gradlew.bat
gradle/
src/
main/
java/
resources/
test/
java/
resources/
11. Understanding build.gradle
In Gradle, the build file describes plugins, repositories, dependencies, tasks, and other configuration.
plugins {
id 'java'
}
group = 'com.example'
version = '1.0.0'
repositories {
mavenCentral()
}
dependencies {
testImplementation 'org.junit.jupiter:junit-jupiter:5.12.2'
}
test {
useJUnitPlatform()
}
12. Gradle tasks and lifecycle
Gradle is very task-centric. A task is a named unit of work. Many tasks are added by plugins.
tasks.register('hello') {
doLast {
println 'Hello from Gradle'
}
}
13. Gradle advanced topics
Incremental builds
Gradle can avoid redoing work when inputs and outputs have not changed.
Build cache
Results can be reused, making builds faster.
Kotlin DSL
You can write Gradle files in Kotlin with .kts syntax.
rootProject.name = 'company-project'
include 'common', 'service', 'web'
14. Maven vs Gradle
Maven strengths
- Standard, predictable structure
- Strong convention over configuration
- Very common in enterprise Java
- Easy to read once you know the model
Gradle strengths
- Very flexible
- Task-based design
- Strong performance features
- Excellent for complex and modern build setups
15. Real-world workflow
Create project
You generate or write the Maven or Gradle build file.
Add dependencies
For example Spring Boot, JUnit, Jackson, database drivers.
Write code and tests
Source goes in main folders, tests go in test folders.
Run build
Compile, test, and package using build commands.
Use CI/CD
The same commands run on GitHub Actions, Jenkins, GitLab CI, or other systems.
Publish or deploy
Artifacts can be uploaded or deployed to servers and repositories.
16. Troubleshooting and common mistakes
Problem: dependency not found
- Check repository configuration.
- Check version string.
- Check internet access and proxy settings.
- Check whether the artifact coordinates are correct.
Problem: build runs but tests fail
- Read the first failing test carefully.
- Do not start with the last error line only.
- Check test dependencies and runtime assumptions.
Problem: project works on one machine only
- Use wrapper scripts.
- Standardize Java version.
- Avoid hidden local environment assumptions.
Problem: build is slow
- Avoid unnecessary tasks.
- Use build cache where appropriate.
- Check plugin behavior and repeated expensive steps.
17. Command cheat sheet with full explanations
This section explains each common command clearly. Every command below has a meaning, when to use it, and at least two examples.
17.1 Maven commands
This command deletes old build output, usually the target folder. Use it when you want a fresh build
without old compiled classes or old packaged files interfering.
Example 1
mvn clean
Use this when your project has stale old build files and you want to remove them.
Example 2
mvn clean package
Here clean runs first, then Maven builds a fresh artifact.
This command compiles the main source code of your project. It checks whether your production Java code compiles correctly.
It usually places compiled classes inside the target/classes folder.
Example 1
mvn compile
Use this to check whether your main application code compiles.
Example 2
mvn -q compile
This asks Maven to compile with quieter console output.
This command runs your test phase. It usually compiles test code and executes unit tests. It is one of the most important quality checks in a project.
Example 1
mvn test
Use this to run your test suite.
Example 2
mvn -Dtest=UserServiceTest test
This targets a specific test class named UserServiceTest.
This command takes the project through earlier necessary phases and creates the final package, such as a JAR or WAR, depending on project configuration.
Example 1
mvn package
Use this to build a distributable artifact like a JAR file.
Example 2
mvn package -DskipTests
This packages the project without running tests. Use carefully.
This command builds the project and places the artifact into your local Maven repository, usually under your home directory. This is useful when another local project depends on this artifact.
Example 1
mvn install
This makes your built artifact available to other local Maven builds.
Example 2
mvn clean install
This is a very common command for a full fresh local build plus local repository installation.
This command prints the dependency tree of your project. It helps you understand not only direct dependencies but also transitive dependencies that come in indirectly.
Example 1
mvn dependency:tree
Use this when you want to see what libraries are coming into the project.
Example 2
mvn dependency:tree -Dincludes=org.slf4j
This focuses the output on dependencies related to org.slf4j.
17.2 Gradle commands
This removes old build output, usually from the build folder.
Use it when you want a fresh build with no previously generated files.
Example 1
gradle clean
Use this to remove old compiled classes and previous artifacts.
Example 2
./gradlew clean
This does the same thing through the wrapper, which is often preferred in teams.
This is a broad build command. It usually compiles code, runs tests, and produces build outputs. In many projects this is the main command developers use most often.
Example 1
gradle build
Use this for a complete normal build.
Example 2
./gradlew build
This is the wrapper version and is usually safer for version consistency.
This runs the test task. It is used to execute tests without necessarily asking for a full packaging build.
Example 1
gradle test
Use this when you only want to validate tests.
Example 2
./gradlew test
This is the wrapper-based version of the same task.
This prints the list of available tasks in the current project. It is extremely useful when you are learning a project or trying to discover what actions are available.
Example 1
gradle tasks
Use this to explore the build script and plugins by seeing available tasks.
Example 2
./gradlew tasks
This is the same command through the wrapper.
This shows the dependency graph of your project. It helps you understand what libraries are present and where they come from.
Example 1
gradle dependencies
Use this when you want to inspect dependency resolution.
Example 2
./gradlew dependencies
This does the same through the wrapper.
This task creates a JAR artifact for Java projects that apply the Java plugin. It is more focused than build.
Example 1
gradle jar
Use this when you mainly want the JAR artifact.
Example 2
./gradlew jar
This creates the JAR using the project’s wrapper version.
This is specifically the wrapper version of a Gradle build command. It means the project is using its own configured Gradle version.
In real teams, this is often preferred over plain gradle build.
Example 1
./gradlew build
This runs a build using the Gradle version locked by the project.
Example 2
gradlew.bat build
This is the Windows batch-file equivalent.
18. Exercises
- Create a tiny Java project with Maven and add JUnit as a test dependency.
- Run
mvn testand observe what Maven creates in the output folder. - Create the same idea in Gradle and compare the build files.
- Add one logging dependency in both tools.
- Create a second module and understand how a multi-module structure works.
- Try using wrapper commands and compare them with system-installed commands.
19. MCQs — Test yourself
Answer these questions and then click the check button.