How to Create a Maven Project: Archetype, Directory Layout and IntelliJ IDEA
A command copied from an older tutorial, mvn archetype:generate -DarchetypeArtifactId=maven-archetype-quickstart -DarchetypeVersion=1.4 ..., finishes without errors, yet the very first build on JDK 21 fails with [ERROR] Source option 7 is no longer supported. Use 8 or later. Version 1.4 of the template wrote the maven.compiler.source and maven.compiler.target properties with the value 1.7 into pom.xml, and a modern javac no longer supports that version. A generated project is a starting point that needs checking, and this lesson shows exactly what to check.
Creating a Maven project means getting a directory with a pom.xml file (the project description and its coordinates groupId, artifactId and version) and the standard folder structure src/main/java, src/test/java and so on. There are three ways to do it: the mvn archetype:generate command based on a ready-made template (an archetype), the New Project wizard in IntelliJ IDEA, or manually by creating pom.xml and the directories yourself. The result is the same in every case: a project that builds with mvn package.
Ways to Create a Maven Project
You can create a Maven project with the mvn archetype:generate command (Maven must be installed), with the New Project wizard in IntelliJ IDEA (Maven is bundled with the IDE), or manually by writing pom.xml and creating the directories. For a simple console application all three give almost the same result; they differ in speed and in how much unnecessary content ends up in the project.
| Method | What you need | Pros | Things to know |
|---|---|---|---|
Command line: mvn archetype:generate | Installed Maven and JDK | Works everywhere, including without an IDE and on a server; suitable for scripts | The template may contain outdated settings - check pom.xml |
| IntelliJ IDEA: New Project → Maven | Only the IDE (Maven is bundled) | Fastest; the project is imported and ready to run right away | The wizard fields change slightly between IDE versions |
| IntelliJ IDEA: New Project → Maven Archetype | Only the IDE | Any archetype from the catalog, including webapp | The same outdated templates as on the command line |
| Manually | A text editor | Full control, nothing extra; this is how existing code is moved to Maven | You need to know the directory layout by heart (see the table below) |
Installing Maven and checking the installation is covered in the lesson How to Install Maven on Windows, Linux and macOS. For the IDE-based methods a separate installation is not required.
What Is a Maven Archetype
A Maven archetype is a project template published in a repository as a regular artifact: it contains a draft pom.xml, directories and sample classes. The mvn archetype:generate command downloads the archetype and creates a new project from it, substituting your groupId, artifactId, version and package name.
Archetypes can be official (group org.apache.maven.archetypes) or third-party, published by framework authors. You can also create your own archetype for a company's typical projects. The best-known official archetypes are:
| Archetype artifactId | What it creates | When to use it |
|---|---|---|
maven-archetype-quickstart | A project with packaging = jar, an App class with a main method and an AppTest test | Console applications, libraries, learning projects - the default choice |
maven-archetype-webapp | A project with packaging = war, a src/main/webapp directory with WEB-INF/web.xml and index.jsp | A servlet/JSP web application for Tomcat. The template's web.xml targets old versions of the Servlet specification - check and update it |
maven-archetype-simple | A simple project with a minimal structure | When you need a "clean" skeleton without extra samples |
maven-archetype-archetype | A skeleton for creating your own archetype | A template for a team's similar projects |
Spring Boot projects are usually created not with an archetype but with the start.spring.io generator (Spring Initializr): it also produces a regular Maven project with pom.xml and the same directory layout.
The mvn archetype:generate Command
The mvn archetype:generate command runs the generate goal of maven-archetype-plugin and creates a project in a subdirectory of the current folder (the subdirectory name equals the artifactId). It works in two modes: interactive, where it asks questions in the console, and batch, where all parameters are passed with -D in one command. Run it in a folder that does not contain a pom.xml yet.
Batch mode (recommended)
In batch mode (-DinteractiveMode=false) Maven asks nothing, so the command is easy to copy and repeat. Example for Linux, macOS and Git Bash:
mvn archetype:generate \
-DarchetypeGroupId=org.apache.maven.archetypes \
-DarchetypeArtifactId=maven-archetype-quickstart \
-DarchetypeVersion=1.5 \
-DgroupId=com.examclouds \
-DartifactId=hello-maven \
-Dversion=1.0-SNAPSHOT \
-DinteractiveMode=false On Windows the backslash does not work as a line continuation (in cmd it is ^, in PowerShell the backtick `), so it is easier to write the command on one line. In PowerShell, wrap every -D argument in quotes:
mvn archetype:generate "-DarchetypeGroupId=org.apache.maven.archetypes" "-DarchetypeArtifactId=maven-archetype-quickstart" "-DarchetypeVersion=1.5" "-DgroupId=com.examclouds" "-DartifactId=hello-maven" "-Dversion=1.0-SNAPSHOT" "-DinteractiveMode=false" Output (fragment; the list of parameters depends on the archetype version):
[INFO] Using following parameters for creating project from Archetype: maven-archetype-quickstart:1.5
[INFO] ----------------------------------------------------------------------------
[INFO] Parameter: groupId, Value: com.examclouds
[INFO] Parameter: artifactId, Value: hello-maven
[INFO] Parameter: version, Value: 1.0-SNAPSHOT
[INFO] Parameter: package, Value: com.examclouds
...
[INFO] Project created from Archetype in dir: /home/user/hello-maven
[INFO] BUILD SUCCESS Command parameters:
| Parameter | What it sets | If omitted |
|---|---|---|
archetypeGroupId, archetypeArtifactId | Which archetype to use | Batch mode uses quickstart; interactive mode offers a list |
archetypeVersion | The template version - it determines what goes into pom.xml | Taken from the archetype catalog; which version exactly depends on the plugin and catalog version. Always set it explicitly |
groupId, artifactId, version | Coordinates of the new project (see the naming rules) | In batch mode groupId and artifactId are required; version defaults to 1.0-SNAPSHOT |
package | The Java package for the sample classes | Equal to groupId |
interactiveMode | false - ask no questions | Interactive mode |
PowerShell and arguments with dots
Without quotes, PowerShell splits the argument -DgroupId=com.examclouds at the dot and passes two words to Maven: -DgroupId=com and .examclouds. Maven treats the second one as a phase name and stops with Unknown lifecycle phase ".examclouds". cmd and bash do not have this problem; in PowerShell write "-DgroupId=com.examclouds" or run the command from cmd.
Interactive mode
If you run mvn archetype:generate without parameters, Maven loads the archetype catalog and prints a long numbered list with the prompt Choose a number or apply filter. The default number points to maven-archetype-quickstart, but the numbers themselves change whenever the catalog is updated, so it is easier to type a filter such as quickstart. Maven then asks in turn for the archetype version, groupId, artifactId, version and package, and asks you to confirm the parameters (Y). Interactive mode is handy for exploring which archetypes exist; for a reproducible result use batch mode.
What quickstart generates and what to fix in pom.xml
The maven-archetype-quickstart archetype creates pom.xml, an App class whose main method prints Hello World!, and a stub test AppTest:
hello-maven/
├── pom.xml
└── src/
├── main/java/com/examclouds/App.java
└── test/java/com/examclouds/AppTest.java The content of pom.xml depends heavily on the archetype version. Versions up to and including 1.4 use JUnit 4 (the oldest ones even JUnit 3.8.1) and set the Java version with the pair maven.compiler.source/maven.compiler.target set to 1.7 - JDK 20 and newer no longer compile that. In version 1.5 the template moved to JUnit 5 (Jupiter) and the maven.compiler.release property. After generating the project, open pom.xml and check three things:
- Java version. There should be a single
maven.compiler.releaseproperty with your JDK version or lower (for example,17or21). Replace thesource/targetpair withrelease- the reason is explained in the lesson What Is Maven. - JUnit version. If the dependencies contain
junit:junit3.x or 4.x and you write tests with JUnit 5, replace the dependency withorg.junit.jupiter:junit-jupiterwithscope=testand fix the imports inAppTest. - Encoding. The property
project.build.sourceEncoding=UTF-8- without it Maven warns about platform-dependent encoding, and builds on different operating systems may read non-ASCII strings differently.
The template's pluginManagement block with pinned plugin versions can stay: it makes the build reproducible. The meaning of each pom.xml tag is covered in a separate lesson of this module on the pom.xml file.
How to Choose groupId, artifactId and version
groupId is the organization or project group written as a reversed domain name (com.examclouds), artifactId is the project name in lowercase words separated by hyphens (hello-maven), and version is the version number; during development it gets the -SNAPSHOT suffix (1.0-SNAPSHOT). Together they form the project's GAV coordinates, by which it is found in a repository.
| Coordinate | Rule | Good | Bad |
|---|---|---|---|
groupId | A reversed domain you own (or io.github.your-login); stick to lowercase Latin letters, digits and dots so that it is also a valid Java package name | com.examclouds, org.example.shop | MyCompany, com.my-company (a hyphen is not allowed in a package name) |
artifactId | The project name in lowercase, words separated by hyphens, no spaces and no version | hello-maven, online-shop | Hello Maven, shop-1.0 |
version | A version number; -SNAPSHOT means a version in development, no suffix means a released version | 1.0-SNAPSHOT, 1.0.0 | last, v1 final |
By default the archetype derives the Java package name from groupId, so the classes end up in com/examclouds/. If groupId contains a hyphen or a segment that starts with a digit, the generated package will not compile - set a valid -Dpackage explicitly. The artifactId and version form the name of the built file: hello-maven-1.0-SNAPSHOT.jar. How SNAPSHOT versions differ from releases when working with repositories is covered in the lesson on the pom.xml file in this module.
Maven Project Structure
A Maven project uses a fixed structure called the Standard Directory Layout: main code goes in src/main/java, resources in src/main/resources, tests in src/test/java and src/test/resources, and the build output appears in target. Maven knows these paths by default, so you do not declare them in pom.xml - you only need to put files in the right place.
hello-maven/
├── pom.xml
├── src/
│ ├── main/
│ │ ├── java/
│ │ │ └── com/examclouds/App.java
│ │ └── resources/
│ │ └── app.properties
│ └── test/
│ ├── java/
│ │ └── com/examclouds/AppTest.java
│ └── resources/
│ └── test-data.json
└── target/ # created by Maven, do not commit
├── classes/
├── test-classes/
└── hello-maven-1.0-SNAPSHOT.jar | Directory | What goes there | Where it ends up after the build |
|---|---|---|
src/main/java | Application source code (.java) in folders that mirror packages | Compiled into target/classes → included in the jar/war |
src/main/resources | Configuration and data: .properties, .xml, .yml, templates, SQL scripts | Copied to target/classes → the classpath root and the jar |
src/test/java | Tests (JUnit) in the same packages as the code under test | Compiled into target/test-classes, not included in the jar |
src/test/resources | Files needed only by tests: test data, test configuration | Copied to target/test-classes, not included in the jar |
src/main/webapp | Only for packaging = war: WEB-INF/web.xml, JSP, static files | The root of the war archive |
target | Nothing by hand - this is the build output | Deleted by mvn clean; add it to .gitignore |
Folders inside src/main/java mirror packages: the class com.examclouds.App lives in src/main/java/com/examclouds/App.java. Its test is conventionally placed in the same package under src/test/java - then the test can also access package-private members of the class.
What happens if a file is in the wrong place
Maven does not search the whole project for files: the compiler takes .java files only from the java directories, and resource copying works only from resources. A misplaced file often does not break the build; the problem shows up later, at runtime or in tests.
| What you did | What happens |
|---|---|
Put a JUnit test class in src/main/java | The build fails at compilation: package org.junit.jupiter.api does not exist - the JUnit dependency has scope = test, so main code cannot see it |
Put config.properties next to the classes in src/main/java | The build succeeds, but the file is missing from target/classes and the jar: getClass().getResourceAsStream("/config.properties") returns null |
Put a .java file in src/main/resources | The file is copied as text and never compiled; at runtime you get ClassNotFoundException or Could not find or load main class |
Named a test CheckCalculator.java | It compiles but never runs: the Surefire plugin by default runs classes named Test*, *Test, *Tests, *TestCase. The mvn test output shows Tests run: 0 or no test block at all |
Created a src/java or source/main/java folder | Maven does not see it: No sources to compile, the jar is empty (manifest only) |
The standard paths can be overridden in pom.xml, but that is worth doing only when moving an old project to Maven that cannot be reorganized. The configuration is shown in the lesson on the pom.xml file in this module.
Maven Project in IntelliJ IDEA
To create a Maven project in IntelliJ IDEA, open the New Project wizard (File → New → Project), choose the Java generator with Maven as the build system or the Maven Archetype generator, and specify the name, location, JDK and GroupId/ArtifactId coordinates. The IDE creates pom.xml and the standard directories and imports the project immediately. You do not need to install Maven separately - it is bundled with the IDE.
The item names below match current versions of IntelliJ IDEA (Community and Ultimate); in older versions the wizard looks different, but the fields are the same.
New project: wizard fields
| Field | What to enter |
|---|---|
| Name | The project and folder name; the IDE also uses it as the ArtifactId |
| Location | The parent directory; preferably a path without spaces or non-ASCII characters |
| Build system | Maven (in the Java generator); the default may be IntelliJ - then the project has no pom.xml |
| JDK | An installed JDK 17 or 21; if none is installed, the IDE offers to download one |
| Add sample code | Create a Main class with a main method |
| GroupId, ArtifactId (Advanced Settings) | Project coordinates following the rules above |
| Catalog, Archetype, Version (Maven Archetype generator only) | The archetype catalog, the archetype itself (for example, org.apache.maven.archetypes:maven-archetype-quickstart) and its version - the same as the archetypeArtifactId and archetypeVersion parameters on the command line |
The Java generator with Build system = Maven usually produces a cleaner pom.xml than the old archetypes: the Java version in it comes from the selected JDK. Still, review the generated file against the checklist in the quickstart section.
The Maven tool window and syncing after editing pom.xml
The Maven tool window (usually on the right sidebar) shows the project as a tree: Lifecycle - build phases you run with a double-click (clean, compile, test, package...), Plugins - the configured plugins and their goals, Dependencies - the dependency tree.
IntelliJ IDEA does not re-read pom.xml on every keystroke. After you edit the file, a floating Load Maven Changes button appears in the editor (default shortcut Ctrl+Shift+O on Windows and Linux, Cmd+Shift+I on macOS). The Maven tool window has a Reload All Maven Projects button that does the same. Until the changes are loaded, a new dependency is highlighted in red in the code even though it is already in pom.xml.
Importing an existing project
An existing Maven project (for example, one cloned from Git) is opened with File → Open: select the pom.xml file and click Open as Project in the dialog (you can also select the folder that contains pom.xml). The IDE configures the source folders, JDK and dependencies on its own. If pom.xml sits in a subfolder and the IDE did not recognize it, right-click the file and choose Add as Maven Project.
Bundled Maven or your own: settings
Maven settings are under Settings (on macOS, Preferences) → Build, Execution, Deployment → Build Tools → Maven:
- Maven home path - Bundled (shipped with the IDE) or the path to your own installation. Point it to your installation if you need the same Maven version as in the terminal and on CI.
- User settings file and Local repository - paths to
settings.xmland to the local repository (by default under~/.m2); repository types are covered in a separate lesson of this module. - The Runner subsection - the JDK that runs Maven and the Delegate IDE build/run actions to Maven option: with it, the Build and Run buttons go through Maven instead of the IDE's own builder.
If the project contains the Maven Wrapper, the IDE can use its Maven version - what mvnw is, is explained in the lesson What Is Maven.
Tricky case: builds in the IDE, fails in the terminal
The bundled Maven is available only inside the IDE: in the Terminal tab the mvn command is not found unless Maven is installed on the system. Besides, the IDE and the terminal may run Maven on different JDKs (Runner in the IDE settings vs JAVA_HOME). If the project builds with the IDE button but fails in the terminal with a Java version error, compare the Java version line in the mvn -version output with the JDK in the Runner settings.
Creating a Maven Project Manually
A Maven project can be created by hand in two minutes: a project directory containing pom.xml with the coordinates and Java version, plus the src/main/java and src/test/java folders with package subdirectories. The same approach is used to move existing code to Maven: sources go into src/main/java, and jar files from a lib folder are replaced with dependencies in pom.xml.
# Linux, macOS, Git Bash
mkdir -p hello-maven/src/main/java/com/examclouds hello-maven/src/main/resources hello-maven/src/test/java/com/examclouds
# Windows (PowerShell)
New-Item -ItemType Directory -Force hello-maven/src/main/java/com/examclouds, hello-maven/src/main/resources, hello-maven/src/test/java/com/examclouds Put pom.xml into the hello-maven root - a minimal working version of about a dozen lines is shown in the lesson What Is Maven - and a class with a main method into src/main/java/com/examclouds:
package com.examclouds;
public class App {
public static void main(String[] args) {
System.out.println("Hello World!");
}
} First Build and Run
Check the first build with three commands in the project root (where pom.xml is): mvn compile compiles the code into target/classes, mvn test also runs the tests, and mvn package builds a jar in target. Each command also runs the steps before it. The first run takes longer than usual because Maven downloads plugins into the local repository.
cd hello-maven
mvn test Output (fragment for a quickstart project):
[INFO] -------------------------------------------------------
[INFO] T E S T S
[INFO] -------------------------------------------------------
[INFO] Running com.examclouds.AppTest
[INFO] Tests run: 1, Failures: 0, Errors: 0, Skipped: 0
...
[INFO] BUILD SUCCESS mvn package
java -cp target/hello-maven-1.0-SNAPSHOT.jar com.examclouds.App Output:
[INFO] Building jar: /home/user/hello-maven/target/hello-maven-1.0-SNAPSHOT.jar
[INFO] BUILD SUCCESS
Hello World! Note that running java -jar target/hello-maven-1.0-SNAPSHOT.jar fails with no main manifest attribute, in target/hello-maven-1.0-SNAPSHOT.jar - the archetype does not write the main class into the jar manifest. That is why the class is specified explicitly with -cp; adding Main-Class to the manifest via plugin configuration is covered in a separate lesson of this module on Maven plugins. If the project uses third-party libraries, they also have to be added to -cp - a regular jar does not contain them.
Why mvn package runs compilation and tests by itself, and how the phases differ, is covered in the lesson on the Maven build lifecycle in this module. How to run Java programs without Maven, with javac and java, is shown in the lesson Creating and Running a Java Application.
Where Beginners Get Tripped Up
Most problems with a first Maven project come down to where the command is run, which JDK Maven uses and which directory a file was put in. Below are the error messages and how to fix them.
| Symptom | Cause | Fix |
|---|---|---|
The goal you specified requires a project to execute but there is no POM in this directory | The command was run outside the project root - for example, right after archetype:generate without changing into the created folder | cd hello-maven and repeat the command |
Source option 7 is no longer supported. Use 8 or later. | An old archetype set source/target to 1.7 | Replace them with maven.compiler.release = 17 or 21 |
release version 21 not supported | Maven runs on a JDK older than the version in release | Check the JDK in mvn -version and JAVA_HOME, or lower release |
Unknown lifecycle phase ".examclouds" | PowerShell split the -DgroupId=com.examclouds argument | Wrap every -D... argument in quotes |
| The IDE does not highlight code, there is no Maven window, imports are red | The project was opened as a plain folder; pom.xml was not imported | Right-click pom.xml → Add as Maven Project, or File → Open → pom.xml → Open as Project |
A new dependency is in pom.xml, but the IDE cannot find the class | The pom.xml changes were not loaded | Load Maven Changes or Reload All Maven Projects |
package org.junit.jupiter.api does not exist during mvn compile | The test is in src/main/java, or JUnit has the wrong version/artifact | Move the test to src/test/java; check the JUnit dependency |
Quiet failure: a test that never runs
A test class in the correct src/test/java directory but named something like CalculatorCheck compiles without errors, and mvn test ends with BUILD SUCCESS - because not a single test was executed. In the IDE the same class runs with the Run button, which adds to the confusion. Name test classes with the *Test pattern so that both the Surefire plugin and the CI server find them.
Frequently Asked Questions
Do I have to use an archetype to create a Maven project?
No. An archetype is just a quick way to get a skeleton. What makes a directory a Maven project is the pom.xml file and the standard folder layout, and you can create both manually or with the IntelliJ IDEA wizard without any archetype. Step by step - in the section Creating a Maven Project Manually.
How do I convert a regular Java project into a Maven project?
Create a pom.xml in the root with the coordinates and Java version, move the sources into src/main/java keeping the package folders, configuration files into src/main/resources and tests into src/test/java. Replace the jar files from the lib folder with dependencies in pom.xml. Then in IntelliJ IDEA right-click pom.xml and choose Add as Maven Project.
Should I commit the target directory and .idea files to Git?
Not target: it is build output and is recreated by mvn package. IDE files (.idea, *.iml) are not required for a Maven project either - IntelliJ IDEA restores the settings from pom.xml. Commit pom.xml, src and, if you use it, the Maven Wrapper.
Where should test data go: src/test/resources or src/main/resources?
In src/test/resources. These files are visible to tests on the classpath but are not packaged into the final jar. If you put test data into src/main/resources, it ships with the production build and can override the real configuration when file names match.
How do I create a Spring Boot Maven project?
With the Spring Initializr generator: on start.spring.io choose Project = Maven, the Java version and the modules you need, download the archive and open pom.xml in the IDE as a project. In IntelliJ IDEA Ultimate the same generator is built into the New Project wizard. The result uses the standard Maven directory layout.
Comments