| // |
| // Licensed under the Apache License, Version 2.0 (the "License"); |
| // you may not use this file except in compliance with the License. |
| // You may obtain a copy of the License at |
| // |
| // http://www.apache.org/licenses/LICENSE-2.0 |
| // |
| // Unless required by applicable law or agreed to in writing, software |
| // distributed under the License is distributed on an "AS IS" BASIS, |
| // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| // See the License for the specific language governing permissions and |
| // limitations under the License. |
| // |
| |
| === Custom distributions |
| |
| As Karaf is an OSGi container, it's heavily used as as application and middleware kernel. |
| |
| You may wish to construct your own Karaf distribution preconfigured to your requirements. |
| |
| This custom distribution could contain: |
| |
| * branding to change the Karaf console look-and-feel |
| * configuration files (in the etc folder) altered to your requirements |
| * pre-packaged artifacts in the deploy folder |
| * a pre-populated system repository (containing your own bundle and features descriptor) |
| * renamed or specific scripts in the bin folder |
| * system documentation files |
| |
| ==== Maven assembly |
| |
| The recommended way to create a Karaf server assembly is to use the karaf-assembly packaging with the karaf-maven-plugin. |
| This assembles a server from the maven dependencies in the project pom. After explanation of the configuration options |
| we present an example. |
| |
| The Karaf project effectively uses this packaging to assemble the official Karaf distributions, but due to maven |
| limitations we have to simulate rather than use the karaf-assembly packaging. |
| |
| This packaging creates tar.gz and zip archives containing the assembled server. |
| They are identical except that zip archives don't unpack with appropriate unix file permissions for the scripts. |
| |
| ===== Maven dependencies |
| |
| Maven dependencies in a karaf-assembly project can be feature repositories (classifier "features") or kar archives. |
| Feature repositories are installed in the internal "system" Maven structured repository. |
| Kar archives have their content unpacked on top of the server as well as contained feature repositories installed. |
| |
| The Maven scope of a dependency determines whether its feature repository is listed in the features service |
| configuration file `etc/org.apache.karaf.features.cfg` `featuresRepositories` property: |
| |
| * compile (default): All the features in the repository (or for a kar repositories) will be installed into the |
| `startup.properties`. The feature repo is not listed in the features service configuration file. |
| * runtime: feature installation is controlled by `<startupFeature>`, `<bootFeature>`, and `<installedFeature>` elements |
| in the karaf-maven-plugin configuration. The feature repo uri is listed in the features service configuration file. |
| |
| ===== Plugin configuration |
| |
| Control how features are installed using these elements referring to features from installed feature repositories: |
| |
| * `<startupFeature>foo</startupFeature>` - This will result in the feature bundles being listed in startup.properties at |
| the appropriate start level and the bundles being copied into the "system" internal repository. |
| You can use feature_name or feature_name/feature_version formats. |
| * `<bootFeature>bar</bootFeature>` - This will result in the feature name added to boot-features in the features |
| service configuration file and all the bundles in the feature copied into the "system" internal repository. |
| You can use feature_name or feature_name/feature_version formats. |
| * `<installedFeature>baz</installedFeature>` - This will result in all the bundles in the feature being installed in |
| the "system" internal repository. Therefore at runtime the feature may be installed without access to external repositories. |
| You can use feature_name or feature_name/feature_version formats. |
| |
| You can also define the libraries shipped in your custom distribution. For instance, it could be interesting if you |
| want to extend your distribution with some JDBC drivers. |
| |
| The plugin accepts the `<libraries/>` element where you can add `<library/>` containing the URL of the library. |
| For instance: |
| |
| ---- |
| <libraries> |
| <library>mvn:org.postgresql/postgresql/9.3-1102-jdbc41;type:=endorsed</library> |
| </libraries> |
| ---- |
| |
| ===== Minimal Distribution Example |
| |
| This is the minimal assembly pom changed to use the packaging and annotated |
| |
| ---- |
| <?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> |
| |
| <parent> |
| ... |
| </parent> |
| |
| <groupId>org.apache.karaf</groupId> |
| <artifactId>apache-karaf-minimal</artifactId> |
| <version>${project.version}</version> |
| <packaging>karaf-assembly</packaging> |
| <name>Apache Karaf :: Assemblies :: Minimal Distribution</name> |
| |
| <dependencies> |
| <dependency> |
| <!-- scope is compile so all features (there is only one) are installed into startup.properties and the feature repo itself is not added in etc/org.apache.karaf.features.cfg file --> |
| <groupId>org.apache.karaf.features</groupId> |
| <artifactId>framework</artifactId> |
| <version>${project.version}</version> |
| <type>kar</type> |
| </dependency> |
| <dependency> |
| <!-- scope is runtime so the feature repo is listed in etc/org.apache.karaf.features.cfg file, and features will installed into the system directory --> |
| <groupId>org.apache.karaf.features</groupId> |
| <artifactId>standard</artifactId> |
| <classifier>features</classifier> |
| <type>xml</type> |
| <scope>runtime</scope> |
| </dependency> |
| </dependencies> |
| |
| <build> |
| <!-- if you want to include resources in the distribution --> |
| <resources> |
| <resource> |
| <directory>src/main/resources</directory> |
| <filtering>false</filtering> |
| <includes> |
| <include>**/*</include> |
| </includes> |
| </resource> |
| <resource> |
| <directory>src/main/filtered-resources</directory> |
| <filtering>true</filtering> |
| <includes> |
| <include>**/*</include> |
| </includes> |
| </resource> |
| </resources> |
| |
| <plugins> |
| <!-- if you want to include resources in the distribution --> |
| <plugin> |
| <groupId>org.apache.maven.plugins</groupId> |
| <artifactId>maven-resources-plugin</artifactId> |
| <version>2.6</version> |
| <executions> |
| <execution> |
| <id>process-resources</id> |
| <goals> |
| <goal>resources</goal> |
| </goals> |
| </execution> |
| </executions> |
| </plugin> |
| <!-- karaf-maven-plugin will call both assembly and archive goals --> |
| <plugin> |
| <groupId>org.apache.karaf.tooling</groupId> |
| <artifactId>karaf-maven-plugin</artifactId> |
| <extensions>true</extensions> |
| <configuration> |
| <!-- no startupFeatures --> |
| <bootFeatures> |
| <feature>standard</feature> |
| </bootFeatures> |
| <!-- no installedFeatures --> |
| </configuration> |
| </plugin> |
| </plugins> |
| </build> |
| </project> |
| ---- |
| |
| ===== Custom Distribution Example |
| |
| It's possible to specify feature versions using the name/version format. |
| |
| For instance, to pre-install Spring 4.0.7.RELEASE_1 feature in your custom distribution, you can use the following pom.xml: |
| |
| ---- |
| <?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>my.custom</groupId> |
| <artifactId>my.distribution</artifactId> |
| <version>1.0</version> |
| <packaging>karaf-assembly</packaging> |
| |
| <dependencies> |
| <dependency> |
| <!-- scope is compile so all features (there is only one) are installed into startup.properties and the feature repo itself is not added in etc/org.apache.karaf.features.cfg file --> |
| <groupId>org.apache.karaf.features</groupId> |
| <artifactId>framework</artifactId> |
| <version>4.0.0</version> |
| <type>kar</type> |
| </dependency> |
| <dependency> |
| <!-- scope is runtime so the feature repo is listed in etc/org.apache.karaf.features.cfg file, and features will installed into the system directory if specify in the plugin configuration --> |
| <groupId>org.apache.karaf.features</groupId> |
| <artifactId>standard</artifactId> |
| <classifier>features</classifier> |
| <type>xml</type> |
| <scope>runtime</scope> |
| </dependency> |
| <dependency> |
| <!-- scope is runtime so the feature repo is listed in etc/org.apache.karaf.features.cfg file, and features will installed into the system directory if specify in the plugin configuration --> |
| <groupId>org.apache.karaf.features</groupId> |
| <artifactId>spring</artifactId> |
| <classifier>features</classifier> |
| <type>xml</type> |
| <scope>runtime</scope> |
| </dependency> |
| </dependencies> |
| |
| <build> |
| <!-- if you want to include resources in the distribution --> |
| <resources> |
| <resource> |
| <directory>src/main/resources</directory> |
| <filtering>false</filtering> |
| <includes> |
| <include>**/*</include> |
| </includes> |
| </resource> |
| <resource> |
| <directory>src/main/filtered-resources</directory> |
| <filtering>true</filtering> |
| <includes> |
| <include>**/*</include> |
| </includes> |
| </resource> |
| </resources> |
| |
| <plugins> |
| <!-- if you want to include resources in the distribution --> |
| <plugin> |
| <groupId>org.apache.maven.plugins</groupId> |
| <artifactId>maven-resources-plugin</artifactId> |
| <version>2.6</version> |
| <executions> |
| <execution> |
| <id>process-resources</id> |
| <goals> |
| <goal>resources</goal> |
| </goals> |
| </execution> |
| </executions> |
| </plugin> |
| <plugin> |
| <groupId>org.apache.karaf.tooling</groupId> |
| <artifactId>karaf-maven-plugin</artifactId> |
| <version>4.0.0</version> |
| <extensions>true</extensions> |
| <configuration> |
| <!-- no startupFeatures --> |
| <bootFeatures> |
| <feature>minimal</feature> |
| </bootFeatures> |
| <installedFeatures> |
| <feature>wrapper</feature> |
| <feature>spring/4.0.7.RELEASE_1</feature> |
| </installedFeatures> |
| </configuration> |
| </plugin> |
| </plugins> |
| </build> |
| </project> |
| ---- |
| |
| ==== (deprecated old style) Maven assembly |
| |
| Basically a Karaf custom distribution involves: |
| |
| . Uncompressing a standard Karaf distribution in a given directory. |
| . Populating the system repo with your features. |
| . Populating the lib directory with your branding or other system bundle jar files. |
| . Overriding the configuration files in the etc folder. |
| |
| These tasks could be performed using scripting, or more easily and portable, using Apache Maven and a set of Maven plugins. |
| |
| For instance, the Maven POM could look like: |
| |
| ---- |
| <?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 http://maven.apache.org/xsd/maven-4.0.0.xsd"> |
| |
| <groupId>my.company</groupId> |
| <artifactId>mycustom-karaf</artifactId> |
| <version>1.0</version> |
| <packaging>pom</packaging> |
| <name>My Unix Custom Karaf Distribution</name> |
| |
| <properties> |
| <karaf.version>${project.version}</karaf.version> |
| </properties> |
| |
| <dependencies> |
| <dependency> |
| <groupId>org.apache.karaf</groupId> |
| <artifactId>apache-karaf</artifactId> |
| <version>${karaf.version}</version> |
| <type>tar.gz</type> |
| </dependency> |
| <dependency> |
| <groupId>org.apache.karaf</groupId> |
| <artifactId>apache-karaf</artifactId> |
| <version>${karaf.version}</version> |
| <type>xml</type> |
| <classifier>features</classifier> |
| </dependency> |
| </dependencies> |
| |
| <build> |
| <resources> |
| <resource> |
| <directory>${project.basedir}/src/main/filtered-resources</directory> |
| <filtering>true</filtering> |
| <includes> |
| <include>**/*</include> |
| </includes> |
| </resource> |
| </resources> |
| <plugins> |
| <plugin> |
| <groupId>org.apache.maven.plugins</groupId> |
| <artifactId>maven-resources-plugin</artifactId> |
| <executions> |
| <execution> |
| <id>filter</id> |
| <phase>generate-resources</phase> |
| <goals> |
| <goal>resources</goal> |
| </goals> |
| </execution> |
| </executions> |
| </plugin> |
| <plugin> |
| <groupId>org.apache.karaf.tooling</groupId> |
| <artifactId>karaf-maven-plugin</artifactId> |
| <version>${karaf.version}</version> |
| <executions> |
| <execution> |
| <id>add-features-to-repo</id> |
| <phase>generate-resources</phase> |
| <goals> |
| <goal>features-add-to-repo</goal> |
| </goals> |
| <configuration> |
| <descriptors> |
| <descriptor>mvn:org.apache.karaf/apache-karaf/${karaf.version}/xml/features</descriptor> |
| <descriptor>file:${project.basedir}/target/classes/my-features.xml</descriptor> |
| </descriptors> |
| <features> |
| <feature>my-feature</feature> |
| </features> |
| </configuration> |
| </execution> |
| </executions> |
| </plugin> |
| <plugin> |
| <groupId>org.apache.maven.plugins</groupId> |
| <artifactId>maven-dependency-plugin</artifactId> |
| <executions> |
| <execution> |
| <id>copy</id> |
| <phase>generate-resources</phase> |
| <goals> |
| <goal>copy</goal> |
| </goals> |
| <configuration> |
| <!-- Define here the artifacts which should be considered in the assembly --> |
| <!-- For instance, the branding jar --> |
| <artifactItems> |
| <artifactItem> |
| <groupId>my.groupId</groupId> |
| <artifactId>my.branding.id</artifactId> |
| <version>1.0</version> |
| <outputDirectory>target/dependencies</outputDirectory> |
| <destFileName>mybranding.jar</destFileName> |
| </artifactItem> |
| </artifactItems> |
| </configuration> |
| </execution> |
| <execution> |
| <!-- Uncompress the standard Karaf distribution --> |
| <id>unpack</id> |
| <phase>generate-resources</phase> |
| <goals> |
| <goal>unpack</goal> |
| </goals> |
| <configuration> |
| <artifactItems> |
| <artifactItem> |
| <groupId>org.apache.karaf</groupId> |
| <artifactId>apache-karaf</artifactId> |
| <type>tar.gz</type> |
| <outputDirectory>target/dependencies</outputDirectory> |
| </artifactItem> |
| </artifactItems> |
| </configuration> |
| </execution> |
| </executions> |
| </plugin> |
| <plugin> |
| <groupId>org.apache.maven.plugins</groupId> |
| <artifactId>maven-assembly-plugin</artifactId> |
| <executions> |
| <execution> |
| <id>bin</id> |
| <phase>package</phase> |
| <goals> |
| <goal>single</goal> |
| </goals> |
| <configuration> |
| <descriptors> |
| <descriptor>src/main/descriptors/bin.xml</descriptor> |
| </descriptors> |
| <appendAssemblyId>false</appendAssemblyId> |
| <tarLongFileMode>gnu</tarLongFileMode> |
| </configuration> |
| </execution> |
| </executions> |
| </plugin> |
| </plugins> |
| </build> |
| |
| </project> |
| ---- |
| |
| The Maven POM will download the Karaf standard distribution and prepare resources to be processed by the Maven assembly plugin. |
| |
| Your Maven project structure should look like: |
| |
| * pom.xml: the previous POM file |
| * src/main/descriptors/bin.xml: the assembly Maven plugin descriptor (see below) |
| * src/main/filtered-resources: contains all resource files that have Maven property values to be filtered/replaced. Typically, this will include features descriptor and configuration files. |
| * src/main/distribution: contains all raw files which will be copied as-is into your custom distribution. |
| |
| For instance, `src/main/filtered-resources` could contain: |
| |
| * `my-features.xml` where Maven properties will be replaced |
| * `etc/org.apache.karaf.features.cfg` file containing your my-features descriptor: |
| |
| ---- |
| # |
| # Comma separated list of features repositories to register by default |
| # |
| featuresRepositories=mvn:org.apache.karaf/apache-karaf/${karaf.version}/xml/features,mvn:my.groupId/my-features/${project.version}/xml/features |
| |
| # |
| # Comma separated list of features to install at startup |
| # |
| featuresBoot=config,ssh,management,my-feature |
| ---- |
| |
| The `src/main/distribution` contains all your custom Karaf configuration files and script, as, for examples: |
| |
| * etc/org.ops4j.pax.logging.cfg |
| |
| ---- |
| # Root logger |
| log4j.rootLogger=INFO, out, osgi:VmLogAppender |
| log4j.throwableRenderer=org.apache.log4j.OsgiThrowableRenderer |
| |
| # CONSOLE appender not used by default |
| log4j.appender.stdout=org.apache.log4j.ConsoleAppender |
| log4j.appender.stdout.layout=org.apache.log4j.PatternLayout |
| log4j.appender.stdout.layout.ConversionPattern=%d{ABSOLUTE} | %-5.5p | %-16.16t | %-32.32C %4L | %X{bundle.id} - %X{bundle.name} - %X{bundle.version} | %m%n |
| |
| # File appender |
| log4j.appender.out=org.apache.log4j.RollingFileAppender |
| log4j.appender.out.layout=org.apache.log4j.PatternLayout |
| log4j.appender.out.layout.ConversionPattern=%d{ABSOLUTE} | %-5.5p | %-16.16t | %-32.32C %4L | %X{bundle.id} - %X{bundle.name} - %X{bundle.version} | %m%n |
| log4j.appender.out.file=${karaf.home}/log/my-customer-distribution.log |
| log4j.appender.out.append=true |
| log4j.appender.out.maxFileSize=1MB |
| log4j.appender.out.maxBackupIndex=10 |
| |
| # Sift appender |
| log4j.appender.sift=org.apache.log4j.sift.MDCSiftingAppender |
| log4j.appender.sift.key=bundle.name |
| log4j.appender.sift.default=my-custom |
| log4j.appender.sift.appender=org.apache.log4j.FileAppender |
| log4j.appender.sift.appender.layout=org.apache.log4j.PatternLayout |
| log4j.appender.sift.appender.layout.ConversionPattern=%d{ABSOLUTE} | %-5.5p | %-16.16t | %-32.32c{1} | %-32.32C %4L | %m%n |
| log4j.appender.sift.appender.file=${karaf.data}/log/$\\{bundle.name\\}.log |
| log4j.appender.sift.appender.append=true |
| ---- |
| |
| * etc/system.properties |
| |
| ---- |
| # |
| # The properties defined in this file will be made available through system |
| # properties at the very beginning of the FAS boot process. |
| # |
| |
| # Log level when the pax-logging service is not available |
| # This level will only be used while the pax-logging service bundle |
| # is not fully available. |
| # To change log levels, please refer to the org.ops4j.pax.logging.cfg file |
| # instead. |
| org.ops4j.pax.logging.DefaultServiceLog.level=ERROR |
| |
| # |
| # Name of this custom instance. |
| # |
| karaf.name=my-custom |
| |
| # |
| # Default repository where bundles will be loaded from before using |
| # other Maven repositories. For the full Maven configuration, see the |
| # org.ops4j.pax.url.mvn.cfg file. |
| # |
| karaf.default.repository=system |
| |
| # |
| # Location of a shell script that will be run when starting a shell |
| # session. This script can be used to create aliases and define |
| # additional commands. |
| # |
| karaf.shell.init.script=${karaf.home}/etc/shell.init.script |
| |
| # |
| # Set this empty property to avoid errors when validating xml documents. |
| # |
| xml.catalog.files= |
| |
| # |
| # Suppress the bell in the console when hitting backspace to many times |
| # for example |
| # |
| jline.nobell=true |
| |
| # |
| # Default port for the OSGi HTTP Service |
| # |
| org.osgi.service.http.port=8181 |
| |
| # |
| # Allow usage of ${custom.home} as an alias for ${karaf.home} |
| # |
| custom.home=${karaf.home} |
| ---- |
| * etc/users.properties |
| ---- |
| admin=admin,admin |
| ---- |
| * You can add a `etc/custom.properties`, it's a placeholder for any override you may need. For instance: |
| ---- |
| karaf.systemBundlesStartLevel=50 |
| obr.repository.url=http://svn.apache.org/repos/asf/servicemix/smx4/obr-repo/repository.xml |
| org.osgi.framework.system.packages.extra = \ |
| org.apache.karaf.branding; \ |
| com.sun.org.apache.xalan.internal.xsltc.trax; \ |
| com.sun.org.apache.xerces.internal.dom; \ |
| com.sun.org.apache.xerces.internal.jaxp; \ |
| com.sun.org.apache.xerces.internal.xni; \ |
| com.sun.jndi.ldap |
| ---- |
| |
| Now, we can "assemble" our custom distribution using the Maven assembly plugin. The Maven assembly plugin uses an |
| assembly descriptor, configured in POM above to be `src/main/descriptors/bin.xml`: |
| |
| ---- |
| <assembly> |
| |
| <id>bin</id> |
| |
| <formats> |
| <format>tar.gz</format> |
| </formats> |
| |
| <fileSets> |
| |
| <!-- Expanded Karaf Standard Distribution --> |
| <fileSet> |
| <directory>target/dependencies/apache-karaf-${karaf.version}</directory> |
| <outputDirectory>/</outputDirectory> |
| <excludes> |
| <exclude>**/demos/**</exclude> |
| <exclude>bin/**</exclude> |
| <exclude>etc/system.properties</exclude> |
| <exclude>etc/users.properties</exclude> |
| <exclude>etc/org.apache.karaf.features.cfg</exclude> |
| <exclude>etc/org.ops4j.pax.logging.cfg</exclude> |
| <exclude>LICENSE</exclude> |
| <exclude>NOTICE</exclude> |
| <exclude>README</exclude> |
| <exclude>RELEASE-NOTES</exclude> |
| <exclude>karaf-manual*.html</exclude> |
| <exclude>karaf-manual*.pdf</exclude> |
| </excludes> |
| </fileSet> |
| |
| <!-- Copy over bin/* separately to get the correct file mode --> |
| <fileSet> |
| <directory>target/dependencies/apache-karaf-${karaf.version}</directory> |
| <outputDirectory>/</outputDirectory> |
| <includes> |
| <include>bin/admin</include> |
| <include>bin/karaf</include> |
| <include>bin/start</include> |
| <include>bin/stop</include> |
| </includes> |
| <fileMode>0755</fileMode> |
| </fileSet> |
| |
| <!-- Copy over jar files --> |
| <fileSet> |
| <directory>target/dependencies</directory> |
| <includes> |
| <include>my-custom.jar</include> |
| </includes> |
| <outputDirectory>/lib/</outputDirectory> |
| </fileSet> |
| |
| <fileSet> |
| <directory>src/main/distribution</directory> |
| <outputDirectory>/</outputDirectory> |
| <fileMode>0644</fileMode> |
| </fileSet> |
| <fileSet> |
| <directory>target/classes/etc</directory> |
| <outputDirectory>/etc/</outputDirectory> |
| <lineEnding>unix</lineEnding> |
| <fileMode>0644</fileMode> |
| </fileSet> |
| |
| <fileSet> |
| <directory>target/features-repo</directory> |
| <outputDirectory>/system</outputDirectory> |
| </fileSet> |
| |
| </fileSets> |
| |
| <files> |
| <file> |
| <source>${basedir}/target/dependencies/apache-karaf-${karaf.version}/bin/karaf</source> |
| <outputDirectory>/bin/</outputDirectory> |
| <destName>my-custom</destName> |
| <fileMode>0755</fileMode> |
| <lineEnding>unix</lineEnding> |
| </file> |
| <file> |
| <source>${basedir}/target/classes/features.xml</source> |
| <outputDirectory>/system/my.groupid/my-features/${project.version}</outputDirectory> |
| <destName>my-features-${project.version}-features.xml</destName> |
| <fileMode>0644</fileMode> |
| <lineEnding>unix</lineEnding> |
| </file> |
| </files> |
| |
| </assembly> |
| ---- |
| |
| To build your custom Karaf distribution, just run: |
| |
| ---- |
| mvn install |
| ---- |
| |
| You will find your Karaf custom distribution tar.gz in the target directory. |