Skip to Content
Author's profile photo Sebastian Steinhauer

SAP BusinessObjects Event Insight – Pushing events with custom adapters.

SAP BusinessObjects Event Insight is officially in ramp-up
& and ready to be used (congratulations to Julio Navas and the team!).  After the installation SAP BusinessObjects
Event Insight shows up in your landscape with a selection of generic adapters.
RFCs, databases and Web services can easily be used to connect to your system
landscape. But what if the system is more exotic or the use case requires a
very specific approach to event production?  Or what if you just want to see what it
happening under the hood?

SAP BusinessObjects Event Insight is a solution for event
processing networks, build strictly following componentization and distribution
principles. The fundamental architecture used is OSGi to manage component
lifecycles. The message transfer is handled transparent to the publisher which
only calls a proxy for each subscriber once.

In this blog post I will describe the fundamental idea
behind OSGi and how it is used to develop SAP BusinessObjects Event Insight
producers as well as how a publisher actually fires of events to the
subscribers. Since I am describing non certifiable, potentially unstable interfaces
please note that developed custom adapters are not supported. This blog post is based on a pre-release version of Event Insight, interfaces might have changed.

Vanilla OSGi</p>

<p>Since eclipse itself is build on OSGI it comes with a

specific project type for OSGI bundles called Plugin-Project.  Also not that currently Event Insight plugins

need to have an ID starting with “”.</p>

<p>An OSGi bundle has a main entry point – the Activator – a component which

implements the BundleActivator

interface. In general activator classes looks like this:</p>

<pre>import org.osgi.framework.BundleActivator;<br />import org.osgi.framework.BundleContext;<br /><br />public class SampleBundle implements BundleActivator {<br /><br />    public void start(BundleContext bc) {<br />        System.out.println(“Hello world”);<br />    }<br /><br />    public void stop(BundleContext bc) {<br />        System.out.println(“Goodbye world”);  <br />    }



<p>The activator is described in a manifest file, which has to

be included in the final bundle (a jar). </p>

<p>*OSGi and Event


<p>An Event Insight bundle is usually implemented by extending LEActivator – which adds some

additional service registration features to the OSGi framework.  This registration contains a list of service factories

which can be used to create multiple instances of services; also handling of

dependencies between producers is supported.</p>

<pre><br />public class Activator extends LEActivator {<br /><br />    static BundleContext bc;<br /><br />    public Activator() {<br />        super();<br />        services = new Hashtable<LEManaged, LEServiceConfig>();<br />        // creating a factory<br />        SamplePublisherFactory pubFactory = new SamplePublisherFactory();<br />        // creating it’s configuration<br />        LEServiceConfig pubServiceConfig = new LEServiceConfig();<br />        // factory exposes itself as a OSGi ManagedServiceFactory<br />        pubServiceConfig<br />                .setRegistrationInterfaceClassNames(new String[] { ManagedServiceFactory.class<br />                        .getName() });<br />        // this id has to be unique <br />        pubServiceConfig.setServicePid(“”);<br />        // set required dependency        <br />        pubServiceConfig.getRequiredServices().add(SamplePublisherFactory.PUBLIHSER_DEPENDENCY);<br />        // turn on the instance support<br />        pubServiceConfig.setInstanceSupport(true);<br />        // add service factory<br />        services.put(pubFactory, pubServiceConfig);<br /><br />    }<br /><br />    @Override<br />    public void start(BundleContext context) throws Exception {<br />        bc = context;<br />        super.start(context);<br />    }<br /><br />    @Override<br />    public void stop(BundleContext context) throws Exception {<br />        super.stop(context);<br />        bc = null;<br />    }<br /><br />}</pre>

<pre><br /></pre>

<p>You can see that Event Insight uses OSGi plus a set of

conventions to implement its bundles. The services that get registered in the

Bundle are actually factories, in this case a single publisher factory

(instance of SamplePublisherFactory).


<p>The Publisher Factory

The publisher factory extends LEAbstractManagedServiceFactory.
The primary purpose of the publisher factory is to create and handle instances
of Producers, which are wrapped in instances of LEEntitySimpleAdaptorWithSecureServices
, whenever createEntity() is

protected LEEntity createEntity(String entityId,
            Dictionary creationProperties) {

            return new LEEntitySimpleAdaptorWithSecureServices(Activator.bc, this,
                requiredRemoteServices, new StaticProducerAddressProvider()) {

As you can see the OSGi pattern is followed on publisher
factory level as well. Please note that here an additional state “waiting” is
introduced which is entered whenever a dependency is missing or removed. As you
can see from the above code segment, an instance of the SampleDataProducer is created, whenever the start() is called on the LEEntity returned by createEntity().


<p>The data producer extends Producer and does two important

things – it deploys a producer graph (usually only a single event type node): </p><pre><br />protected ParametersQueryGraph createGraph() {<br />        // Create a graph that represents event types that are produced by this producer<br />        QueryGraph queryGraph = new QueryGraphImpl();<br />        <br />        try {<br />            //load event type that represents a demo message from metadata repository<br />            sampleDataEventType = secServices.getMetaDataManipulator().loadEventTypeBy(“demo.SampleData”);<br />            //create event type node<br />            EventTypeNode node = new EventTypeNode(secServices.getMetaDataManipulator(), sampleDataEventType);<br />            //add it to the graph<br />            queryGraph.addQueryNode(node);<br />        } catch (RemoteException e) {<br />            log.error(e);<br />            return null;<br />        }<br />        <br />        return new ParametersQueryGraph(queryGraph, new HashMap<String, String>());<br />    }<br /></pre><p>and it creates instances of generators, which are finally the

components creating our events!</p><pre>    protected List<EventGenerator> createGenerators() {<br />        // create a simple data generator<br />        SampleDataGenerator generator = new SampleDataGenerator(sampleDataEventType);<br />        List<EventGenerator> generators = new LinkedList<EventGenerator>();<br />        generators.add(generator);<br />        return generators;<br />    }</pre><pre><br /></pre><p>*The actual Event


<p>So – just to recap for a second, going through 4 levels of

indirection: Every publisher factory has to realize LEAbstractMangedServicesFactory and returns instances

extending LEEntitySimpleAdapterWithSecureServices

which wrap realizations of Producer.

Every producer does contain at least on Generator which implements EventGenerator.</p><pre><br />public interface EventGenerator {<br />    EventType getEventType();<br /><br />    void startEventProduction(byte[] uid, CertPath certPath, QueryGraph fullGraph, QueryGraph notAcceptedGraph, List<QueryEventListener> listeners);<br /><br />    void stopEventProduction(byte[] uid);<br /><br />    void addQueryEventListener(byte[] uid, QueryEventListener queryEventListener);<br /><br />    void removeQueryEventListener(byte[] uid, QueryEventListener queryEventListener);<br />}</pre><p> </p><p>In this sample I am showing a lightweight generator that is

triggered periodically from a thread created in its parent class which

implements EventGenerator. Using

AbstractGenerator makes it super

easy to get going and arrive at working code quickly.</p>

<pre><br />public class SampleDataGenerator extends AbstractGenerator {<br /><br />    private String sampleContent = “Hello World!”;<br /><br />    private EventType eventType;<br /><br />    public SampleDataGenerator() {<br />        super();<br />    }<br /><br />    public SampleDataGenerator(EventType eventType) {<br />        super();<br />        this.eventType = eventType;<br />    }<br /><br />    public EventType getEventType() {<br />        return eventType;<br />    }<br /><br />    @Override<br />    //AbstractGenerator will call this method once per second and the generated event will be propagated to all subscribers<br />    protected QueryEvent createEvent(QueryGraph fullGraph,<br />            QueryGraph notAcceptedGraph) {<br />        //create event with a hard coded text<br />        Map<String, Object> contents = new HashMap<String, Object>();<br />        contents.put(“message”, new Random().nextInt() % 4);<br />        QueryEvent event = new MapEvent(contents, new Date());<br />        return event;<br />    }</pre><pre><br /></pre><p>In this case you can see that AbstractGenerator

actually handles the publishing of the events to the subscribers as well as the

handling of the subscribers. By implementing the EventGenerator

interface it is actually possible to control the publishing of events on a

per-event-per-subscriber level.</p>

<p>The actual event generation can be triggered through all

sorts of mechanisms, listening sockets, jetty servers listening to JSON

objects, or plain text http-post messages, JNI interactions with native

applications.  Whatever you can think of

you can build. </p>

<p>*AAAHH – I need to see


<p>Since this is a lot of code to digest and understand you can

download the sample bundle from code exchange (</p><p>I hope you will contribute to the project and help developing a full documentation with nice samples on how to best develop add-ons to SAP Event Insight. </p>

<p>The code exchange project will contain more information than just the four classes mentioned above,

the manifest. Please note that it is a work in progress and is currently driven as a side project.</p><p> </p>

<p>Next Steps

I hope to find some time in the near future to work with
early customers or partners on creating a more comprehensive whitepaper on a
sample integration project. If you have ideas or visions, please reach out to
me at any time.

Good luck building your own.

Assigned Tags

      Be the first to leave a comment
      You must be Logged on to comment or reply to a post.