ADempiere/OSGi Integration

From ADempiere
Revision as of 21:28, 17 April 2009 by Red1 (Talk) (better announcement suggestion)

(diff) ← Older revision | Latest revision (diff) | Newer revision → (diff)
Jump to: navigation, search
This Wiki is read-only for reference purposes to avoid broken links.

ANNOUNCEMENT: THIS IS NOW DEPRECATED BY Equinox Integration

OSGi module framework in ADempiere

120px-OSGi Logo.gif

Overview

OSGi is a modular framework for Java with many advanced features. For information see http://en.wikipedia.org/wiki/OSGi.

Modular design has many advantages on huge projects such as ADempiere. Integrating OSGi may have huge impact on maintainability of the code.

Integration with ADempiere was done by Schmidt András.

OSGi module framework is pending more votes to be accepted into the ADempiere project. Please vote in the SF thread link below.

Technical documentation and howto

Overview

150px-Apache Felix Logo.png

The Apache Felix OSGi implementation was selected for integration. This is the framework that is easiest to be run embedded.

Embedding an OSGi framework with the following properties could be a common task when converting non-OSGi software to modular design. So I have decided to create a new project for the embedding code. This project's output is a single jar file that contains felix.jar and some helper methods for easier startup. Helper methods' interface are implementation independent so change to Equinox or Knopflerfish can be done by just replacing a single jar of the project. The embedder is announced here: http://i-erp.i-logic.hu/?q=content/osgi-embedder-adempiere-and-other-projects. It is not documented too much yet.

The properties of embedding:

  1. Don't use a constant configuration but create a new one for each started instance in a temporary directory.
  2. Start all plugins in a directory on startup. So installing plugins can be done by just copying them.
  3. Hot Start plugins, so plugins can be started without restarting the server.
  4. Export some packages of the host application, so they can be reached from the osgi bundles.

Parameters of the OSGI starter

Exported packages

The exported packages of the host application (so bundles can resolve these packages and load classes from them) are listed in file: "base/src/org/compiere/exported.properties"

This file is a comma and whitespace separated list of package names. It has ".properties" suffix so that it will be packaged into the created jar file without changing the build.xml files.

Initial startup plugins directory

Osgi bundles in this directory will be started on ADempiere (embedded osgi) startup. This directory is:

  1. either the system property: System.getProperty("org.osgi.bundles.dir")
  2. or the directory "%ADEMPIERE_HOME%/plugins" if this system parameter does not exist.

Dynamic startup plugins directory

File changes in this directory will be scanned periodically. Plugins copied here will be started automatically just as ear and web application hot deploy works on application and web servers. This directory is:

  1. either the system property: System.getProperty("org.osgi.bundles.dynamic.dir")
  2. or the directory "%ADEMPIERE_HOME%/dynPlugins" if this system parameter does not exist.

Creating a extension bundle

Import packages from ADempiere

The extension bundle has to import packages from ADempiere using import package in MANIFEST.MF. It can be handled in the Dependencies/import packages field if edited using Eclipse plugin manifest editor.

Import-Package: org.adempiere.process,
 org.adempiere.util

Publish a service

In activator's start method:

	public void start(BundleContext context) throws Exception {
		Dictionary<String, Object> props=new Hashtable<String, Object>();
		props.put("name", "org.myorg.MyProcessClassName");
		context.registerService(ProcessCall.class.getName(),
				new MyProcess(), props);
	}

If the name parameter is used then the ClassByNameUtil (in ADempiere) will find this class on the given name instead of the class's real name.


Changes made to the source code

  1. replace class.forName(name) constructions throughout the code with ClassLoaderUtil.loadClass(name). It is imperative as the few lines of class loading n-plicates code all around the project. This util handles OSGI extension mechanisms _and_ class.forName mechanism. OSGI class loading and later extension mechanisms can then be integrated at a single point.
  2. Hook OSGI startup to server and client startup.
  3. Include the modified apache felix Osgi framework jar into the project.
  4. Add a plugin autoloader funcionality to OSGI that scans a directory for new plugins, so installing a plugin does not require hacking with configuration files.
  5. Add a MANIFEST.MF file to the project with "Export-Package: " tag. This way osgi plugins in Eclipse workspace will be able to resolve dependencies set as packages to the ADempiere project. This package export should be added to each separate project too. As I use single project workspace I could not do that work.

Installation

Dev Environment

  • Install Adempiere from trunk
  • Apply adempiere_osgi_patch.txt from here (several changes required since trunk has evolved... I will provide an updated version shortly)
  • Checkout [1] via svn as an eclipse project
  • Build it via ant (eg from within eclipse) - build/felixMod.jar is created
  • Move build/felixMod.jar to tools (is this required?)
  • Move build/felixMod.jar your jboss/server/adempiere/deploy/adempiere.ear/lib (create the lib dir).

Build a plugin

  • Create an eclipse plugin project: File/New/Other... then Plugin Dev/Plugin Project, then OSGi Framework other, then next, then eg use Hello World bundle as a start
  • Edit MANIFEST.MF: Under dependencies, add the packages: org.adempiere.{process,util},org.compiere.process
  • Edit Activator.java and enter your code
  • Export the project as Plugin-Development/Deployable plugins and fragments, then change directory to your Adempiere/util directory and press finish
  • if you want, rename util/plugins to util/dynPlugins to allow for hot deployment

Start your JBoss and watch out for the Messages:

  INFO  [STDOUT] fw started
  INFO  [STDOUT] OSGI Bundles directory: C:\workspace\adempiere\adempiere\adempiere\Adempiere\utils\plugins

Congrats - you're done. Change your plugin and watch its console output while re-deployed.

Plugins?

Just a few additional thoughts: What would plugins expect to be able to do?

  • On startup:
    • dictionary changes:
      • add tables, columns
      • add/change/remove windows, tabs, fields
    • add menue items
    • add processes
  • At runtime be called upon:
    • user login/logout
    • Open Window/Tab
    • new/change/delete record
    • callout triggered
    • process triggered
    • report triggered
    • Workflow?

See Also