Red Hat Training

A Red Hat training course is available for Red Hat Fuse

4.5. Generating a Custom Offline Repository

Use case for a custom offline repository

When you move from the development phase of a project to the deployment phase, it is typically more convenient to pre-install all of the artifacts required by your application, rather than downloading them from the Internet on demand. In this case, the ideal solution is to create a custom offline repository, which contains the artifacts needed for your deployment. Creating a custom offline repository by hand, however, would be difficult, because it would need to include all of the transitive dependencies associated with your application bundles and features.
The ideal way to create a custom offline repository is to generate it, with the help of the Apache Karaf features-maven-plugin plug-in.

features-maven-plugin Maven plug-in

The features-maven-plugin plug-in from Apache Karaf is a utility that is used internally by the Apache Karaf developer community and the Red Hat JBoss Fuse development team to create distributions of the Apache Karaf OSGi container. Some of the goals of this plug-in are also useful for application developers, however, and this section explains how you can use the add-features-to-repo goal to generate your own custom offline repository.
Important
At present, only the add-features-to-repo goal of the features-maven-plugin plug-in is supported.

Steps to generate a custom repository

To generate and install a custom offline repository for specific Apache Karaf features, perform the following steps:

Create a POM file

In a convenient location—for example, ProjectDir—create a new directory, ProjectDir/custom-repo to hold the Maven project. Using a text editor, create the project's POM file, pom.xml, in the custom-repo directory and add the following contents to the file:
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">

    <modelVersion>4.0.0</modelVersion>

    <groupId>org.acme.offline-repo</groupId>
    <artifactId>custom-repo</artifactId>
    <version>1.0.0</version>
    <name>Generate offline features repository</name>
    
</project>
This is the bare bones of a Maven POM, which will be added to in the following steps. There is no need to specify a Maven package type here (it defaults to jar), because no package will be generated for this project.

Add the features-maven-plugin

Continue editing the pom.xml and add the features-maven-plugin as shown (where the build element is inserted as a child of the project element):
<project ...>
    ...
    <build>
        <plugins>
          <plugin>
            <groupId>org.apache.karaf.tooling</groupId>
            <artifactId>features-maven-plugin</artifactId>
            <version>2.2.1</version>

            <executions>
              <execution>
                <id>add-features-to-repo</id>
                <phase>generate-resources</phase>
                <goals>
                  <goal>add-features-to-repo</goal>
                </goals>
                <configuration>
                  <descriptors>
 <!-- List the URLs of required feature repositories here -->
                  </descriptors>
                  <features>
 <!-- List features you want in the offline repo here -->
                  </features>
                  <repository>target/features-repo</repository>
                </configuration>
              </execution>
            </executions>
          </plugin>
        </plugins>
    </build>

</project>
Subsequent steps will explain how to specify the descriptor list (of features repositories) and the features list.

Specify the features to download

In this example scenario, it is assumed that you want to make the camel-jms feature and the camel-quartz feature available in offline mode. List all of the features you want to download and store in the offline repository in the features element, which is a child of the configuration element of the features-maven-plugin.
To make the camel-jms and camel-quartz features available offline, add the following features element as a child of the feature-maven-plugin's configuration element:
<features>
  <feature>camel-jms</feature>
  <feature>camel-quartz</feature>
</features>

Specify the feature repositories

A feature repository is a location that stores feature descriptor files. Generally, because features can depend recursively on other features and because of the complexity of the dependency chains, the project normally requires access to all of the standard Red Hat JBoss Fuse feature repositories.
To see the full list of standard feature repositories used by your installation of JBoss Fuse, open the etc/org.apache.karaf.features.cfg configuration file and look at the featuresRepository setting, which is a comma-separated list of feature repositories, like the following:
...
#
# Comma separated list of feature repositories to register by default
#
featuresRepositories=mvn:org.apache.karaf/apache-karaf/2.1.3-fuse-00-00/xml/features,
mvn:org.apache.servicemix.nmr/apache-servicemix-nmr/1.4.0-fuse-00-00/xml/features,mvn
:org.apache.servicemix/apache-servicemix/4.3.1-fuse-00-00/xml/features,mvn:org.apache
.camel.karaf/apache-camel/2.6.0-fuse-00-00/xml/features,mvn:org.apache.servicemix/ode
-jbi-karaf/1.3.4/xml/features,mvn:org.apache.activemq/activemq-karaf/5.4.2-fuse-01-00
/xml/features
...
Now, add the listed feature repositories to the configuration of the features-maven-plugin in your POM file. Open the project's pom.xml file and add a descriptor element (as a child of the descriptors element) for each of the standard feature repositories. For example, given the preceding value of the featuresRepositories list, you would define the features-maven-plugin descriptors list in pom.xml as follows:
<descriptors>
  <!-- List taken from featuresRepositories in etc/org.apache.karaf.features.cfg -->
  <descriptor>mvn:org.apache.karaf/apache-karaf/2.1.3-fuse-00-00/xml/features</descriptor>
  <descriptor>mvn:org.apache.servicemix.nmr/apache-servicemix-nmr/1.4.0-fuse-00-00/xml/features</descriptor>
  <descriptor>mvn:org.apache.servicemix/apache-servicemix/4.3.1-fuse-00-00/xml/features</descriptor>
  <descriptor>mvn:org.apache.camel.karaf/apache-camel/2.6.0-fuse-00-00/xml/features</descriptor>
  <descriptor>mvn:org.apache.servicemix/ode-jbi-karaf/1.3.4/xml/features</descriptor>
  <descriptor>mvn:org.apache.activemq/activemq-karaf/5.4.2-fuse-01-00/xml/features</descriptor>
</descriptors>

Specify the Red Hat JBoss Fuse system repository

Add the Red Hat JBoss Fuse system repository, EsbInstallDir/system, to the list of repositories in the pom.xml file. This is necessary for two reasons: first of all, it saves you from downloading Maven artificats that are already locally available from your JBoss Fuse installation; and secondly, some of the artifacts in the system repository might not be available from any of the other repositories.
Using a text editor, open pom.xml and add the following repositories element as a child of the project element, customizing the file URL to point at your local system repository:
<project ...>
    ...
    <repositories>
      <repository>
        <id>esb.system.repo</id>
        <name>Red Hat JBoss Fuse internal system repo</name>
        <url>file:///E:/Programs/FUSE/apache-servicemix-6.2.0.redhat-133/system</url>
        <snapshots>
          <enabled>false</enabled>
        </snapshots>
        <releases>
          <enabled>true</enabled>
        </releases>
      </repository>
    </repositories>
    ...
</project>

Specify the remote repositories

Generally, the project requires access to all of the standard JBoss Fuse remote repositories. To see the full list of standard remote repositories, open the etc/org.ops4j.pax.url.mvn.cfg configuration file and look at the org.ops4j.pax.url.mvn.repositories setting, which is a comma-separated list of URLs like the following:
org.ops4j.pax.url.mvn.repositories= \
    http://repo1.maven.org/maven2, \
    http://repo.fusesource.com/maven2, \
    http://repo.fusesource.com/maven2-snapshot@snapshots@noreleases, \
    http://repo.fusesource.com/nexus/content/repositories/releases, \
    http://repo.fusesource.com/nexus/content/repositories/snapshots@snapshots@noreleases, \
    http://repository.apache.org/content/groups/snapshots-group@snapshots@noreleases, \
    http://repository.ops4j.org/maven2, \
    http://svn.apache.org/repos/asf/servicemix/m2-repo, \
    http://repository.springsource.com/maven/bundles/release, \
    http://repository.springsource.com/maven/bundles/external
Each entry in this list must be converted into a repository element, which is then inserted as a child element of the respositories element in the project's pom.xml file. The preceding repository URLs have slightly different formats and must be converted as follows:
RepoURL
The value of the repository URL, RepoURL, is inserted directly into the url child element of the repository element. For example, the http://repo1.maven.org/maven2 repository URL translates to the following repository element:
<repository>
  <!-- 'id' can be whatever you like -->
  <id>repo1.maven.org</id>
  <!-- 'name' can be whatever you like -->
  <name>Maven central</name>
  <url>http://repo1.maven.org/maven2</url>
  <snapshots>
    <enabled>false</enabled>
  </snapshots>
  <releases>
    <enabled>true</enabled>
  </releases>
</repository>
RepoURL@snapshots
The @snapshots suffix indicates that downloading snapshots should be enabled for this repository. When specifying the value of the url element, remove the @snapshots suffix from the URL. Change the snapshots/enabled flag to true, as shown in the following example:
<repository>
  <id>IdOfRepo</id>
  <name>LongNameOfRepo</name>
  <url>RepoURL</url>
  <snapshots>
    <enabled>true</enabled>
  </snapshots>
  <releases>
    <enabled>true</enabled>
  </releases>
</repository>
RepoURL@snapshots@noreleases
The combination of the @snapshots suffix and the @noreleases suffix indicates that downloading snapshots should be enabled and downloading releases should be disabled for this repository. When specifying the value of the url element, remove both suffixes from the URL. Change the snapshots/enabled flag to true and change the releases/enabled flag to false, as shown in the following example:
<repository>
  <id>IdOfRepo</id>
  <name>LongNameOfRepo</name>
  <url>RepoURL</url>
  <snapshots>
    <enabled>true</enabled>
  </snapshots>
  <releases>
    <enabled>false</enabled>
  </releases>
</repository>

Generate the offline repository

To generate the custom offline repository, open a new command prompt, change directory to ProjectDir/custom-repo, and enter the following Maven command:
mvn generate-resources
Assuming that the Maven build completes successfully, the custom offline repository should now be available in the following location:
ProjectDir/custom-repo/target/features-repo

Install the offline repository

To install the custom offline repository in the JBoss Fuse container, edit the etc/org.ops4j.pax.url.mvn.cfg file and append the offline repository directory to the list of default repositories, as follows:
org.ops4j.pax.url.mvn.defaultRepositories=file:${karaf.home}/${karaf.default.repository}@snapshots,file:ProjectDir/custom-repo/target/features-repo@snapshots
The @snapshots suffix can be added to the offline repository URL, if there is a possibility that some of the artifacts in it are snapshot versions.