Extension Modules

(2Q21)


This article provides an overview of how to create XQuery extension modules (in Java) for eXist-db, and contains a list of extension modules which have additional configuration options.

Introduction

eXist-db provides a pluggable module interface that allows extension modules to be easily developed in Java. These extension modules can provide additional XQuery functions through a custom namespace. The extension modules have full access to the eXist-db database, its internal API, the context of the executing XQuery and the HTTP Session (if appropriate).

The source code for extension modules should be placed in their own folder inside $EXIST_HOME/extensions/modules/*/src/main/java/org/exist/xquery/modules/*. They may then be added to $EXIST_HOME/extensions/modules/pom.xml and compiled in place using mvn compile.

Modules associated with modularized indexes must be placed in the $EXIST_HOME/extensions/indexes/*/xquery/modules/* hierarchy. They may then be added to $EXIST_HOME/extensions/indexes/pom.xml. They will be compiled automatically by the standard build targets or as indicated above.

eXist-db must also be told which modules to load at startup, this is done in conf.xml and the Class name and Namespace for each module is listed below.

eXist-db will require a restart to load any new modules added.

Once a Module is configured and loaded eXist-db will display the module and its function definitions as part of the function library page or through util:decribe-function().

Extension Modules Configuration

Whilst most extension modules work without any further configuration than that described above, some modules have additional configuration options. Those additional options are described in this section.

Cache Module

This module provides a Global Mutable cache which can be used for manually caching data. This is often used for caching the results of expensive queries.

  • Creator: Adam Retter

  • Licence: LGPL v2

  • Used: Caffeine

  • Status: production

  • Class: org.exist.xquery.modules.cache.CacheModule

  • Namespace: http://exist-db.org/xquery/cache

The Cache module can be configured for with a bounded size, or time, or both. eXist-db cannot know how much memory the data you will put in the cache will take, so it is up to you to manage your own memory needs here.

A named cache can either be explicitly created by calling the cache:create XQuery function, or it can be implicitly created lazing on the first operation performed on the cache. Configuration of the Cache module is specified within the module definition of eXist-db's conf.xml file:

<module class="org.exist.xquery.modules.sql.CacheModule" uri="http://exist-db.org/xquery/cache">
  <parameter name="enableLazyCreation" value="true"/>
  <!-- allow the cache to be created implicitly -->
  <parameter name="lazy.maximumSize" value="128"/>
  <!-- size bound - 128 entries max -->
  <parameter name="lazy.expireAfterAccess" value="60000"/>
  <!-- time bound - 60 seconds -->
</module>

SQL Module

This module provides facilities for performing SQL operations against traditional databases from XQuery and returning the results as XML nodes.

  • Creator: Adam Retter

  • Licence: LGPL v2

  • Used: JDBC

  • Status: production

  • Class: org.exist.xquery.modules.sql.SQLModule

  • Namespace: http://exist-db.org/xquery/sql

The SQL Module can be configured with additional which allow Connection Pooling of the SQL connections to be utilised. For this purpose the HikariCP connection pool implementation is used.

Multiple connection pools can be configured and used from XQuery via the sql:get-connection-from-pool function.

All of HikariCP's configuration options can be configured on a per-pool basis. Configuration of the connection pools is specified within the module definition of eXist-db's conf.xml file:

<module class="org.exist.xquery.modules.sql.SQLModule" uri="http://exist-db.org/xquery/sql">
  <!-- Connection Pool 1 -->
  <parameter name="pool.1.name" value="pool-1"/>
  <parameter name="pool.1.properties.dataSourceClassName" value="org.postgresql.ds.PGSimpleDataSource"/>
  <parameter name="pool.1.properties.dataSource.user" value="my-username"/>
  <parameter name="pool.1.properties.dataSource.password" value="my-password"/>
  <parameter name="pool.1.properties.dataSource.databaseName" value="my-db"/>
  <parameter name="pool.1.properties.maximumPoolSize" value="10"/>
  <parameter name="pool.1.properties.registerMbeans" value="false"/>
  <!-- Connection Pool 2 -->
  <parameter name="pool.2.name" value="pool-2"/>
  <parameter name="pool.2.properties.dataSourceClassName" value="org.mariadb.jdbc.MariaDbDataSource"/>
  <parameter name="pool.2.properties.dataSource.user" value="my-other-username"/>
  <parameter name="pool.2.properties.dataSource.password" value="my-other-password"/>
  <parameter name="pool.2.properties.dataSource.databaseName" value="other-db"/>
  <parameter name="pool.2.properties.maximumPoolSize" value="10"/>
  <parameter name="pool.2.properties.registerMbeans" value="false"/>
</module>

Any JDBC drivers that are used will need to be added to eXist-db's lib/ folder and configured in the startup descriptor XML file in eXist-db's etc/ folder.