The eXist-db package repository is a central component of eXist-db. It makes it easy to
manage and deploy external packages (
.xar archives) which include everything they
need to run third party XQuery libraries, full applications or other XML technology
functionality. This article provides technical details on the packaging format.
The package repository is based on and extends the EXPath Packaging System. The core of the EXPath packaging specification has been designed to work across different XQuery implementations and is targeted at managing extension libraries (including XQuery, Java or XSLT code modules). eXist-db extends this core by adding a facility for the automatic deployment of entire applications into the database.
eXist-db packages may fall into one of the following categories:
Contain application code, HTML views, associated services, resources and data. An application always has a web interface which can be displayed, if for example the user clicks on the application icon in the Dashboard.
- Resource packages
- Library packages
Provide a set of XQuery library modules to be registered with eXist-db and used by other packages. A library package may also contain Java
.jararchives to be loaded into the eXist-db classpath. It has no web view and is not deployed into the database.
These categories are not exclusive. An application may include resources and XQuery libraries and is not required to move those into separate packages.
An EXPath package is essentially an archive file in ZIP format. By convention, the file
extension of the package is
The archive must contain two XML descriptor files in the root
This is the standard EXPath descriptor as defined by the EXPath specification. It specifies the unique name of the package, lists dependencies and any library modules to register globally. See expath-pkg.xml.
The eXist-db specific deployment descriptor: it contains additional metadata about the package and controls how it will be deployed into the database. See repo.xml.
For library packages
repo.xml is optional. However, we recommend to
always provide it for better tool integration.
As an example, the EXPath descriptor for the documentation app is shown below:
The schema of this file is documented in the specification. In short, the attributes are as follows:
URI used as a unique identifier for the package. The URI does not need to point to an existing web site. The package repository will use this URI to identify a package within the system.
Short abbreviation for the package. This will be used as part of the file name for the
.xar. We recommend to choose a short, simple name, without spaces or punctuation characters.
Version of the package. This allows the Package Manager to determine if newer versions of the same package are available.
Version of the packaging specification the package conforms to. Always
1.0for the current specification.
Descriptive title to display to the user (in the Dashboard)
A package may depend on one or more other packages. The Package Manager in the Dashboard will resolve these dependencies before deployment. Dependant packages will be installed automatically from the public repository. It is an error if a dependency cannot be resolved.
A dependency on another package is defined by using a reference to the unique name of
the other package: The name attribute (URI) of the
It is also possible to create a dependency on a specific version, based on Semantic Versioning. This can be done by adding either of the
A simple version string which must exactly match the version string of the package to install.
A "semantic" version string: the version number must follow the scheme
x.x.x. Selects the highest version in the range of versions starting with
For example, if semver is
1.2, a package with version
1.2.3will be selected because it is in the
1.2release series. Likewise, if
1, any package with a version starting with
1will be chosen.
Defines a minimal required version according to the
Maximum version allowed.
These attributes are mutually exclusive, except for
semver-max, which may appear together. We recommend using
It is also possible to require a certain eXist-db version (for versions greater than 2.2). The Dashboard will prevent installation of packages into unsupported instances and display a warning to the user. To require such a specific eXist-db version, include a processor dependency in your descriptor:
A package may list one or more library modules to register with eXist-db. The registered modules will become globally available within the eXist-db instance and may be used by other packages without knowing where the module code is stored.
For example, the following descriptor registers the module
functx.xql using the given namespace:
The namespace has to correspond to the namespace defined in the module declaration of
the XQuery module. The file should be placed into a subdirectory of the .xar archive,
named "content". The structure of the
.xar for the
library would be as follows:
/expath-pkg.xml /repo.xml /content/functx.xql
Only XQuery files which are registered in
expath-pkg.xml need to go into
this special directory. You are free to keep other XQuery files wherever you want. Also,
XQuery resources which are only used by a single application, should
not be registered (to avoid messing up the global context).
Registering a module only makes sense for libraries which will likely be used by several
After installing the package, you should be able to use the registered XQuery modules
from anywhere within the database instance without knowing the exact import path. Thus the
following import statement will be sufficient to import the
eXist-db also supports XQuery extension modules written in Java. These require a
slightly different mechanism for integration into a
.xar package. This
is an extension to the standard EXPath format and should goes into a separate file, named
As an example, the
exist.xml descriptor of the cryptographic extension
module is shown below:
The descriptor may contain one or more
<jar> elements, each pointing to a
.jar archive to be installed. Arbitrary
can be listed here: they do not need to be XQuery extension modules. Again, the
.jar files should be placed into the "content" subdirectory of the
.jar files will be dynamically added to eXist-db's class loader and
become immediately available after deploying a package. A restart of eXist-db is not
<java> element registers an XQuery extension module written in Java. This
is similar to the
<xquery> element for library modules, except that the namespace
is mapped to a Java class instead of an XQuery file. The Java class should point to the
Module class which defines the module.
The deployment descriptor contains additional metadata and defines how the package will be installed into an eXist-db database instance. For example:
The two settings:
target determine how a package is
handled by the installer:
Type of package
An application package has
<type> set to
application and specifies
<target> because it needs to be deployed into the database. Contrary to this, a
library package only registers XQuery or other modules, but no resources need to be stored
into the database, so
<target> is empty.
Should be set to either
library. We assume a library has no GUI. A library will therefore not be shown on the main Dashboard page, which only lists applications.
Specifies the collection where the contents of the package will be stored. Top-level files in the package will end up in this collection, resources in sub-directories will go into sub-collections. Please note that the target collection can be changed by the package manager during install: It is a recommendation, not a requirement.
The collection path should be relative to the repository root collection defined in the configuration (usually
You can define package specific permissions in the
repo.xmlto use when uploading package contents like this:<permissions user="app-user" password="123" group="app-group" mode="rw-rw-r--"/>
All resources and collections will be owned by the specified user and permissions will be changed to those given in
mode. If the user does not exist, the deploy function will try to create it, using the password specified in the
Concerning permissions: the execute
xflag will be set automatically on all XQuery files, in addition to the default permissions defined in the descriptor. For more control over permissions, use a post-install XQuery script (see element
It is generally recommended to specify users in this manner when a package requires write privileges to the database, and to use a custom user-group (i.e. not
dba). To avoid conflicts with locally defined user-names and group names, packages that do not require write access can omit permissions in their
repo.xml. These packages will be assigned to the
guestuser group by default.
Points to an XQuery script inside the root of the package archive, which will be executed before any package data is uploaded to the database. By convention the XQuery script is called
pre-install.xql, but this is not a requirement.
If you create a package via eXide, it will generate a default
pre-install.xqlwhich uploads the default collection configuration to the system collection. This needs to be done before deployment to guarantee that index definitions are applied when data is uploaded to the db.
The target collection, the file system path to the current package directory and eXist-db's home directory, are passed to the script as external variables:(: file path pointing to the eXist-db installation directory :) declare variable $home external; (: path to the directory containing the unpacked .xar package :) declare variable $dir external; (: the target collection into which the app is deployed :) declare variable $target external;
The script can use these to read files contained in the package.
<prepare>, this element must point to an XQuery script. This will be executed after all data has been uploaded to the database. It receives the same external variables as the prepare script. The convention is to name the script
<finish>script to run additional tasks or move data into different collections. For example, the XQuery function documentation app runs an indexing task from the finish trigger to extract documentation from all XQuery modules known to the database at the time.
This element is set automatically when the package is deployed into a database instance. It is used by eXide to track changes and does not need to be specified in the original
Packages should be portable and should not make any assumptions about the collection path in which they will be installed. So best to use relative paths throughout XQuery modules, in particular for import statements. Just as a reminder: a relative path in an "import module namespace..." expression is always relative to the XQuery which contains the import.
If an XQuery needs to access data provided by another package, it should locate the other package by its package name and not by using an absolute collection path which may change in the future. For example, if an application requires access to data stored in another package called "data-pkg", it could define a variable to point to the correct collection as follows:
The root collection for deployed packages can be configured in
The install location specified in the
<target> element of
repo.xml will always be relative to this root collection.
eXist-db's URL rewriting is by default configured to map any path starting with
/apps to the repository root collection. Check
webapp/WEB-INF/controller-config.xml and the URL rewriting
repo XQuery module provides a number of functions to
programmatically install, remove or inspect packages. The Dashboard Package Manager relies on
the same functions.
The module distinguishes between installation and
deployment steps. The reason for this distinction is: while the
installation process is standardized by the EXPath packaging specification, the deployment
step is implementation defined and specific to eXist-db. Installation
will register a package with the EXPath packaging system, but not copy anything into the
database. Deployment will deploy the application into the database as
specified by the
The most convenient way to install a package are the
repo:install-and-deploy downloads the specified package from a public
repository. For example, one can install the eXist-db demo apps using the following
The first parameter denotes the unique name of the package to install. The second may contain a specific version or the empty sequence. The third parameter is the URI for the public repository. The function call will download, install and deploy the package as well as any dependencies it defines. If the installation succeeds, an element will be returned to indicate the target collection into which the package was deployed.
repo:install-and-deploy-from-db function works in a similar way, but
reads the package data to install from a resource stored in the database.
To uninstall a package, you should first call
repo:undeploy, followed by
repo:remove. For instance:
To list all installed packages, call
repo:list. This will return the unique
name of every installed package.
You can run your private repository and install packages from it, for instance to
distribute applications to your customers. The eXist-db repository is implemented by the
http://exist-db.org/apps/public-repo. The code can be
downloaded from the eXist-db
Once you have built and installed the app, you can upload the package
files you wish to distribute into the collection
make the uploaded
.xar files available, run the query
public-repo/modules/update.xql once as an
admin user. This
will create a document