"assembly" protocol

Overview

Assembly protocol handlers provides you with the mean for assembling a jar on the fly out of files from a directory, another jar file and/or a zip file, in any combination. There are two flavors of "assembly" protocol as detailed bellow: the simplest form will allow you to transform just one source (directory / jar / zip), the other form, will allow your to use a descriptor file to combine any number sources.

When do I use it?

There are probably numerous use cases when you could use the "assembly" protocol but one stands out:

During development of your projects you usually have the sources on the file system, sources that are compiled by your build system, such as Maven or ANT, or your IDE, and stored somewhere on the file system in a directory. As an example lets take Maven case: the compiled classes are stored under "<project>/target/classes". If you use an IDE such as IntelliJ IDEA on this Maven project, as soon as sources get changes, they are automatically compiled to the same directory.

Now, what would you want to do is to have the sources of this project, assembled together as bundle and deployed as a bundle in an OSGi framework. To do this you will have to (usually) generate an OSGi bundle (jar) our of this classes and deploy the generated bundle.

But why not directly deploy the directory as a bundle? Because most of OSGi frameworks only supports a jar as deployment artifact. And here is where the "assembly" protocol will shine. Will allow you to do just that: transparently deploy the directory as a bundle on ANY OSGi framework. More then that doing a bundle update will re-generate the bundle content automatically. And all of this with a simple URL like:

assembly:<project>/target/classes

Now, do not understand from this example that it can be used only with Maven. You can use any directory, include or exclude files you want and much more as described in the sections bellow.

Simple form: "assembly:"

The simple form of "assembly" protocol is probably the form you will use most of the time and will allow you to assemble a jar out of files from a file system directory, a jar or a zip. By default it will include all files from all subdirectories but you can specify the include and exclude patters in ANT format.

All jars need a manifest so the assembly handler will search a file META-INF/MANIFEST.MF and use it if present. Otherwise a default manifest will be generated.

Here are some examples of usage:

  • Generate a jar including all files from a directory relative to current directory:
    assembly:./my-project/bin
  • Generate a jar including all files from an absolutely specified directory:
    assembly:/Users/pax/Projects/my-project/bin
  • Generate a jar including all files from zip:
    assembly:/Users/pax/Projects/my-project.zip
  • Generate a jar including all files from jar:
    assembly:/Users/pax/Projects/my-project.jar
  • Generate a jar including all files from jar specified from an URL:
    assembly:mvn:my-project-group/my-project-artifact
  • Generate a jar including all classes from a directory:
    assembly:./my-project/bin!/*/.class
  • Generate a jar including all classes and files under META-INF from a directory:
    assembly:./my-project/bin!/*/.class&META-INF/**
  • Generate a jar including all classes and excluding Java files from a directory (note the "!"):
    assembly:./my-project/bin!/*/.class&!*/.java

Syntax

The url of "assembly:" protocol must comply to the following syntax:

assembly-uri := 'assembly:' path [ '!/' filters ]

path := directory | zip

directory := <file system path>| < file url>

zip := <zip/jar file system path> | <zip/jar url>

filter := filter [ '&' filter ]

filter := include | exclude

include := <ant pattern>

exclude := '!' <ant pattern>

Where:

  • file system path
    A relative or absolute file system specific path. E.g. ./my-project/target/classes or /Users/pax/Projects/my-project/target/classes.
  • file url
    A Java "file:" url. E.g. file:./my-project/target/classes or file:/Users/pax/Projects/my-project/target/classes
  • zip/jar file system path
    A relative or absolute path to a zip or jar file. E.g. ./my-project/target/my-project.zip or /Users/pax/Projects/my-project/target/my-project.jar
  • zip/jar url
    An url of a zip or jar file. E.g. file:./my-project/target/my-project.zip or http://my-site.org/my-project.jar or mvn:my-project-group/my-project-artifact
  • ant pattern
    An ANT like pattern. E.g. "*/.class". Read more about on ANT documentation.

Advanced form: "assemblyref:"

If you need to combine files from more then one directory of zip or jar then you can use the advanced form that will allow you to use a descriptor file to specify the sources and inclusion / exclusion patterns. The descriptor file is a JSON file that specified the directories, zips or jars, inclusion / exclusion patterns and an optional manifest url.

All jars need a manifest, the assembly handler will first use the specified manifest url in descriptor. If not specified it will search a file META-INF/MANIFEST.MF and use it if present. Otherwise a default manifest will be generated.

Here are some examples of usage:

  • Generate a jar using a descriptor file referenced as relative to current directory:
    assemblyref:./my-project/assembly.json
  • Generate a jar using a descriptor referenced as an absolute path:
    assemblyref:/Users/pax/Projects/my-project/assembly.json

As well as some examples of descriptor files:

  • Generate a jar including all files from an absolutely specified directory:
    {
        "assembly" : {
            "directory" : {
                "path" : "/Users/pax/Projects/my-project/bin"
            }
        }
    }
    
  • Generate a jar including all classes and files under META-INF from a directory:
    {
        "assembly" : {
            "directory" : {
                "path" : "./my-project/bin",
                "include" : "**/*.class",
                "include" : "META-INF/**"
            }
        }
    }
    
  • Generate a jar including all classes and excluding Java files from a directory (note the "!"):
    {
        "assembly" : {
            "directory" : {
                "path" : "./my-project/bin",
                "include" : "**/*.class",
                "exclude" : "**/*.java"
            }
        }
    }
    
  • Generate a jar combining more directories:
    {
        "assembly" : {
            "directory" : {
                "path" : "./my-project/bin",
            },
            "directory" : {
                "path" : "./Users/pax/Projects/my-other-project/target/classes",
            }
        }
    }
    
  • Generate a jar combining directories with jars and zips:
    {
        "assembly" : {
            "directory" : {
                "path" : "./my-project/bin",
            },
            "jar" : {
                "path" : "mvn:my-project-group/my-project-artifact",
            },
            "zip" : {
                "path" : "/Users/pax/Projects/my-project.zip",
            }
        }
    }
    
  • Generate a jar including all files from an absolutely specified directory with a specified manifest:
    {
        "assembly" : {
            "directory" : {
                "path" : "/Users/pax/Projects/my-project/bin"
            }
        },
        "manifest" : "/Users/pax/Projects/my-project/MANIFEST.MF"
    }
    

Syntax

The url of "assemblyref:" protocol must comply to the following syntax:

assembly-ref-uri := 'assemblyref:' descriptor

descritor := <file system path>| < file url>

Where:

  • file system path
    A relative or absolute file system specific path. E.g. ./my-project/assembly.json or /Users/pax/Projects/my-project/assembly.json.
  • url
    An url of a descriptor file. E.g. file:./my-project/assembly.json or http://my-site.org/descriptors/assembly.json

Descriptor format

The descriptor file is a JSON file that must comply to the following format.

Tips & tricks

Automatically generate OSGi manifest headers

The assembly url does not automatically generate an OSGi bundle. It will just include the files and the manifest file your specify. If you do not have a manifest or the manifest does not include the necessary OSGi entries you can make use of Pax URL "wrap:" protocol, that will automatically transform the jar generated by "assemble:" handler into an OSGi bundle. For example:

wrap:assembly:./my-project/bin
wrap:assemblyref:./my-project/assembly.json

Automatically generate WARs

If you are into web applications you can make use of assembly url handler to generate your WAR file and then combine it with Pax URL "war:" protocol, that will automatically transform the jar generated by "assemble:" handler into an OSGi enabled Web ARchive. For example:

warbundle:assembly:./my-project/bin
warbundle:assemblyref:./my-project/assembly.json

Use assembly url with Pax Runner

Starting with version 1.2.0, Pax Runner will include by default "assembly:" / "assemblyref:" protocol handlers, so you will be very easy to provision them as for example:

pax-run assembly:./my-project/bin wrap:assemblyref:./my-project/assembly.json

Use assembly url with Apache Felix

Read about how to configure Apache Felix to use "assembly" and "assemblyref:" protocols.