NF9 OSGi New Event Handling Annotation
Feature: OSGi New Event Handling Annotation
Goal: Development
Description: Implement a new thread safe, annotation based osgi event handling mechanism as an alternative to the existing AbstractEventHandler approach.
Usage
To listen to before change of C_BPartner (MBPartner), create new ModelEventDelegate subclass and use "@BeforeChange" for before change event (method name is insignificant here).
public class MyBpBeforeChangeDelegate extends ModelEventDelegate<MBPartner> { public MyBpBeforeChangeDelegate(MBPartner po, Event event) { super(po, event); } @BeforeChange public void beforeChange() { MBPartner bp = getModel(); //perform before change actions ... Env.setContext(Env.getCtx(), getClass().getName(), bp.toString()); } }
Developer can use one of the following approach to register the event delegate class:
1. At plugin Activator start method, register the event delegate class.
public void start(BundleContext context) throws Exception { ModelEventHandler<MBPartner> handler = new ModelEventHandler<MBPartner>(MBPartner.class, MyBpBeforeChangeDelegate.class, (bp, event) -> new MyBpBeforeChangeDelegate(bp, event)); Core.getEventManager().register(handler); }
2. Create an osgi component, at the bind method for the IEventManager service.
public void bindService(IEventManager eventManager) { this.eventManager = eventManager; this.handler = new ModelEventHandler<MBPartner>(MBPartner.class, MyBpBeforeChangeDelegate.class, (po, event) -> new MyBpBeforeChangeDelegate(po, event)); eventManager.register(handler); }
3. Annotate your class with EventTopicDelegate and one of ModelEventTopic, ImportEventTopic or ProcessEventTopic annotation. Create a new OSGi component that extends the AnnotationBasedEventManager class (with service = {}).
@EventTopicDelegate @ModelEventTopic(modelClass = MInOut.class) public class AutoProduceEventDelegate extends ModelEventDelegate<MInOut> { ... @BeforeComplete public void onBeforeComplete() { ... } }
Event handlers and Event delegates
- PO and FactValidate - ModelEventHandler and ModelEventDeleagete
- Import (I_BPartner, I_Product, etc) - ImportEventHandler and ImportEventDelegate
- Process - ProcessEventHandler and ProcessEventDelegate
- Others - SimpleEventHandler and EventDelegate (and the optional, convenient delegate class of RequestSendEmailEventDelegate and AfterLoginEventDelegate)
Annotations
- There’s annotattion created for all predefined event delegate (“@AfterLogin”, “@AfterProcess”, “@BeforeComplete”, “@AfterImport”, etc)
- Model/PO event annotation at org.adempiere.base.event.annotations.po
- Process event annotation at org.adempiere.base.event.annotations.process
- Import event annotation at org.adempiere.base.event.annotations.imp
- Document event annotation at org.adempiere.base.event.annotations.doc
- Base classes and Other event annotation at org.adempiere.base.event.annotations
- IDEMPIERE-5019 added EventTopicDelegate, ModelEventTopic, ImportEventTopic and ProcessEventTopic class level annotation.
- Event delegate class with EventTopicDelegate annotation will be discovered and register by OSGi Component that extends the AnnotationBasedEventManager class (Doesn't have to provide any service, i.e service = {}).
- For core, annotate your event delegate class and place it in the org.adempiere.base.event.delegate package.
- ModelEventTopic, ImportEventTopic and ProcessEventTopic annotation is to define the parameter needed for each event type (for e.g, model class for model event type).
- Example from org.adempiere.base.event.delegate.AutoProduceEventDelegate:
@EventTopicDelegate @ModelEventTopic(modelClass = MInOut.class) public class AutoProduceEventDelegate extends ModelEventDelegate<MInOut> { public AutoProduceEventDelegate(MInOut po, Event event) { super(po, event); } @BeforeComplete public void onBeforeComplete() { MInOut mInOut = getModel(); if (mInOut.isSOTrx()) { String msg = processShipment(mInOut); if (msg != null) throw new RuntimeException (msg); } } ... }
Technical Info: IDEMPIERE-4694, IDEMPIERE-5019