iDempiere and OSGi: a modular Java architecture



iDempiere is an open source Enterprise Resource Planning (ERP) system that describes itself as "OSGi + ADempiere", but what does that mean in practice? 

iDempiere and Modularity

This post describes OSGi and the technology stack that was used to build iDempiere so that developers and solution architects can see how the system hangs together.

History of iDempiere

In the beginning, there was Compiere ("to accomplish, complete, fulfill" in Italian), an open source ERP system that was started in 1999. Initially it was very successful but after a long-standing disagreement between the developer community and the management company behind Compiere about its monetization strategy, the project was forked by a number of developers to create ADempiere (a word like 'compiere', but with the additional sense of "to fulfil obligations, or discharge duties", and also "to honor and respect").

ADempiere was also very successful, but its monolithic design had a number of limitations so some of the core architects forked the codebase in 2011 to create a more modular system called iDempiere, based on the OSGi specification.

OSGi and modularity

The OSGi specification defines a dynamic component system for Java. It is a specification that describes how individual bundles of code, also known as plug-ins, can be connected together in a dynamic way by a services layer that offers a publish-find-bind model for plain old Java objects (POJOs).

In standard Java everything in a JAR may be visible to all other JARs, but with OSGi, everything in that JAR is hidden unless it is explicitly exported in a predetermined manner. There is no sharing by default, so a bundle that wants to use another JAR must explicitly import the parts it needs. Conversely, a bundle must explicitly export functionality that is to be used by other bundles.

<table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container"
    style="margin-left: auto; margin-right: auto; text-align: center;">
    <tbody>
        <tr>
            <td style="text-align: center;"><a href="https://www.osgi.org/wp-content/uploads/layering-osgi.png"
                    imageanchor="1"
                    style="clear: right; margin-bottom: 1em; margin-left: auto; margin-right: auto;"><img border="0"
                        src="https://www.osgi.org/images/resources/layering-osgi.png" style="cursor: move;" /></a>
            </td>
        </tr>
        <tr>
            <td class="tr-caption" style="text-align: center;">OSGi layered architecture</td>
        </tr>
    </tbody>
</table>OSGi does this by specifying a layered model to manage plug-ins:<br />
<ul>
    <li>Bundles: these are the OSGi plug-in components that deliver the application functionality, consisting of
        POJOs with additional meta-data defined in the <i><b>MANIFEST.MF</b></i> file. Bundles hide their internals
        from other bundles and communicate through well defined services. Bundles are self-contained, reusable units
        of deployable code, usually in the form of a JAR;</li>
    <li>Services: this layer connects bundles in a dynamic way by offering a publish-find-bind model for the POJOs
        registered in the service registry. Without OSGi, the standard Java solution is to use static factory
        methods and Java Reflection to load classes dynamically, resulting is a variety of passive, non-standard
        APIs and configuration mechanisms;</li>
    <li>Life-Cycle: the API that allows you to list, install, start, stop, update, and uninstall bundles on the fly
        without bringing down the whole system. Bundles can be managed directly from the OSGi console command line
        interface and they can be managed remotely;</li>
    <li>Modules: the layer that defines how a bundle's dependencies are managed by importing and exporting code
        according to the bundle's manifest. Modules are discrete, coarse-grained deployable units;</li>
    <li>Security: the layer that handles &nbsp;security by separating bundles from each other and enforcing
        permissions to allow or deny bundles access to each other;</li>
    <li>Execution Environment: the underpinning OSGi platform that manages the containers. Like the Eclipse IDE,
        iDempiere is built on <a href="https://www.eclipse.org/equinox/" target="_blank">Equinox</a>, which is the
        reference implementation of the OSGi specification (two other notable implementations of OSGi are&nbsp;<a
            href="http://www.knopflerfish.org/" target="_blank">Knopflerfish OSGi</a> and <a
            href="http://felix.apache.org/" target="_blank">Apache Felix</a>).</li>
</ul>
<h3>Modular structure of iDempiere</h3>
<div>The team that forked the code partitioned the monolithic Adempiere application into a large number of plug-ins,
    each with its own classpath and set of dependencies. If you download the iDempiere codebase and <a
        href="https://wiki.idempiere.org/en/Installing_iDempiere" target="_blank">open it with Eclipse</a>, you
    will see that it consists of dozens of projects: one for each OSGi bundle, or plug-in.&nbsp;</div>
<div><br />This allows developers to create custom-built plug-ins without touching the upstream codebase. The
    Equinox OSGi container manages these plug-ins as free-standing, deployable Java objects that interact with the
    rest of the core iDempiere bundles by means of APIs.<br /><br />
    <table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container"
        style="margin-left: auto; margin-right: auto; text-align: center;">
        <tbody>
            <tr>
                <td style="text-align: center;"><a
                        href="https://1.bp.blogspot.com/-kBjDPaeJwqQ/WXgfHGdsiKI/AAAAAAAAC4I/8YvcIeJ-vp8LUH1Uzc6WzPBvXkd6C7rHgCLcBGAs/s1600/services.png"
                        imageanchor="1" style="margin-left: auto; margin-right: auto;"><img border="0"
                            data-original-height="126" data-original-width="352" height="142"
                            src="https://1.bp.blogspot.com/-kBjDPaeJwqQ/WXgfHGdsiKI/AAAAAAAAC4I/8YvcIeJ-vp8LUH1Uzc6WzPBvXkd6C7rHgCLcBGAs/s400/services.png"
                            width="400" /></a></td>
            </tr>
            <tr>
                <td class="tr-caption" style="text-align: center;">Bundles are managed in a service registry</td>
            </tr>
        </tbody>
    </table><br />The advantages are:<br />
    <ul>
        <li>explicit dependency management: iDempiere plug-ins declare what they need and what functionality they
            provide, whilst otherwise remaining isolated from each other;</li>
        <li>versioned dependency: you can have different versions of the same Java class in different bundles if
            necessary because your plug-in's dependencies are managed by the OSGi container, not the JVM;</li>
        <li>small footprint: plug-ins are not packaged with all their dependencies, and they follow a lazy
            activation policy so they are only loaded as and when required;</li>
        <li>easy release: plug-ins can be developed and released independently of upstream developments;</li>
        <li>hot redeploy: individual plug-ins can be redeployed on the fly without affecting the others.</li>
    </ul>
</div>
<h2>Core iDempiere plug-ins</h2>
<h3>org.adempiere.server</h3>Now that we have looked at OSGi, let's dig deeper into the structure of iDempiere and
look at the core plug-ins that make up the application. <br /><br />When iDempiere starts, a Bash shell script <span
    style="font-family: monospace; font-size: 9pt; white-space: pre-wrap;">idempiere-server.sh</span>&nbsp;executes
the Equinox OSGi launcher&nbsp;<span
    style="font-family: monospace; font-size: 9pt; white-space: pre-wrap;">org.eclipse.equinox.launcher</span>,
passing it the name of the initial executable entry point as a runtime option, namely <span
    style="font-family: monospace; font-size: 9pt; white-space: pre-wrap;">org.adempiere.server.application.
</span>This Java class implements the Equinox OSGi IApplication interface and starts the application.<br /><br />The
manifest of <span
    style="font-family: monospace; font-size: 9pt; white-space: pre-wrap;">org.adempiere.server</span>&nbsp;directs
Equinox to load these bundles as dependencies:<br />
<ul>
    <li>org.eclipse.equinox.app:&nbsp;implementation of the Equinox OSGi Application Container service;</li>
    <li>org.eclipse.jetty.apache-jsp: support for JSP in the embedded Jetty HTTP container;</li>
    <li>org.adempiere.base: the core functionality of iDempiere.</li>
</ul>
<h3>Equinox OSGi Application Container</h3>
<div>The Equinox OSGi framework implementation is probably better known as the foundation of the Eclipse IDE
    platform, but it is actually a <a href="https://www.eclipse.org/equinox/documents/quickstart.php"
        target="_blank">standalone OSGi implementation</a>. It is launched by the&nbsp;<span
        style="font-family: monospace; font-size: 12px; white-space: pre-wrap;">org.adempiere.server</span> plug-in
    when iDempiere is started and is responsible for loading all the other iDempiere plug-ins and managing the
    relationships and dependencies between them.<br /><br />Read&nbsp;<a
        href="http://www.vogella.com/tutorials/OSGi/article.html" target="_blank">this tutorial</a>&nbsp;on OSGi
    modularity with Eclipse by the ever-dependable Lars Vogel, and watch&nbsp;<a
        href="https://www.youtube.com/watch?v=BnT38yzJk1c" target="_blank">this video</a>&nbsp;by Kirk Knoernschild,
    the author of "Java Application Architecture: Modularity Patterns with Examples Using OSGi", for a very useful
    overview of the current state of modularity on the Java platform.</div>
<h3>Jetty HTTP Server</h3>iDempiere uses <a
    href="https://www.eclipse.org/jetty/documentation/current/framework-jetty-osgi.html" target="_blank">the Jetty
    OSGi infrastructure</a> to <a href="https://www.eclipse.org/equinox/server/http_in_equinox.php"
    target="_blank">embed an HTTP server</a> inside an OSGi container. This hosts the static content, servlets, OSGi
web bundles (the OSGi equivalent of WAR files), and provides support for the Java ServerPages (JSPs) used by the
original Adempiere code.<br /><br />In production, it would be wise to put a reverse proxy in front of Jetty,
running web application security software such as <span
    style="font-family: monospace; font-size: 9pt; white-space: pre-wrap;"><a
        href="https://www.modsecurity.org/about.html" target="_blank">mod_security</a>.</span> Jetty can expose JMX
services which should be monitored in a production environment. The Jetty configuration files are in <span
    style="font-family: monospace; font-size: 9pt; white-space: pre-wrap;">$IDEMPIERE_HOME/jettyhome/etc/.</span><br /><span
    style="font-family: monospace; font-size: 9pt; white-space: pre-wrap;"></span>
<h3>org.adempiere.base</h3>
<div>This is the base plug-in that provides all the core functionality needed to <a
        href="http://wiki.idempiere.org/en/Developing_plug-ins_without_affecting_the_trunk" target="_blank">build
        iDempiere plug-ins</a> and includes interfaces such as:<br />
    <ul>
        <li>IResourceFinder: finds resources in each plugin;</li>
        <li>IColumnCallout: called whenever a column on a table changes its value;</li>
        <li>IModelValidator: called whenever a record is saved;</li>
        <li>IMenuAction: called whenever a window menu is created;</li>
        <li>IModelFactory: called to create new class models;</li>
        <li><a href="http://red1.org/javadoc/org/adempiere/base/package-summary.html" target="_blank">and many
                others</a>.</li>
    </ul>
</div>

Wait, there's more...

These core plug-ins are at the heart of iDempiere, but there are many others that provide the application functionality, including the persistence layer, the report writer and the user interface, so follow the tutorial by Carlos Ruiz from GlobalQSS and download the code to explore further.

Here is a follow-up post that describes how Buckminster is used to build iDempiere on OSGi.