Red Hat Training

A Red Hat training course is available for Red Hat Fuse

4.3. Locating Maven Artifacts at Run Time

Abstract

At run time, the process of locating Maven artifacts is implemented by the Eclipse Aether library, which is bundled with the Karaf container (so that it is not necessary for Apache Maven to be installed on the container host). It is possible to customize the Karaf container's Maven configuration by editing the etc/org.ops4j.pax.url.mvn.cfg file. For example, you can customize the list of remote Maven repositories and you can configure a HTTP proxy, if required.

4.3.1. Maven URL Handler Architecture

Overview

You can specify the location of an OSGi bundle using a Maven URL—for example, as the argument to the osgi:install command. When resolution of a Maven URL is triggered, JBoss Fuse uses a combination of the Pax URL Aether component and the Eclipse Aether component to implement artifact resolution. The basic strategy is to search the system/ directory, then search the local Maven repository, and then search the configured remote Maven repositories.

Maven URL protocol

The Maven URL protocol specifies the location of a Maven artifact, which can be retrieved either from local or remote Maven repositories. For example, an artifact with the Maven coordinates, GroupId:ArtifactId:Version, can be referenced by the following Maven URL:
mvn:GroupId/ArtifactId/Version
In a standalone (non-Fabric) container, a Maven URL lookup can be triggered by either of the following events:
  • When osgi:install is invoked on a Maven URL to install an OSGi bundle;
  • When features:install is invoked to install a Karaf feature (a Karaf feature typically includes one or more Maven URL references).

Pax URL Aether layer

In Apache Karaf, the framework for resolving Maven URLs is the URL protocol handler mechanism, which is a standard feature of the Java language and JVM. To handle URLs prefixed by the mvn: scheme, Karaf registers the OPS4J Pax URL Aether protocol handler. The Pax URL Aether layer is thus responsible for resolving all mvn URLs in the JVM. This layer can be configured through one or both of the following configuration files:
InstallDir/etc/org.ops4j.pax.url.mvn.cfg
Stores the OSGi Config Admin properties used to configure the Pax URL Aether layer. In particular, it is possible to specify the locations of local and remote Maven repositories through the settings in this file. For details of the available settings, see Section 4.3.5, “Pax URL Aether Reference”.
UserHome/.m2/settings.xml
(Optional) You can optionally configure the Pax URL Aether layer to read its configuration from a standard Maven settings.xml file (by configuring the relevant settings in org.ops4j.pax.url.mvn.cfg).
The main purpose of the Pax URL Aether layer is to facilitate configuration. The Pax URL Aether layer does not actually implement resolution of Maven artifacts. That responsibility is delegated to the Eclipse Aether layer instead.
Note
In some old org.ops4j.pax.url.mvn.cfg configuration files, you might see the setting disableAether=false. This setting is obsolete, however, and has no effect on the pax-url-aether component. The current implementation of Pax URL Aether (previously called Pax URL Maven) is completely dependent on Eclipse Aether.

Eclipse Aether layer

The Eclipse Aether layer is fundamental to Maven artifact resolution in Apache Karaf. Ultimately, resolution of Maven artifacts for the Karaf container is always performed by the Aether layer. Note that the Aether layer itself is stateless: the parameters required to perform resolution of a Maven artifact are passed to the Aether layer with every invocation.

Locating artifacts at run time

Figure 4.2, “How the Container Locates Artifacts at Run Time” shows the mechanism for handling a Maven URL and resolving a Maven artifact at run time.

Figure 4.2. How the Container Locates Artifacts at Run Time

How the Container Locates Artifacts at Run Time
The steps followed to locate the required Maven artifacts are:
  1. Resolution of a Maven artifact is triggered when a user invokes the osgi:install command on a Maven URL (or if a user invokes the features:install command on a feature that references some Maven URLs).
  2. To resolve the Maven URL, the JVM calls back on the protocol handler registered against the mvn scheme, which happens to be the Pax URL Aether component.
  3. The Pax URL Aether component reads its configuration from the InstallDir/etc/org.ops4j.pax.url.mvn.cfg file (and possibly also from a Maven settings.xml file, if so configured). The Pax URL Aether layer parses the requested Maven URL and combines this information with the specified configuration in order to invoke the Eclipse Aether library.
  4. When the Aether library is invoked, the first step is to look up any local Maven repositories to try and find the Maven artifact. The following local repositories are configured by default:
    InstallDir/system
    The JBoss Fuse system directory, which contains all of the Maven artifacts that are bundled with the JBoss Fuse distribution.
    UserHome/.m2/repository
    The user's own local Maven repository in the user's home directory, UserHome.
    If you like, you can customize the list of local repositories to add your own custom Maven repository.
    If the Maven artifact is found locally, skip straight to step 7.
  5. If the Maven artifact cannot be found in one of the local repositories, Aether tries to look up the specified remote repositories (using the list of remote repositories specified in the Pax URL Aether configuration). Because the remote repositories are typically located on the Internet (accessed through the HTTP protocol), it is necessary to have Internet access for this step to succeed.
    Note
    If your local network requires you to use a HTTP proxy to access the Internet, it is possible to configure Pax URL Aether to use a HTTP proxy. For example, see the section called “Configuring a HTTP proxy for Maven URLs” for details.
  6. If the Maven artifact is found in a remote repository, Aether automatically installs the artifact into the user's local Maven repository, so that another remote lookup will not be required.
  7. Finally, assuming that the Maven artifact has been successfully resolved, Karaf installs the artifact in the Karaf bundle cache, InstallDir/data/cache, and loads the artifact (usually, an OSGi bundle) into the container runtime. At this point, the artifact is effectively installed in the container.

4.3.2. Redeploying Maven Artifacts in a Development Environment

Overview

An important aspect of the Karaf container architecture is that deployed Maven artifacts are stored in the container cache, which is separate from the local Maven repository. Bundles and features get copied from the local Maven repository into the cache at the time they are first deployed. After that, any changes to the artifact in the local Maven repository are ignored.

Immutable artifacts

Usually, it makes sense to ignore changes in the local Maven repository, because Maven requires each specific version of an artifact to be immutable: that is, once you make a particular version of a Maven artifact available in a Maven repository, it must never change. Hence, it should never be necessary to go back and check the Maven repository for changes to the artifact.

SNAPSHOT artifacts

On the other hand, there is a partial exception to this convention: in a development environment, the same artifacts are constantly being rebuilt and retested, which requires them to be redeployed into the Karaf container. The correct way to deal with this is to attach the suffix -SNAPSHOT to the Maven version specifier. Maven treats these artifacts differently: for example, by periodically checking remote Maven repositories for updates and downloading the changed artifacts to the local repository.

Explicitly redeploying

When working with SNAPSHOT artifacts, you will also need to redeploy the changed artifacts to the Karaf container. One approach is explicit redeployment.
For example, say you have already deployed the org.example/myfoobundle/1.0.0-SNAPSHOT Maven artifact into the Karaf container and this bundle has the bundle ID, 751. If you now rebuild this bundle (for example, by executing mvn install in the bundle's Maven project), you can redeploy the changed bundle with the following console commands:
osgi:uninstall 751
osgi:install mvn:org.example/myfoobundle/1.0.0-SNAPSHOT

dev:watch command

Typically, a more convenient approach to redeploying SNAPSHOT artifacts is to enable automatic redeployment, using the dev:watch command. For example, given a particular bundle—with bundle ID, 751—you can enable automatic redeployment by entering the command:
dev:watch 751
Now, whenever you rebuild and install the Maven artifact into your local Maven repository (for example, by executing mvn install in your Maven project), the Karaf container automatically re-installs the changed Maven artifact. For more details, see section "dev:watch, watch" in "Console Reference".
Important
Using the dev:watch command is intended for a development environment only. It is not recommended for use in a production environment.

4.3.3. Configuring Pax URL Aether Directly

Overview

The default approach to configuring the Pax URL Aether component is to edit the property settings in the InstallDir/etc/org.ops4j.pax.url.mvn.cfg file directly. This approach is particularly convenient for a production environment, because the Maven configuration is colocated with the rest of the container configuration.
Note
In order to use the direct configuration approach, you must at least set the org.ops4j.pax.url.mvn.repositories property. If this property is not set, Pax URL Aether falls back to reading configuration from the Maven settings.xml file.

Adding a remote Maven repository

To add a remote Maven repository to the Pax URL Aether configuration, open the InstallDir/etc/org.ops4j.pax.url.mvn.cfg configuration file in a text editor and edit the org.ops4j.pax.url.mvn.repositories property setting. The default is as follows:
org.ops4j.pax.url.mvn.repositories= \
    http://repo1.maven.org/maven2@id=maven.central.repo, \
    https://maven.repository.redhat.com/ga@id=redhat.ga.repo, \
    https://maven.repository.redhat.com/earlyaccess/all@id=redhat.ea.repo, \
    https://repository.jboss.org/nexus/content/groups/ea@id=fuseearlyaccess
Where the org.ops4j.pax.url.mvn.repositories property is defined as a comma-separated list of Maven repository URLs. The backslash character, \, functions as a (UNIX style) line continuation character and must be followed immediately by the newline character. The Pax URL Aether component supports special repository URL options, defined using the @Option=Value syntax—see the section called “Pax URL Aether repository URL syntax”.
Note
The @id option specifies the name of the repository and is required by the Aether layer.
Note
The presence of the org.ops4j.pax.url.mvn.repositories property setting has an important side effect: it signals that the Pax URL Aether component takes its configuration from the etc/org.ops4j.pax.url.mvn.cfg, not from a settings.xml file (even if the org.ops4j.pax.url.mvn.settings property has been set).

Adding a default Maven repository

The default repositories are a list of repositories that the container always checks first. To add a default Maven repository to the Pax URL Aether configuration, open the InstallDir/etc/org.ops4j.pax.url.mvn.cfg configuration file in a text editor and edit the org.ops4j.pax.url.mvn.defaultRepositories property setting. The default is as follows:
org.ops4j.pax.url.mvn.defaultRepositories=\
    file:${runtime.home}/${karaf.default.repository}@snapshots@id=karaf.${karaf.default.repository},\
    file:${runtime.home}/local-repo@snapshots@id=karaf.local-repo,\
    file:${karaf.base}/${karaf.default.repository}@snapshots@id=child.karaf.${karaf.default.repository}
Where the org.ops4j.pax.url.mvn.defaultRepositories property is defined as a comma-separated list of Maven repository URLs. The backslash character, \, functions as a (UNIX style) line continuation character and must be followed immediately by the newline character. Local repositories should be defined using a URL with the file: scheme. The Pax URL Aether component supports special repository URL options, defined using the @Option=Value syntax—see the section called “Pax URL Aether repository URL syntax”.
Note
It is recommended that you leave the container's system repository as the first entry in the list.

Customizing the location of the local Maven repository

The local Maven repository plays a special role, because it is the primary local cache of Maven artifacts: whenever Maven downloads an artifact from a remote repository, it installs the artifact into the local repository. The usual location of the local Maven repository is .m2/repository/ under the user's home directory. You can optionally customize the location by setting the org.ops4j.pax.url.mvn.localRepository property in the InstallDir/etc/org.ops4j.pax.url.mvn.cfg configuration file. For example:
org.ops4j.pax.url.mvn.localRepository= /home/jbloggs/path/to/local/repository
By default, this property is not set.

Configuring a HTTP proxy for Maven URLs

To configure a HTTP proxy (which will be used when connecting to remote Maven repositories), open the InstallDir/etc/system.properties file in a text editor and set the http.proxyHost and http.proxyPort system properties with the host and port of the proxy—for example:
http.proxyHost=192.0.2.0
http.proxyPort=8080
You can optionally specify a list of non-proxy hosts (hosts that can be reached without going through the proxy) using the http.nonProxyHosts property—for example:
http.nonProxyHosts=localhost|*.redhat.com|*.jboss.org
Note
An advantage of using the system properties approach to configuring the proxy is that these settings will be used both by the mvn URL protocol handler and by the http URL protocol handler (see Section 4.1, “Locating HTTP Artifacts”).

4.3.4. Configuring Pax URL Aether through settings.xml

Overview

You can optionally configure Pax URL Aether using a standard Maven settings.xml file. This approach is particularly convenient in a development environment, because it makes it possible to store your build time settings and your run time settings all in one place.

Enabling the settings.xml configuration approach

To configure Pax URL Aether to read its configuration from a Maven settings.xml file, you must remove or comment out the org.ops4j.pax.url.mvn.repositories setting in the InstallDir/etc/org.ops4j.pax.url.mvn.cfg file. For example, you can comment out the default repositories setting by inserting a hash, #, at the start of the line, as follows:
#org.ops4j.pax.url.mvn.repositories= \
    http://repo1.maven.org/maven2@id=maven.central.repo, \
    https://maven.repository.redhat.com/ga@id=redhat.ga.repo, \
    https://maven.repository.redhat.com/earlyaccess/all@id=redhat.ea.repo, \
    https://repository.jboss.org/nexus/content/groups/ea@id=fuseearlyaccess
When the repositories setting is absent, Pax URL Aether implicitly switches to the settings.xml configuration approach.

Location of the settings.xml file

By default, Pax URL Aether looks in the standard locations for the Maven settings.xml file (usually UserHome/.m2/settings.xml). If you like, you can specify the location explicitly using the org.ops4j.pax.url.mvn.settings property. For example:
org.ops4j.pax.url.mvn.settings= /home/fuse/settings.xml
For full details of the search order for settings.xml, see the description of org.ops4j.pax.url.mvn.settings in the section called “Pax URL Aether configuration reference”.

Adding a remote Maven repository

To add a new remote Maven repository to your settings.xml file, open the settings.xml file in a text editor and add a new repository XML element. For example, to create an entry for the JBoss Fuse public Maven repository, add a repository element as shown:
<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">
  ...
  <profiles>
    <profile>
      <id>my-fuse-profile</id>
      <activation>
        <activeByDefault>true</activeByDefault>
      </activation>
      <repositories>
        <!--
         | Add new remote Maven repositories here
          -->
        <repository>
            <id>redhat-ga-repository</id>
            <url>https://maven.repository.redhat.com/ga</url>
            <releases>
                <enabled>true</enabled>
            </releases>
            <snapshots>
                <enabled>false</enabled>
            </snapshots>
        </repository>
        ...
      </repositories>
  </profiles>
  ...
</settings>
The preceding example additionally specifies that release artifacts can be downloaded, but snapshot artifacts cannot be downloaded from the repository.

Customizing the location of the local Maven repository

To customize the location of your local Maven repository, open the settings.xml file in a text editor and add (or modify) the localRepository XML element. For example, to select the directory, /home/fuse/.m2/repository, as your local Maven repository:
<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">
  ...
<!-- localRepository
 | The path to the local repository Maven will use to store artifacts.
 |
 | Default: ~/.m2/repository -->
  <localRepository>/home/fuse/.m2/repository</localRepository>
  ...
</settings>
For a detailed explanation of the search order for the local Maven repository, see the section called “Local Maven repository search order”.

Configuring a HTTP proxy for Maven URLs

To configure a HTTP proxy (which will be used when connecting to remote Maven repositories), open the settings.xml file in a text editor and add a new proxy XML element as a child of the proxies XML element. The definition of the proxy follows the standard Maven syntax. For example, to create a proxy for the HTTP (insecure) protocol with host, 192.0.2.0, and port, 8080, add a proxy element as follows:
<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">
  ...
  <proxies>
    <proxy>
      <id>fuse-proxy-1</id>
      <active>true</active>
      <protocol>http</protocol>
      <host>192.0.2.0</host>
      <port>8080</port>
    </proxy>
  </proxies>
  ...
</settings>
You can also add a proxy for secure HTTPS connections by adding a proxy element configured with the https protocol.

Reference

For a detailed description of the syntax of the Maven settings.xml file, see the Maven Settings Reference. But please note that not all of the features documented there are necessarily supported by the Pax URL Aether component.

4.3.5. Pax URL Aether Reference

Overview

This section provides a configuration reference for the Pax URL Aether component, which is used to configure the runtime behaviour of Maven in the Karaf container.
Note
The prefix appearing in the property names, org.ops4j.pax.url.mvn.*, reflects the old name of this component, which was previously called Pax URL Mvn.

Local Maven repository search order

Pax URL Aether resolves the location of the local repository in the following order:
  1. The location specified by the org.ops4j.pax.url.mvn.localRepository property in the org.ops4j.pax.url.mvn.cfg file.
  2. Otherwise, the location specified by the localRepository element in the settings.xml file specified by the org.ops4j.pax.url.mvn.settings property in the org.ops4j.pax.url.mvn.cfg file.
  3. Otherwise, the location specified by the localRepository element in the .m2/settings.xml file located under the user's home directory.
  4. Otherwise, the location specified by the localRepository element in the M2_HOME/conf/settings.xml file.
  5. Otherwise, the default location is .m2/repository/ under the user's home directory.

Pax URL Aether Maven URL syntax

The protocol handler registered by Pax URL Aether supports the following Maven URL syntax:
mvn:[RepositoryUrl!]GroupId/ArtifactId[/Version[/Type]]
Where RepositoryUrl has the syntax specified by the section called “Pax URL Aether repository URL syntax”; and GroupId, ArtifactId, Version, Type are the standard Maven location coordinates.

Pax URL Aether repository URL syntax

You specify a repository location using a URL with a file:, http:, or https: scheme, optionally appending one or more of the following suffixes:
@snapshots
Allow snapshot versions to be read from the repository.
@noreleases
Do not allow release versions to be read from the repository.
@id=RepoName
(Required) Specifies the repository name. This setting is required by the Aether handler.
@multi
Marks the path as a parent directory of multiple repository directories. At run time the parent directory is scanned for subdirectories and each subdirectory is used as a remote repository.
@update=UpdatePolicy
Specifies the Maven updatePolicy, overriding the value of org.ops4j.pax.url.mvn.globalUpdatePolicy.
@releasesUpdate=UpdatePolicy
Specifies the Maven updatePolicy specifically for release artifacts (overriding the value of @update).
@snapshotsUpdate=UpdatePolicy
Specifies the Maven updatePolicy specifically for snapshot artifacts (overriding the value of @update).
@checksum=ChecksumPolicy
Specifies the Maven checksumPolicy, which specifies how to react if a downloaded Maven artifact has a missing or incorrect checksum. The policy value can be: ignore, fail, or warn.
@releasesChecksum=ChecksumPolicy
Specifies the Maven checksumPolicy specifically for release artifacts (overriding the value of @checksum).
@snapshotsChecksum=ChecksumPolicy
Specifies the Maven checksumPolicy specifically for snapshot artifacts (overriding the value of @checksum).
For example:
https://repo.example.org/maven/repository@id=example.repo

Pax URL Aether configuration reference

The Pax URL Aether component can be configured by editing the etc/org.ops4j.pax.url.mvn.cfg configuration file (uses OSGi Config Admin service). In pax-url-aether version 2.4.2, the following configuration properties are supported:
org.ops4j.pax.url.mvn.certificateCheck
If true, enable the SSL certificate check when connecting to a remote repository through the HTTPS protocol. If false, skip the SSL certificate check. Default is false.
org.ops4j.pax.url.mvn.defaultRepositories
Specifies a list of default (local) Maven repositories that are checked before looking up the remote repositories. Specified as a comma-separated list of file: repository URLs, where each repository URL has the syntax defined in the section called “Pax URL Aether repository URL syntax”.
org.ops4j.pax.url.mvn.globalUpdatePolicy
Specifies the Maven updatePolicy, which determines how often Aether attempts to update local Maven artifacts from remote repositories. Can take the following values:
  • always—always resolve the latest SNAPSHOT from remote Maven repositories.
  • never—never check for newer remote SNAPSHOTS.
  • daily—check on the first run of the day (local time).
  • interval:Mins—check every Mins minutes.
Default is daily.
org.ops4j.pax.url.mvn.localRepository
Specifies the location of the local Maven repository on the file system, overriding the default value (which is usually UserHome/.m2/repository).
org.ops4j.pax.url.mvn.proxies
Can be used to specify a HTTP proxy, a HTTPS proxy, and non-proxy host lists. The value consists of a semicolon, ;, separated list of entries. You can include the following entries (where each entry is optional):
  • http:host=Host,port=Port[,nonProxyHosts=NonProxyHosts]
  • https:host=Host,port=Port[,nonProxyHosts=NonProxyHosts]
The nonProxyHosts setting is optional and, if included, specifies a list of hosts that can be reached without going through the proxy. The list of non-proxy hosts has its entries separated by a pipe, |, symbol—for example, nonProxyHosts=localhost|example.org.
Here is a sample org.ops4j.pax.url.mvn.proxies setting:
org.ops4j.pax.url.mvn.proxies= http:host=gateway,port=8080;https:host=sslgateway,port=8453
org.ops4j.pax.url.mvn.proxySupport
If true, enable HTTP proxy support through property settings. When this setting is enabled, the HTTP proxy can be configured in either of the following ways:
  • Through the org.ops4j.pax.url.mvn.proxies property (takes precedence), or
  • Through the http.proxyHost, http.proxyPort, and http.nonProxyHosts Java system properties, set in the etc/system.properties file.
If false, the preceding property settings are ignored. Default is true.
Note
This setting has no effect on proxy support when a Maven settings.xml file is selected to configure Pax URL Aether.
org.ops4j.pax.url.mvn.repositories
Specifies a list of remote Maven repositories that can be searched for Maven artifacts. Specified as a comma-separated list of http: or https: repository URLs, where each repository URL has the syntax defined in the section called “Pax URL Aether repository URL syntax”.
Important
If the org.ops4j.pax.url.mvn.repositories property is not set, Pax URL Aether reads its Maven settings from the relevant Maven settings.xml file instead (usually, from UserHome/.m2/settings.xml by default). In other words, the absence of the org.ops4j.pax.url.mvn.repositories property implicitly enables the settings.xml configuration approach.
org.ops4j.pax.url.mvn.security
Specifies the path to a Maven settings-security.xml file. This can be used to enable server password encryption. Default is ${user.home}/.m2/settings-security.xml.
org.ops4j.pax.url.mvn.settings
Specifies a path on the file system to override the default location of the Maven settings.xml file. Pax URL Aether resolves the location of the Maven settings.xml file in the following order:
  1. The location specified by org.ops4j.pax.url.mvn.settings.
  2. ${user.home}/.m2/settings.xml
  3. ${maven.home}/conf/settings.xml
  4. M2_HOME/conf/settings.xml
Note
All settings.xml files are ignored, if the org.ops4j.pax.url.mvn.repositories property is set.
org.ops4j.pax.url.mvn.timeout
Specifies the timeout to use while downloading artifacts, in units of milliseconds. Default is 5000 (five seconds).