---
title: "Maven (Java)"
order: 8
---

A Maven feed in ProGet acts as a "maven2-compatible" artifact repository. Clients such as Maven, Gradle, and SBT can publish and consume artifacts in a Maven feed, and you can browse artifacts using the ProGet web application.

## Prerequisite Configuration

### Maven Client Configuration

We recommend using newer versions of the Maven client; see [Maven Releases History](https://maven.apache.org/docs/history.html) to learn which versions are considered end-of-life.

To install packages and plugins from ProGet, you need to modify Maven's `settings.xml` file. This is the Maven configuration file, which is described in detail in the [Maven's Settings Reference Documentation](https://maven.apache.org/settings.html). 

If you are not familiar with how to edit this file, you can follow the steps below. For simplicity, these steps assume that you have a single feed that contains all the public and private artifacts that you want to use.

#### 1. Locate your Settings.xml File

The `settings.xml` file may exist in two different places:
- `«maven-install-directory»/conf/settings.xml` - global-level settings for all users on the machine
- `«user-home-directory»/.m2/settings.xml` - user-level settings that can override any global settings

You can find your `«maven-install-directory»` by running `mvn --version`, and the `«user-home-directory»` is `~/` on Linux or `%UserProfile%` on Windows. If both files are available, we generally recommend editing the global settings file,

If you can't find a `settings.xml` file in either location, you can create one using the template below.

```xml
<settings xmlns="http://maven.apache.org/SETTINGS/1.0.0"
          xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
          xsi:schemaLocation="http://maven.apache.org/SETTINGS/1.0.0 https://maven.apache.org/xsd/settings-1.0.0.xsd">
  <localRepository/>
  <interactiveMode/>
  <offline/>
  <pluginGroups/>
  <servers/>
  <mirrors/>
  <proxies/>
  <profiles/>
  <activeProfiles/>
</settings>
```

#### 2. Add a ProGet profile

Profiles are used by Maven to store repository settings and we recommend adding an active profile called `ProGet`. To do this, you need to edit the `profiles` and `activeProfiles` nodes as follows:

```xml
<profiles>
    <profile>
        <id>ProGet</id>
        <repositories />
        <pluginRepositories />
    </profile>
</profiles>
<activeProfiles>
    <activeProfile>ProGet</activeProfile>
</activeProfiles>
```

#### 3. Configure ProGet Feed as Repositories

Maven uses two types of repositories:
* normal repositories, which are used for libraries and other artifacts
* plugin repositories, which are used for the many plugins that Maven requires

When searching for content (i.e. ordinary artifacts or plugins), Maven will look in the `settings.xml` files for a repository named `central`. If this isn't found, the default repository on `maven.org` will be used.

Therefore, we recommend adding a `central` repository to your `settings.xml` by editing the `repositories` and `pluginRepositories` nodes as follows:

```xml
<repositories>
    <repository>
        <id>central</id>
        <url>«maven-feed-api-endpoint»</url>
        <snapshots><enabled>true</enabled></snapshots>
        <releases><enabled>true</enabled></releases>
    </repository>
</repositories>
<pluginRepositories>
    <pluginRepository>
        <id>central</id>
        <url>«maven-feed-api-endpoint»</url>
        <snapshots><enabled>true</enabled></snapshots>
        <releases><enabled>true</enabled></releases>
    </pluginRepository>
</pluginRepositories>
```

The `«maven-feed-api-endpoint»` can be found on the browse feed page in ProGet.

#### 4. Add a Repository Mirror

A POM file can reference a Maven repository directly, bypassing your `settings.xml` configuration. To prevent this, we recommend also configuring a mirror to ensure that all artifact requests go to your feed.

```xml
<mirrors>
	<mirror>
	  <id>proget</id>
	  <name>ProGet</name>
	  <url>«maven-feed-api-endpoint»</url>
	  <mirrorOf>*</mirrorOf>
	</mirror>
</mirrors>
```

If you want to mirror a specific repository, you can change the `mirrorOf` to be the ID of a repository.

#### 5. (Optional) Authenticate to Your Feeds

If you've [configured a restricted feed](/docs/proget/administration-security/proget-howto-configure-permissions-and-restrictions-on-feeds), you must configure Maven to authenticate with ProGet.

To do this, we recommend that you first [create an API key](/docs/proget/reference-api/proget-apikeys) that has the appropriate permissions for your Maven feed (generally, read and publish). Once you have that, you can edit the `servers` node of your `settings.xml` file as follows:

```xml
<servers>
    <server>
        <id>central</id>
        <username>api</username>
        <password>«api-key»</password>
    </server>
</servers>
```

#### Example: settings.xml

To put it all together, here is an example `settings.xml` that will push/pull artifacts and plugins from `http://progetsv:8624/maven2/my-maven/` using the API key `apiKey12345`.

```xml
<settings xmlns="http://maven.apache.org/SETTINGS/1.0.0"          
          xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
          xsi:schemaLocation="http://maven.apache.org/SETTINGS/1.0.0 http://maven.apache.org/xsd/settings-1.0.0.xsd">
    <servers>
        <server>
            <id>central</id>
            <username>api</username>
            <password>apiKey12345</password>
        </server>
    </servers>
    <profiles>
        <profile>
            <id>ProGet</id>
            <repositories>
                <repository>
                    <id>central</id>
                    <url>http://progetsv:8624/maven2/my-maven</url>
                    <snapshots><enabled>true</enabled></snapshots>
                    <releases><enabled>true</enabled></releases>
                </repository>
            </repositories>
            <pluginRepositories>
                <pluginRepository>
                    <id>central</id>
                    <url>http://progetsv:8624/maven2/my-maven</url>
                    <snapshots><enabled>true</enabled></snapshots>
                    <releases><enabled>true</enabled></releases>
                </pluginRepository>
            </pluginRepositories>
        </profile>
    </profiles>
    <activeProfiles>
        <activeProfile>ProGet</activeProfile>
    </activeProfiles>
    <mirrors>
        <mirror>
            <id>proget</id>
            <name>ProGet</name>
            <url>«maven-feed-api-endpoint»</url>
            <mirrorOf>*</mirrorOf>
        </mirror>
    </mirrors>    
</settings>
```

## Installing Packages

To add a Maven package to a Maven project, you  need to add a dependency to your project's `pom.xml`.

```xml
<dependency>
   <groupId>joda-time</groupId>
   <artifactId>joda-time</artifactId>
   <version>2.2</version>
</dependency>
```

These can then be installed using `mvn install`.

## Creating Packages

Maven inherently includes a lifecycle for creating a package. You can create a package by running the following commands:

```bash
mvn install
mvn compile
mvn package
```

## Publishing Packages

Publishing Maven packages requires a distribution repository to be added to your `pom.xml`  as follows:

```xml
<distributionManagement>
    <repository>
        <id>central</id>
        <name>ProGet</name>   
        <url>«maven-feed-api-endpoint»</url>
        <layout>default</layout>
    </repository>
</distributionManagement>
```

This distribution repository will use the authentication credentials specified in your `settings.xml`, under the `servers` node. In the case above, this will use the `central` server. 

To publish a Maven package and deploy it to ProGet, just run the `mvn deploy` operation. 

### Best Practice: Use Properties for Repository URL

Instead of specifying the repository URL directly, we recommend using a property. This not only allows you to override the setting when you run the `mvn deploy` command, but also allows you to specify the property in the `settings.xml` file instead of in each project.

To do this, add (or edit) the `properties` node under the ProGet profile in your `settings.xml` file:

```xml
<profiles>
    <profile>
        <id>ProGet</id>
        <properties>
            <distribution-repository>«maven-feed-api-endpoint»</distribution-repository>
        </properties>
        ... snip ...
```

You can then use a property in your POM file, like this:

```xml
<distributionManagement>
    <repository>
        <id>central</id>
        <name>ProGet</name>   
        <url>${distribution-repository}</url>
        <layout>default</layout>
    </repository>
</distributionManagement>
```

## Snapshot versions

[Snapshot versions](https://maven.apache.org/guides/getting-started/index.html#What_is_a_SNAPSHOT_version) allow you to work with unstable (i.e. pre-release) versions of a library. This is common when you're developing an application—and libraries that the application consumes—at the same time.

### Using Snapshot Dependencies

You can use a snapshot version of a dependency by adding `-SNAPSHOT` to a dependency's version number in your POM file. For example:

```xml
<dependency>
   <groupId>corp.kramerica</groupId>
   <artifactId>common-library</artifactId>
   <version>2.2-SNAPSHOT</version>
</dependency>
```

When specified in a dependency, `-SNAPSHOT` acts as a wildcard. When you run `mvn install`,  Maven will search the repository for the latest matching version starting with `2.2`. In the example above, this means that `2.2-SNAPSHOT` could be `2.2.0`, `2.2.1`, `2.2.4-alpha1`, etc.

By convention, any version number containing a `-` is considered "unstable".

### Publishing Snapshot Dependencies

To publish (deploy) an unstable snapshot version of a library, simply append `-SNAPSHOT` to the version number in your POM file. For example:

```xml
<project>
  ... snip ...
   <groupId>corp.kramerica</groupId>
   <artifactId>common-library</artifactId>
   <version>2.2-SNAPSHOT</version>
  ... snip ...   
</project>
```

After doing this, when you run the `mvn deploy` command, Maven will simply replace the `-SNAPSHOT` with a timestamp of when it was published. For example, if your POM file specified `2.2-SNAPSHOT`, then Maven will deploy something like `2.2-20230308.201920-3` to the repository instead.

:::(Error) (Don't Use `deploy:deploy-file` with `-SNAPSHOT` Artifacts)
Maven has a [deploy:deploy "mojo"](https://maven.apache.org/plugins/maven-deploy-plugin/usage.html) that publishes (deploys) a file directly to a repository. You can specify a version number with this command; if you do, Maven will **not** replace it with a timestamp. This leads to unpredictable behavior in both Maven and ProGet.
:::

:::(Warning) (Use Standardized Versioning with SNAPSHOT Versions)
Maven uses a 5-part scheme for version numbers: major, minor, incremental, build, and qualifier. This is "documented" in the Maven source code, and explained in detail in an [archived Codehaus article](https://web.archive.org/web/20150308195657/http://docs.codehaus.org/display/MAVEN/Versioning).

If you don't use "standard" versions (for example, if you were to use a 6-part version number), then both Maven and ProGet will behave in unpredictable ways.
:::

### ProGet and Snapshot Versions

Although Maven has built-in support for separate snapshot and non-snapshot repositories, we recommend using a single ProGet feed for both artifacts. This makes things easier and you can automatically configure [retention rules](/docs/proget/administration/retention-rules) to clean up old, unstable versions.

Note that when browsing a Maven feed of snapshot versions, you shouldn't see a version that ends in `-SNAPSHOT`. Instead, you'll see artifacts with timestamps instead of the string `-SNAPSHOT`. However, when a snapshot version is used for a dependency, Maven looks for files named `-SNAPSHOT`. To handle these requests, ProGet will simply return the latest version of the artifact. 

## Bulk Importing Using a Drop Path

### ProGet 2023.21 and Above

ProGet 2023.21 adds [Drop Path](/docs/proget/feeds/feed-overview/proget-bulk-import-with-droppath) support to Maven Feeds. Maven packages are made up of a POM file and one or more artifacts, like jar, war, ear, xml, etc...  When adding Maven packages to a drop folder, each package should be its own folder that contains the POM file, and all related artifacts. When Maven packages are imported via a drop path, ProGet will first find all files that end with `.pom` and then will add any artifacts in the same folder as that POM file.

::: (Warning) (SNAPSHOTS are not supported)
Due to how Maven handles SNAPSHOT packages, packages using a SNAPSHOT version cannot be imported using a drop path.
:::

### ProGet 2023.20 and Below

ProGet 2023.20 and below do not currently support import drop paths for Maven, but we are considering adding this in a future release. Please consider joining [the existing discussion in our forums](https://forums.inedo.com/topic/3128) if this feature would be of interest to you.

To work around this limitation, follow this approach:

1. Go through all directories and upload all POM files with a path relative to the root directory
2. Go through all directories again and upload all files that do not have POM and a checksum (like .md5)

Errors will occur, especially if you have invalid POM files or your directory structure does not conform to the required MAVEN convention. So check on a case-by-case basis if this matters (a bad artifact from 5 years ago can probably be ignored).

You can use a tool like `curl` or even `maven deploy:deploy` to deploy individual files.

## Maven (Classic) Feed Types

In ProGet 2024.14, we created a new Maven feed type called "Maven (New)" feeds and called the old feeds to "Maven (Classic)". In ProGet 2025, the old feeds will be called "Maven (Legacy)" and the new will be simply "Maven".

The key differences between the feed types is underlying code and the metadata indexes (i.e. database tables) that are used. The new feed use the "packages index" and common code that most other feed types use, while the old feed use separate indexes doesn't share much code.

In addition to reducing technical debt and simplifying maintenance, the main benefit to the new Maven feeds is that they can be used in [pgutil](https://docs.inedo.com/docs/proget/reference-api/proget-pgutil) and queried with the [packages API](https://docs.inedo.com/docs/proget/reference-api/proget-api-packages).

The new feeds also include a "file browser" at the Maven API endpoint, which looks similar to [Maven Central](https://repo1.maven.org/maven2/) and other file-based repositories.


### Migration from Maven (Classic) Feeds

You can migrate artifacts from a Maven (Classic) to a Maven (New) feed with these steps:

1. Locate the storage path of your Maven (Classic) feed; this can be found on the Storage & Retention tab and will look something like `c:\ProgramData\ProGet\PackageStore\.maven2\F13`
2. Create a Maven (New) feed, called something like `mymaven-new`
3. Add Artifacts to the feed using the Bulk Import option and specify the storage path
4. Delete or rename the Maven (Classic) feed to `mymaven-old`
5. Rename the Maven (New) feed to `mymaven`

Note that, because this is a new feed, you will need to upgrade any permissions and/or API Keys that reference this feed.

In a future version of ProGet, we will support an "in-place Migration" that will populate the  metadata indexes based from files on disk, and then switch the feed type from Maven (Classic) to Maven (New).

## Technical Limitations

Maven works differently than other feed types in that Maven artifacts are not self-contained archives; instead, an artifact is more like a grouping of files with some associated metadata. The Maven "API" is essentially just file requests.

### Connectors & Local Indexing

Many public Maven repositories do not support search or indexing. Some (including Maven Central) have a large Lucene-based database that can be downloaded and contains all of the repository's artifacts.

ProGet will attempt to routinely download this index from the connectors, but this can be a very resource-intensive process. If you do not need this search feature, we recommend disabling this task in ProGet. Artifacts accessed directly by name do *not* need this index.

This indexing is performed on a schedule. To manually trigger the index task, navigate to "Administration Overview" > "Scheduled Jobs" and select `FullMavenConnectorIndex`. If this connector index is not available, go to "Administration Overview" > "Service" and trigger the `Scheduled Job Dispatcher.` This will reconfigure any missing scheduled jobs for the connector index.
