Powered By Blogger

Jun 20, 2014

Writing a Custom Mediator - UI Component


When considering the UI component there are three main classes as listed below

  • DataMapperMediator
  • DataMapperMediatorActivator
  • DataMapperMediatorService

DataMapperMediator


In this class both serialize method and build method are included in the DataMapperMediator UI class. This class can be found in org.wso2.carbon.mediator.datamapper.ui package and this should inherit from org.wso2.carbon.mediator.service.ui.AbstractMediator.


serialize method is similar to serializeSpecificMediator method in DataMapperMediatorSerializer class in backend component and build method is similar to createSpecificMediator method in DataMapperMediatorFactory class in backend component.


public class DataMapperMediator extends AbstractMediator {
    public String getTagLocalName() {
    }
    public OMElement serialize(OMElement parent) {
    }
    public void build(OMElement omElement) {
    }
}

DataMapperMediatorService

DataMapperMediatorService is the class which implements the required settings of the UI. Every Mediator Service should inherit the org.wso2.carbon.mediator.service.AbstractMediatorService class.

public class DataMapperMediatorService extends AbstractMediatorService {

    public String getTagLocalName() {
        return "datamapper";
    }

    public String getDisplayName() {
        return "DataMapper";
    }

    public String getLogicalName() {
        return "DataMapperMediator";
    }

    public String getGroupName() {
        return "Transform";
    }

    public Mediator getMediator() {
        return new DataMapperMediator();
    }
}


DataMapperMediatorActivator

Unlike other Carbon bundles where Bundle Activator is defined in the backend bundle, in a mediator class, the Bundle Activator is defined in the  UI bundle. Mainly the Bundle Activator should inherit the org.osgi.framework.BundleActivator class and should implement start and stop methods. 

public class DataMapperMediatorActivator implements BundleActivator {

    private static final Log log = LogFactory.getLog(DataMapperMediatorActivator.class);

    /**
     * Start method of the DataMapperMediator
     */
    public void start(BundleContext bundleContext) throws Exception {

        if (log.isDebugEnabled()) {
            log.debug("Starting the DataMapper mediator component ...");
        }

        bundleContext.registerService(
                MediatorService.class.getName(), new DataMapperMediatorService(), null);

        if (log.isDebugEnabled()) {
            log.debug("Successfully registered the DataMapper mediator service");
        }
    }

    /**
     * Terminate method of the DataMapperMediator
     */
    public void stop(BundleContext bundleContext) throws Exception {
        if (log.isDebugEnabled()) {
            log.debug("Stopped the DataMapper mediator component ...");
        }
    }
}

Also the edit-mediator.jsp JSP located in the resources package in org.wso2.carbon.mediator.datamapper.ui component and update-mediator.jsp JSP adjacent to the edit-mediator.jsp JSP are used to handle the changes made on UI.


You can find the source of the UI component at [1]

[1] https://github.com/sohaniwso2/FinalDMMediator/tree/master/datamapper/org.wso2.carbon.mediator.datamapper.ui

Writing a Custom Mediator - Backend Component

When considering the backend component three main classes can be identified as listed below
  • DatamapperMediator
  • DataMapperMediatorFactory
  • DataMapperMediatorSerializer

DataMapperMediatorFactory

Mediator are created using the Factory design pattern, therefore mediator should have a Mediator factory class. When considering the DataMapperMediator the class is org.wso2.carbon.mediator.datamapper.config.xml.DataMapperMediatorFactory which contains all the code relevant to the mediator. Basically this Factory class used to generate the mediator based on the XML specification of the mediator in the ESB sequence. In here the configuration information is extracted from the XML and creates a mediator based on that configuration.

Below method takes the XML as an OMElement and returns the relevant Mediator.


 protected Mediator createSpecificMediator(OMElement element,
   Properties properties) {

  DataMapperMediator datamapperMediator = new DataMapperMediator();

  OMAttribute configKeyAttribute = element.getAttribute(new QName(
    MediatorProperties.CONFIG));
  OMAttribute inputSchemaKeyAttribute = element.getAttribute(new QName(
    MediatorProperties.INPUTSCHEMA));
  OMAttribute outputSchemaKeyAttribute = element.getAttribute(new QName(
    MediatorProperties.OUTPUTSCHEMA));
  OMAttribute inputTypeAttribute = element.getAttribute(new QName(
    MediatorProperties.INPUTTYPE));
  OMAttribute outputTypeAttribute = element.getAttribute(new QName(
    MediatorProperties.OUTPUTTYPE));

  /*
   * ValueFactory for creating dynamic or static Value and provide methods
   * to create value objects
   */
  ValueFactory keyFac = new ValueFactory();

  if (configKeyAttribute != null) {
   // Create dynamic or static key based on OMElement
   Value configKeyValue = keyFac.createValue(
     configKeyAttribute.getLocalName(), element);
   // set key as the Value
   datamapperMediator.setConfigurationKey(configKeyValue);
  } else {
   handleException("The attribute config is required for the DataMapper mediator");
  }

  if (inputSchemaKeyAttribute != null) {
   Value inputSchemaKeyValue = keyFac.createValue(
     inputSchemaKeyAttribute.getLocalName(), element);
   datamapperMediator.setInputSchemaKey(inputSchemaKeyValue);
  } else {
   handleException("The attribute inputSchema is required for the DataMapper mediator");
  }

  if (outputSchemaKeyAttribute != null) {
   Value outputSchemaKeyValue = keyFac.createValue(
     outputSchemaKeyAttribute.getLocalName(), element);
   datamapperMediator.setOutputSchemaKey(outputSchemaKeyValue);
  } else {
   handleException("The outputSchema attribute is required for the DataMapper mediator");
  }

  if (inputTypeAttribute != null) {
   datamapperMediator.setInputType(inputTypeAttribute
     .getAttributeValue());
  } else {
   handleException("The input DataType is required for the DataMapper mediator");
  }

  if (outputTypeAttribute != null) {
   datamapperMediator.setOutputType(outputTypeAttribute
     .getAttributeValue());
  } else {
   handleException("The output DataType is required for the DataMapper mediator");
  }

  processAuditStatus(datamapperMediator, element);

  return datamapperMediator;
 }

Also in order to define the QName of the XML of the specific mediator we use below code snippet and have used the method getTagQName() to get the QName.

private static final QName TAG_QNAME = new QName(
   XMLConfigConstants.SYNAPSE_NAMESPACE,
   MediatorProperties.DATAMAPPER);


DataMapperMediatorSerializer

Mediator Serializer does the reverse of the Mediator Factory class where is creates the XML, related to the mediator from the Mediator class. When considering the DataMapperMediator the relevant class is org.wso2.carbon.mediator.datamapper.config.xml.DataMapperMediatorSerializer

Below method has used to do the conversion

protected OMElement serializeSpecificMediator(Mediator mediator) {
if (!(mediator instanceof DataMapperMediator)) {
handleException("Unsupported mediator passed in for serialization :"
+ mediator.getType());
}
DataMapperMediator dataMapperMediator = (DataMapperMediator) mediator;
OMElement dataMapperElement = fac.createOMElement(
MediatorProperties.DATAMAPPER, synNS);
if (dataMapperMediator.getConfigurationKey() != null) {
// Serialize Value using ValueSerializer
ValueSerializer keySerializer = new ValueSerializer();
keySerializer.serializeValue(
dataMapperMediator.getConfigurationKey(),
MediatorProperties.CONFIG, dataMapperElement);
} else {
handleException("Invalid DataMapper mediator. Configuration registry key is required");
}
if (dataMapperMediator.getInputSchemaKey() != null) {
ValueSerializer keySerializer = new ValueSerializer();
keySerializer.serializeValue(
dataMapperMediator.getInputSchemaKey(),
MediatorProperties.INPUTSCHEMA, dataMapperElement);
} else {
handleException("Invalid DataMapper mediator. InputSchema registry key is required");
}
if (dataMapperMediator.getOutputSchemaKey() != null) {
ValueSerializer keySerializer = new ValueSerializer();
keySerializer.serializeValue(
dataMapperMediator.getOutputSchemaKey(),
MediatorProperties.OUTPUTSCHEMA, dataMapperElement);
} else {
handleException("Invalid DataMapper mediator. OutputSchema registry key is required");
}
if (dataMapperMediator.getInputType() != null) {
dataMapperElement.addAttribute(fac.createOMAttribute(
MediatorProperties.INPUTTYPE, nullNS,
dataMapperMediator.getInputType()));
} else {
handleException("InputType is required");
}
if (dataMapperMediator.getOutputType() != null) {
dataMapperElement.addAttribute(fac.createOMAttribute(
MediatorProperties.OUTPUTTYPE, nullNS,
dataMapperMediator.getOutputType()));
} else {
handleException("OutputType is required");
}
saveTracingState(dataMapperElement, dataMapperMediator);
return dataMapperElement;
}
DatamapperMediator
This is the main class used for the mediation purpose. Since the meditor is intended to interact with the message context you should include the below method
public boolean isContentAware() {
return true; }
mediate method is the most important method where it takes the MessageContext of the message, which is unique to an each request passing through the mediation sequence. The return boolean value should be true if the mediator was successfully executed and false if not.
Please find the source of the backend component at [1]


Introduction - Custom Mediators for WSO2 ESB


This provides an introduction to custom mediatos for WSO2 ESB and I have referred the DataMapperMediator as the custom mediator for describing the process. 


Bundles Used

The developer can include the created custom mediator to ESB as a pluggable component but developer just need to develop the functionality and does not need to worry about how to plug the component to the ESB.  Below is the structure of a mediator component. 

── org.wso2.carbon.mediator.datamapper
│       ├── pom.xml
│       └── src
│           └── main
│               ├── java
│               │   └── org
│               │       └── wso2
│               │           └── carbon
│               │               └── mediator
│               │                   └── datamapper
│               │                       ├── DatamapperMediator.java
 |                 |                        └── DataMapperHelper.java
 |                 |                        └── DataMapperCacheContext.java
 |                 |                        └── CacheResources.java
 |                 |                        └── SOAPMessage.java
│               │                       └── config
 |                 |                         |   └── xml
│               │                        |        ├── DataMapperMediatorFactory.java
│               │                        |        └── DataMapperMediatorSerializer.java
 |                 |                         |        └── MediatorProperties.java
 |                 |                        └── datatypes
 |                 |                               └── CSVWriter.java
 |                 |                               └── InputOutputDataTypes.java
 |                 |      └── JSONWriter.java
 |                 |                            └── OutputWriter.java
 |                 |                              └── OutputWriterFactory.java
 |                 |                              └── XMLWriter.java
│               └── resources
│                   └── META-INF
│                       └── services
│                           ├── org.apache.synapse.config.xml.MediatorFactory
│                           └── org.apache.synapse.config.xml.MediatorSerializer
├── org.wso2.carbon.mediator.datamapper.ui
│       ├── pom.xml
│       └── src
│           └── main
│               ├── java
│               │   └── org
│               │       └── wso2
│               │           └── carbon
│               │               └── mediator
│               │                   └── datamapper
│               │                       └── ui
│               │                           ├── DataMapperMediator.java
│               │                           ├── DataMapperMediatorActivator.java
│               │                           └── DataMapperMediatorService.java
│               └── resources
│                   ├── org
│                   │   └── wso2
│                   │       └── carbon
│                   │           └── mediator
│                   │               └── datamapper
│                   │                   └── ui
│                   │                       └── i18n
│                   │                           ├── JSResources.properties
│                   │                           └── Resources.properties
│                   └── web
│                       └── datamapper-mediator
│                           ├── docs
│                           │   ├── images
│                           │   └── userguide.html
│                           ├── edit-mediator.jsp
│                           ├── images
│                           ├── js
│                           └── update-mediator.jsp
└── pom.xml


UI Bundle : This adds the UI functionality which can be used in the design view of the ESB management console as shown below. 




Backend bundle - This handles the mediation related backend processing. 

Next blog post describes the process of writing the custom mediator.....

Jun 19, 2014

Time Series Analysis with WSO2 Complex Event Processor

A time series is a sequence of observations recorded at regular intervals one after the other. Time series analysis accounts for the fact that data points taken over time may have a structure like trend, seasonal, cyclical, or irregular. Regression can be used to forecast purposes where it is all about predicting Y values for a given set of predictors. 

Please refer the article at [1] which discusses how WSO2 Complex Event Processor (CEP) can be used to carry out a time series analysis.

[1] http://wso2.com/library/articles/2014/06/time-series-analysis-with-wso2-complex-event-processor/