Developing Plug-Ins - Model Events
Goal of this how-to
The goal of this how-to is to show how you would develop a EventHandler in your own plug-in so you can share your plug-in to others with all necessary information needed to get it running.
Prerequisites
Before you start developing plug-ins, you should take a look at Developing Plug-Ins without affecting trunk and Get your Plug-In started to get a good starting point.
tl;dr
https://www.youtube.com/watch?v=zc_Ye8WZ-jc
The workflow
Overview
Build on top of the OSGi Event Admin Framework, the iDempiere platform enable the use of OSGi event handler to replace the use of AD_ModelValidator table and the ModelValidator interface. The IEventManager service is provided by the org.adempiere.base bundle.
Since iDempiere 9: Event Annotation
If you're running iDempiere 9 or higher, you can use the new process factory and annotations approach. You can find how to do it here: NF9 OSGi New Process Factory.
Create The EventHandler Class
To register a new event handler, you need to know the model event topic name, create a new java class and register that class as an OSGi component. The model event topics publish by iDempiere is define in the IEventTopics interface ( Note that your bundle and other extension bundle can publish additional event topics ). As required by the OSGI Event Admin framework, your event handler class must implement the OSGi EventHandler interface. However, to ease event handler coding, iDempiere include the AbstractEventHandler class for your event handler class to extend. One of the benefit having your event handler class extend AbstractEventHandler is you can stop the event by simply throw RuntimeException in the doEventHandler method.
If your class extends AbstractEventHandler, you needs to do the 2 step below at your class:
- Override the initialize() method to register the table event that your class are interested at.
- Override the doHandleEvent(Event event) method to do your work when the registered event occur.
If you need to show the user an error message, you can call addErrorMessage() instead of throwing an exception.
Create Component Definition
NOTE: If you use Eclipse Oxigen or a newer version, you can use annotations instead of creating the component definition manually. Read more about it here
Your event handler received the IEventManager service through the OSGi dynamic service framework. To do that, you have to declare your event handler class as an OSGi component.
First, create a new folder in your bundle to store the OSGi component definition file ( an xml file ). The standard convention for this is to name that folder as "OSGI-INF". Right click on the OSGI-INF folder, you select new Component Defintion on the context menu.
The component definition editor have 3 tab, Overview, Services and Source. The Source tab is the raw xml source. At the Overview tab, you have to define the component name and fill the class field with your event handler class name. The component name must be unique within the whole system, the recommendation is to use all lower case qualified by the java package name of the component class.
At the services tab, you have to add IEventManager service as one of the entry in the Referenced Services list.
In the ReferencedService dialog, you refer the service using the service's fully qualified java interface name: org.adempiere.base.event.IEventManager ( the bindEventManager and unbindEventManager method is from the AbstractEventHandler class ).
The Eclipse component editor will save the component definition as a xml file that you can give it an arbitrary name ( example component.xml ) At runtime, the OSGi dynamic service framework will auto inject the IEventManager service to your event handler when the IEventManager service have been started.
Also, the Eclipse component editor should auto add the component definition reference to your plugin's MANIFEST.MF file. Note that if you have many component definition file, you can use *.xml instead of including all the names there.
Finally, you should turn on the "Activate this plugin when class is loaded" option.
Useful Tutorial Links
- There is a video in Youtube that shows how to create component.xml. It is part of the series in the playing list.