1. Overview

Apache Maven lets us define a repository or a central place where we store and retrieve project artifacts. Sometimes, we need to define multiple repositories, especially when our project depends on libraries available only in specific repositories.

In this tutorial, we’ll explore two primary ways to do this in Maven: through the settings.xml file and the pom.xml file.

2. Uploading Our Own Third-Party JAR to a Private Repository

To demonstrate these approaches, we’ll first deploy our simple GreeterServiceExample to a private remote repository:

public class GreeterServiceExample {
    public Greeting greetInYourLanguage(String language) {
        return switch (language.toLowerCase()) {
            case "english" -> new Greeting("Hello", new Language("English", "en"));
            case "spanish" -> new Greeting("Hola", new Language("Spanish", "es"));
            case "xhosa" -> new Greeting("Molo", new Language("Xhosa", "xh"));
            default -> null;
        };
    }
}

The example service returns a language-specific Greeting based on the selected language.

Before we can deploy our artifact, we need to specify our repository details in either the POM or settings.xml file:

<repositories> 
    <repository>
        <id>internal-maven-repo</id>
        <name>Internal Repository</name>
        <url>https://host/internal-maven-packages</url> 
    </repository>
    <!-- Other repositories -->
</repositories>

Next, let’s update our settings.xml by adding a server directive specifying authentication information for our internal repository:

<server>
    <id>internal-maven-repo</id>
    <username>username</username>
    <password>passphrase_or_token</password>
</server>

In addition to the authentication credentials, we’ve also specified a unique ID that our repository configuration references.

Now, let’s publish our example library to our internal repository:

mvn deploy:deploy-file \
    -DgroupId=com.baeldung \
    -DartifactId=maven-multiple-repositories \
    -Dversion=0.0.1 \
    -Dpackaging=jar \
    -Dfile=./target/GreeterExampleService.jar \
    -DrepositoryId=internal-maven-repo \
    -Durl=<url-of-the-repository-to-deploy>

In our deploy:deploy-file goal, we specify the repositoryId defined in our settings.xml file, as well as the file to be deployed and the repository URL, which are required by the deploy:deploy-file goal.

If we need the artifact to be present in other repositories, we’d need to repeat the Maven deploy process for each repository.

Now that our custom library is deployed, let’s explore how this dependency can be used in other projects.

3. Set up the Repository With the settings.xml File

Maven profiles help us customize our build configuration. Let’s add a profile definition to our settings.xml file:

<profile>
    <id>local-dev</id>
    <repositories>
        <repository>
            <id>internal-maven-repo</id>
            <name>Internal Repository</name>
            <url>https://host/internal-maven-packages</url>
        </repository>
        <repository>
            <id>central</id>
            <name>Central Repository</name>
            <url>https://repo.maven.apache.org/maven2</url>
        </repository>
    </repositories>
</profile>

In our internal repository definition, we’ve ensured that the repository ID matches the one specified in the server directive. Although the central repository configuration is inherited from the Super POM, we’ve included it here for demonstration purposes.

Next, let’s add the newly defined profile to the list of active profiles in our settings.xml file:

<activeProfiles>
    <activeProfile>local-dev</activeProfile>
</activeProfiles>

Including the profile in this list activates it for all builds.

Let’s specify a dependency for the library we uploaded:

<dependency>
    <groupId>com.baeldung</groupId>
    <artifactId>maven-multiple-repositories</artifactId>
    <version>0.0.1</version>
</dependency>

Next, let’s run a Maven install goal so that Maven will download our dependencies:

mvn install

Our build succeeds because all dependencies were sourced correctly from their respective repositories. Let’s utilize the imported library in our unit test:

@Test
public void whenGreetingInEnglish_thenAnENCodeShouldBeMadeAvailable() {
    GreeterServiceExample greeterService = new GreeterServiceExample();
    Greeting englishGreeting = greeterService.greetInYourLanguage("English");
    assertEquals("en", englishGreeting.getLanguage().getCode());
}

Configuring repository information in our settings.xml is suitable for local development; however, it can become cumbersome with multiple build environments. Let’s explore another option.

4. Configuring the Repository via pom.xml File

The POM file allows us to specify which repositories to use and to choose whether to define our repository details inside or outside of build profiles. It’s not necessary to define our repositories inside a Maven build profile.

Let’s define our repositories outside of the build profile in our POM file:

<repositories>
    <repository>
        <id>internal-maven-repo</id>
        <name>Internal Repository</name>
        <url>https://host/internal-maven-packages</url>
    </repository>
    <!-- Other repositories -->
</repositories>

Since our internal repository requires authentication, it’s best to leave those credentials in the server directive of our settings.xml file to avoid distributing them with the source code. Once again, we ensure that the repository ID matches the one specified in the server directive of our settings.xml file.

Let’s run a build:

mvn clean install

Since we defined our repositories outside of a build profile, we didn’t include it in the Maven install goal.

5. Conclusion

In this tutorial, we explored two approaches for specifying multiple repositories in Maven: using the settings.xml file and using the pom.xml file. Although both approaches lead to the same outcome, we saw how configuring the repository details in the pom.xml file lends itself better to portability. However, it is preferred that repository authentication details not be included in the pom.xml file due to security considerations, such as distributing sensitive information.

As always, the source code for all the examples can be found over on GitHub.