| |
| |
| h1. Custom distributions |
| |
| As Karaf is an OSGi container, it's heavily used as an 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 |
| |
| h2. Maven assembly |
| |
| Basically a Karaf custom distribution involves: |
| 1. Uncompressing a standard Karaf distribution in a given directory. |
| 2. Populating the system repo with your features. |
| 3. Populating the lib directory with your branding or other system bundle jar files. |
| 4. 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: |
| |
| {code} |
| <?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>2.2.2</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>features-maven-plugin</artifactId> |
| <version>${karaf.version}</version> |
| <executions> |
| <execution> |
| <id>add-features-to-repo</id> |
| <phase>generate-resources</phase> |
| <goals> |
| <goal>add-features-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> |
| {code} |
| |
| 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: |
| {code} |
| # |
| # 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 |
| {code} |
| |
| The {{src/main/distribution}} contains all your custom Karaf configuration files and scripts, as, for examples: |
| |
| * etc/org.ops4j.pax.logging.cfg |
| {code} |
| # 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 |
| {code} |
| * etc/system.properties |
| {code} |
| # |
| # 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} |
| {code} |
| * etc/users.properties |
| {code} |
| admin=admin,admin |
| {code} |
| * You can add a {{etc/custom.properties}}, it's a placeholder for any override you may need. For instance: |
| {code} |
| 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 |
| {code} |
| |
| 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}}: |
| |
| {code} |
| <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> |
| {code} |
| |
| To build your custom Karaf distribution, just run: |
| |
| {code} |
| mvn install |
| {code} |
| |
| You will find your Karaf custom distribution tar.gz in the target directory. |
| |
| h2. Roadmap |
| |
| A distribution goal is in preparation in the next Karaf |
| |
| h2. Custom distribution examples |
| |
| * [Apache ServiceMix 4|http://svn.apache.org/repos/asf/servicemix/smx4/features/trunk/assembly/] |
| * [Apache ServiceMix NMR|http://svn.apache.org/repos/asf/servicemix/smx4/nmr/trunk/assembly/] |
| * [BuildProcess BuildEraser|http://buildprocess.svn.sourceforge.net/viewvc/buildprocess/builderaser/trunk/assembly/] |