Powered By Blogger

Jun 20, 2014

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]

No comments:

Post a Comment