Showing posts with label OSGi. Show all posts
Showing posts with label OSGi. Show all posts

Wednesday, January 2, 2013

Publish WSO2 Governance Registry Data to WSO2 BAM


This post will explain how to publish WSO2 G-Reg generated events to WSO2 BAM server. In other words, this is a custom data publisher for G-Reg/BAM.


   

Pre-requisites

- Install WSO2 Business Activity Monitor (BAM 2.0.0)
- Install WSO2 Governance Registry(G-Reg 4.5.3)

What needs to done:
a) Configure WSO2 BAM to accept events generated from WSO2 G-Reg
b) Publish events generated from G-Reg to the BAM event listeners.

How to:
- To achieve (a), we need to install a relevant Toolbox to BAM.
(A BAM Toolbox is an installable archive which contains stream definitions, dashboard components and analytics for WSO2 Business Activity Monitor. KPI_Registry_Activity.tbox is a such pre-built BAM Toolbox based on the KPI Monitoring sample of WSO2 BAM. Further you can read the KPI Monitoring sample of WSO2 BAM to learn how to make changes to this BAM Toolbox or create your own.)

 - To achieve (b), in WSO2 Carbon Kernel, we are given an extension point to collect stats from a running carbon server. To accomplish this, we need to write a class that extends StatisticsCollector interface and override the collect method such that it will publish the collected event to WSO2 BAM.  

I hope now you got a brief understanding of how to achieve this goal. So lets figure out what needs to be done to achieve (a) and (b)  in detail.


a) Configure WSO2 BAM to accept events generated from WSO2 G-Reg

- Download the KPI_Registry_Activity.tbox .
- Start WSO2 BAM server and login as admin (username - admin password -admin).
- In BAM management console go to BAM Toolbox > Custom Toolbox   select the downloaded toolbox from the file system and click Install.

Now you have the tool box installed which awaits and listens to the events coming through its tcp event listener port.

b)  To add a stat collector which publish the collected stats to WSO2 BAM, we need to write a custom OSGi bundle which register the statistic collector service at bundle startup.

To write a new OSGi bundle we can reuse the greg handler sample code. Find the handler sample in
GREG_HOME/samples/handler.

There add a new class called RegistryStatCollectorServiceComponent under the package  org.wso2.carbon.registry.samples.statistics.

In the sample pom file, you need to do the following changes to make the code work.
Add following dependencies to the pom.


    org.wso2.carbon
    org.wso2.carbon.databridge.agent.thrift
    4.0.1


    org.wso2.carbon
    org.wso2.carbon.databridge.commons
    4.0.0


Add the following plugin.

    org.apache.felix
    maven-scr-plugin


Commet-out the following exclusions in the pom file.



Now edit the previously created RegistryStatCollectorServiceComponent class as follows.
package org.wso2.carbon.registry.samples.statistics;

 

import org.osgi.framework.ServiceRegistration;

import org.osgi.service.component.ComponentContext;

import org.wso2.carbon.context.CarbonContext;
import org.wso2.carbon.databridge.agent.thrift.Agent;
import org.wso2.carbon.databridge.agent.thrift.DataPublisher;
import org.wso2.carbon.databridge.agent.thrift.conf.AgentConfiguration;
import org.wso2.carbon.databridge.commons.Event;
import org.wso2.carbon.databridge.commons.exception.NoStreamDefinitionExistException;
import org.wso2.carbon.registry.core.service.RegistryService;
import org.wso2.carbon.registry.core.statistics.StatisticsCollector;
import org.wso2.carbon.registry.core.utils.RegistryUtils;
import org.wso2.carbon.utils.NetworkUtils;
 

/**

 * @scr.component name="org.wso2.carbon.registry.samples.statistics" immediate="true"

 * @scr.reference name="registry.service" interface="org.wso2.carbon.registry.core.service.RegistryService"

 * cardinality="1..1" policy="dynamic" bind="setRegistryService" unbind="unsetRegistryService"

 */

public class RegistryStatCollectorServiceComponent {

 

    public static final String REGISTRY_ACTIVITY_STREAM = "org.wso2.bam.registry.activity.kpi";

    public static final String VERSION = "1.0.0";

 

    private ServiceRegistration serviceRegistration;

 

    protected void activate(ComponentContext context) {

        serviceRegistration = context.getBundleContext().registerService(

                StatisticsCollector.class.getName(), new StatisticsCollector() {

            public void collect(Object... objects) {

                try {

                    // Create Data Publisher

                    RegistryUtils.setTrustStoreSystemProperties();

                    DataPublisher dataPublisher = new DataPublisher(

                            "tcp://" + NetworkUtils.getLocalHostname() + ":7612", "admin", "admin",

                            new Agent(new AgentConfiguration()));

 

                    // Find Data Stream

                    String streamId;

                    try {

                        streamId = dataPublisher.findStream(REGISTRY_ACTIVITY_STREAM, VERSION);

                    } catch (NoStreamDefinitionExistException ignored) {

                        streamId = dataPublisher.defineStream("{" +

                                "  'name':'" + REGISTRY_ACTIVITY_STREAM + "'," +

                                "  'version':'" + VERSION + "'," +

                                "  'nickName': 'Registry_Activity'," +

                                "  'description': 'Registry Activities'," +

                                "  'metaData':[" +

                                "          {'name':'clientType','type':'STRING'}" +

                                "  ]," +

                                "  'payloadData':[" +

                                "          {'name':'operation','type':'STRING'}," +

                                "          {'name':'user','type':'STRING'}" +

                                "  ]" +

                                "}");

                    }

 

                    if (!streamId.isEmpty()) {

                        // Publish Event to Stream

                        dataPublisher.publish(new Event(

                                streamId, System.currentTimeMillis(),

                                new Object[]{"external"}, null, new Object[]{

                                Thread.currentThread().getStackTrace()[3].getMethodName(),

                                CarbonContext.getCurrentContext().getUsername()}));

                        dataPublisher.stop();

                        System.out.println("Successfully Published Event");

                    }

 

                } catch (Exception e) {

                    e.printStackTrace();

                }

            }

        }, null);

    }

 

    protected void deactivate(ComponentContext context) {

        serviceRegistration.unregister();

    }

 

    protected void setRegistryService(RegistryService registryService) {

        // The Maven SCR Plugin Needs These

    }

 

    protected void unsetRegistryService(RegistryService registryService) {

        // The Maven SCR Plugin Needs These

    }

}

- Now go to  REG_HOME/ samples/handler/src and do a maven clean install to build the project. Once done inside the target folder of the sample, you can find the updated jar file.

- Copy the jar  org.wso2.carbon.registry.samples.handler-4.5.3.jar in to  REG_HOME/repository/components/dropins folder.

- Go to REG_HOME/repository/conf/carbon.xml and change the offset value to 1 as follows.
- Now start the server and do registry operations such as adding WSDLs/Services /Resources and etc (these actions will create events from WSO2 G-Reg side and publish them to WSO2 BAM) and check the WSO2 BAM  Gadget Portal and you will find the operations you did published as events on WSO2 BAM dashboard.

For more info:visit WSO2 G-Reg wiki docs - http://docs.wso2.org/wiki/display/Governance453/WSO2+Governance+Registry+Documentation

Thursday, December 15, 2011

Using WSO2 Registry Eventing for notification through an Executor

We will gonna do this through an Executor associated to a registry LC (Life Cycle) .

What we gonna do: We are going to create a simple registry LC associate a resource to it and write an Executor class which notify via email when that resource promote to its next state. To send email we use registry eventing functionality.

Executors are one of the facilitators which helps to extend the WSO2 GReg functionality. Here an Executor is associated to a registry life cycle. Life Cycle is basically a set of pre-defined states which can be associated to a registry Resource and allows that associated resource to evolve through that LC as defined. There users can basically do "Promote" and "Demote" a resource from one state to another.

You can write your own WSO2 GReg Executor class by implementing the org.wso2.carbon.governance.registry.extensions.interfaces.Execution interface. There you can override the execution method.

public class LCStateChangeNotificationExecutor implements Execution {
public void init(Map map) { }
public boolean execute(RequestContext requestContext, String s, String s1) {
// DO what you want to do when the resource change its LC state. Here we try to send an email notification to a subscriber.
sendEmail(requestContext);
return true;
}
}
Now lest see how to achieve the notification through registry eventing. Here we create a ResourceUpdateEvent and send that event to a subscriber resource which is a dummy resource where we manually subscribed to its update mode via my email. ( when state change happens to a resource, the executor gets HIT and it will send a Update Event to a dummy resource to which user is subscribed via email.)

UserRegistry registry registry = (UserRegistry) requestContext.getSystemRegistry();
ResourceUpdatedEvent resourceUpdatedEvent = new ResourceUpdatedEvent(CUSTOM_EMAIL_MESSAGE);

resourceUpdatedEvent.setResourcePath(SUBSCRIPTION_RESOURCE_PATH);
if (registry != null) {
resourceUpdatedEvent.setTenantId(registry.getTenantId());
}


Now Event instance is ready and only needs to sent it through registry NotificationService.

 org.wso2.carbon.registry.common.eventing.NotificationService.notify(resourceUpdatedEvent);

NOTE: Notification service is exposed as an OSGi service where that service included component class has getters and setters so that you can call the getRegistryNotificationService() method on that class which will return the NotificationService set by the eventing service.


Then you are done with the Executor class. Please add an entry inside to a LC state from which you want the Executor to be HIT when state change takes place.

So to define reference to Executor.
Now we have to define the Executor in our LC. Find the EventLifeCycle.xml.xml LC file under GREG_HOME/samples/sportmeet-scenario/src/resources.
(In the EventLifeCycle.xml.xml file we have added an entry for our executor inside the first state, because here, we want the executor to hit as soon as LC state promote from its initial state).
Here is the sample LC XML.
<aspect name="WSO2SportMeetEventHandler" class="org.wso2.carbon.governance.registry.extensions.aspects.DefaultLifeCycle">
<configuration type="literal">
<lifecycle>
<scxml xmlns="http://www.w3.org/2005/07/scxml"
version="1.0"
initialstate="Create">
<state id="Create">
<datamodel>
<data name="checkItems">
<item name="Created the Event" forEvent="Promote">
</item>
<item name="Announced the Event" forEvent="Promote">
</item>
</data>
<data name="transitionValidation">
<validation forEvent="Promote"
class="org.wso2.carbon.registry.samples.sportmeet.validators.PromoteValidator">
</validation>
</data>
<data name="transitionExecution">
<execution forEvent="Promote"
class="org.wso2.carbon.registry.samples.sportmeet.executors.LCStateChangeNotificationExecutor">
</execution>
</data>
</datamodel>
<transition event="Promote" target="Edit"/>
</state>
<state id="Edit">
<datamodel>
<data name="checkItems">
<item name="Add participants" forEvent="Promote">
</item>
<item name="Collect participant details" forEvent="Promote">
<validations>
<validation forEvent="Promote"
class="org.wso2.carbon.registry.samples.sportmeet.validators.ParticipantValidator">
</validation>
</validations>
</item>
</data>
<data name="transitionValidation">
<validation forEvent="Promote"
class="org.wso2.carbon.registry.samples.sportmeet.validators.PromoteValidator">
</validation>
</data>
<data name="transitionExecution">
<execution forEvent="Promote"
class="org.wso2.carbon.registry.samples.sportmeet.executors.LCStateChangeNotificationExecutor">
</execution>
</data>
</datamodel>
<transition event="Promote" target="Review"/>
<transition event="Demote" targedt="Create"/>
</state>
<state id="Review">
<datamodel>
<data name="checkItems">
<item name="Not eligible participants removed" forEvent="Promote">
</item>
<item name="Extra participants removed(if maximum number exceeds)" forEvent="Promote">
</item>
<item name="All the participhants are not eligible for the Event" forEvent="Demote">
</item>
</data>
<data name="transitionExecution">
<execution forEvent="Promote"
class="org.wso2.carbon.registry.samples.sportmeet.executors.LCStateChangeNotificationExecutor">
</execution>
</data>
<data name="transitionValidation">
<validation forEvent="Promote"
class="org.wso2.carbon.registry.samples.sportmeet.validators.PromoteValidator">
</validation>
</data>
</datamodel>
<transition event="Promote" target="Accept"/>
<transition event="Demote" target="Edit"/>
</state>
<state id="Accept">
<transition event="Demote" target="Review"/>
<datamodel>
<data name="transitionExecution">
<execution forEvent="Promote"
class="org.wso2.carbon.registry.samples.sportmeet.executors.LCStateChangeNotificationExecutor">
</execution>
</data>
</datamodel>
</state>
</scxml>
</lifecycle>
</configuration>
</aspect>



For the notification part you must enable the axis2 TransportSender in GREG_HOME/reposiroty/conf/axis2.xml.


1. Now everything is ready and start the server.

2. Go to admin console.

3.Add a resource (which you provided as SUBSCRIPTION_PATH) and subscribe to it via email under update resource mode.

4 . Now add another resource and associate the service LC to it and do a promote.

5 When promoted, an email notification will be sent to your previously
subscribed email address.


References: