Code Organisation
Last modified on Fri 17 Apr 2026

Packaging

The Java ecosystem provides many guidelines about structuring a project and naming things the right way.

Source and test files

Starting from the project root folder, source classes and resources should be placed in src/main/java, while test classes and resources should be placed in src/test/java. The base package is named by the reversed domain name of the company, followed by the project name, e.g. com.infinum.myapp.

Compiled sources (.class files) or sources generated by a framework e.g. Jooq, QueryDsl etc. should be excluded from the source files and handled by .gitignore to prevent codebase pollution. If necessary, a goal can be declared in the generate-sources phase which will handle generating these files in a designated directory (e.g. target/build).

If the project is based on Spring Boot, the main class (annotated with @SpringBootApplication) needs to be placed in the base package, e.g. com.infinum.myapp (Spring docs reference).

Non-source resources (.properties, .xml, .yml etc.) are placed in src/main/resources or src/test/resources, respectively.

Package naming

Refer to the official Oracle docs to check if you are doing things by convention.

Package organization

At Infinum, we use package-by-layer embedded in package-by-feature for organizing packages. This means that the features are split into their packages, e.g. customer, order, product, and each of these feature packages contains a package for each layer of the feature, e.g. model, repository, service, web etc.

An example of this is:

co
 +- infinum
     +- app
         +- Main.java
         |
         +- customer
         |    +- model
         |       | +- Customer.java
         |    +- repository
         |       | +- CustomerRepository.java
         |    +- service
         |       | +- CustomerService.java
         |    +- web
         |       | +- CustomerController.java
         |
         +- order
              +- model
                 | +- Order.java
                 | +- OrderProjection.java
              +- repository
                 | +- OrderRepository.java
              +- service
                 | +- OrderService.java
              +- web
                 | +- OrderController.java

One more thing to keep in mind when organizing classes into packages: avoid cyclic dependencies as they can cause unnecessary complexity. IntelliJ IDEA offers a great plugin which allows you to analyze dependency structure matrix by using Analyze -> Analyze Dependency Matrix action. Ideally you would want that matrix to be lower triangular, but this is not strictly enforced. Most important thing is not to have any red elements in the matrix.

More about packaging by layer

When placing classes according to package-by-layer, one of the recommended ways to place source files is as follows:

Build tools

The two most popular build tools in the Java community are Maven and Gradle. At Infinum, we use Gradle by default.

Maven

Maven helps in managing project dependencies, application packaging, executing various goals (clean, build, test) etc. A Maven project is described by its Project Object Model (pom.xml) file, where the project's metadata, dependencies and various tasks throughout the build phases are declared. Maven commands are usually run from the terminal in the project root (where pom.xml is located).

Useful links:

Gradle

Gradle is another build tool used to handle various tasks like above, however there are some differences between the two. If migrating from Maven, check the Migrating from Maven guide.

Modern Gradle features to consider: * Use version catalogs for dependency management * Use Gradle Wrapper for consistent builds across environments

Other useful links:

Coding guidelines

SOLID

Modern Java Features

When organizing code, consider using these modern Java features: