How to Structure a Simple Java Project

Diagram showing standard Java project folders and package structure

Introduction

A clear project structure makes Java code easier to understand, navigate, and build. Even for small applications, following common conventions helps other developers quickly find classes, tests, and configuration files.

This tutorial explains how to organize a simple Java project using a layout that works well with common build tools and IDEs. You will learn where to put source files, how to name packages, and how build descriptors such as pom.xml or build.gradle fit into the picture.

Who This Guide Is For

This guide targets developers who are starting new Java projects without heavy frameworks. It is especially useful if you:

Prerequisites

To follow along, you should have:

Step-by-Step Instructions

Step 1: Create the Project Root

Start by creating a directory for your project, for example my-app. This folder will contain all source code, tests, and build files. Inside my-app, create a src directory to hold your Java sources.

Step 2: Add Main and Test Source Folders

Within src, create two subfolders: main and test. Under each, create a java directory. The resulting layout looks like this:

my-app/
  src/
    main/
      java/
    test/
      java/

This structure matches the conventions used by Maven and Gradle, which means they automatically know where to find production and test code.

Step 3: Define a Package Structure

Inside src/main/java, create a package directory tree that matches your chosen package name, such as com/example/app. Avoid using very short or generic package names; instead, use your domain or organization to keep names unique.

Create a class in this package called App with a main method so you can verify that the structure works.

Step 4: Add Build Files

Even if you start with manual compilation, adding a build file early makes it easier to scale the project. For Maven, create a pom.xml file in the project root. For Gradle, create a build.gradle or build.gradle.kts file.

At minimum, the build file should declare the group ID, artifact ID, version, and source compatibility. This allows IDEs to import the project and manage dependencies later without reworking the structure.

Step 5: Mirror Packages in Tests

Under src/test/java, create matching package directories for your tests, such as com/example/app. Place your test classes here, following a naming pattern like AppTest. Mirroring the package structure keeps tests aligned with the code they verify.

Common Mistakes and How to Avoid Them

A frequent mistake is placing Java source files directly in the project root or in arbitrary folders. While this may work for very small scripts, it quickly becomes unmanageable as the project grows and makes it harder for tools to infer structure.

Another issue is mixing test code with production code in the same folder. Separating them into main and test trees helps maintain clear boundaries and prevents test utilities from accidentally shipping with production artifacts.

Finally, inconsistent package names can cause confusion. Changing package names after the project grows requires updating many files. Decide on a clear naming convention early and stick to it.

Practical Example or Use Case

Imagine you are creating a small REST API service. Following this structure, you can create packages such as com.example.app.controller, com.example.app.service, and com.example.app.model. Controllers handle HTTP requests, services contain business logic, and models represent data.

When another developer joins the project, they can immediately understand where to place new classes. Build tools can also automatically run tests, package the application, and generate artifacts because the structure matches their expectations.

Summary

A simple, conventional project structure saves time and reduces friction as your Java codebase evolves. By organizing code into main and test trees, using consistent package names, and adding build files early, you create a foundation that scales from small experiments to production applications.

Adopting these practices from the beginning helps your projects remain maintainable and welcoming to new contributors.