uCosminexus Service Platform, Reception and Adapter Definition Guide
This section describes the sample program of the custom adapter that uses the custom adapter development framework.
With the sample program, create a custom adapter that receives the count increment request (increment) or the count decrement request (decrement) and invokes the counter service.
The following figure shows an overview of the custom adapter that invokes the counter service:
Figure B-2 Overview of the custom adapter that invokes the counter service
The counter service and the protocol converter of the custom adapter are as follows:
The counter service maintains the count.
The counter service of the sample program is a normal Java class but is viewed as a service. Therefore, the storage location of the counter service is the same JAR as the protocol converter.
The counter service provides the following three services:
The protocol converter invokes the counter service.
The protocol converter performs the following two operations:
The message formats used in the sample program are as follows:
Create a binary format definition file that takes a single binary integer with one-byte encoding. Specify the file name as BinaryRequest.fdx.
For details about how to create a binary format definition file, see 4.4 Creating Message Formats (Binary Format Definition File) in the manual Service Platform Basic Development Guide.
Create the request message format (XML format definition file) for decrement as an XML document type by using a text editor. Specify the file name as XMLRequest.xsd.
For details about how to create an XML format definition file, see 4.3 Creating Message Formats (XML Format Definition File) in the manual Service Platform Basic Development Guide.
The contents of the XML format definition file to be created are as follows:
<?xml version="1.0" encoding="UTF-8"?> <schema xmlns="http://www.w3.org/2001/XMLSchema" targetNamespace="http://www.example.org/RequestXML" xmlns:tns="http://www.example.org/RequestXML"> <element name="request" type="string"></element> </schema> |
Create the response message format (XML format definition file) for decrement as an XML document type using a text editor. Specify the file name as XMLResponse.xsd.
For details about how to create an XML format definition file, see 4.3 Creating Message Formats (XML Format Definition File) in the manual Service Platform Basic Development Guide.
The contents of the XML format definition file to be created are as follows:
<?xml version="1.0" encoding="UTF-8"?> <schema xmlns="http://www.w3.org/2001/XMLSchema" targetNamespace="http://www.example.org/RequestXML" xmlns:tns="http://www.example.org/RequestXML"> <element name="response" type="string"></element> </schema> |
The counter service used in the sample program, and the sample code of the protocol converter are as follows:
A sample code for counter service is described here. The class name is Counter and the package name is service.
/* All Rights Reserved. Copyright (C) 2008, Hitachi, Ltd. */
package service;
/**
* Count value fluctuation and count value acquisition class (viewed as a service)
* The count value is always 0 or more
*/
public class Counter {
/**
* Count value (always 0 or more)
*/
protected int count;
/**
* Constructor
* Initial value of @param init count
* @throws IllegalArgumentException An invalid value below 0 was specified.
* @return void
*/
public Counter(int init) {
if (init < 0) {
throw new IllegalArgumentException();
}
this.count = init;
}
/**
* Increment the count by 1
* @return void
*/
public void increment() {
++this.count;
}
/**
* Decrement the count by 1
* @throws IllegalStateException Invoked when the count was 0 o less.
* @return void
*/
public void decrement() {
if (this.count <= 0) {
throw new IllegalStateException();
}
--this.count;
}
/**
* Acquire the count value
* @return int Count value
*/
public int getCount() {
return this.count;
}
}
|
A sample code for protocol converter is described below. The class name is MyProtocolConverter and the package name is protocolconverter.
/* All Rights Reserved. Copyright (C) 2008, Hitachi, Ltd. */
package protocolconverter;
import java.util.Properties;
import javax.xml.parsers.*;
import org.w3c.dom.*;
import jp.co.Hitachi.soft.csc.msg.adapter.custom.*;
import service.Counter;
/**
* Implementation class of custom protocol converter interface
*/
public class MyProtocolConverter implements CSCMsgCustomProtocolConverter {
/**
* Adapter context
*/
private CSCMsgCustomAdapterContext adapterContext;
/**
* Counter class (viewed as a service)
*/
private Counter counter;
/**
* Used to create a DOM. XML message
*/
private DocumentBuilderFactory docBuilderFactory;
private DocumentBuilder docBuilder;
/**
* public default constructor (mandatory)
*/
public MyProtocolConverter() { }
/**
* Invoked when the custom adapter is started (before start is invoked).
* Acquire the adapter context.
* @param adapterContext Adapter context
*/
public void setCustomAdapterContext(
CSCMsgCustomAdapterContext adapterContext) {
this.adapterContext = adapterContext;
}
/**
* Invoked when the custom adapter is started (after setCustomAdapterContext is invoked).
* Implement the initialization processing.
* @throws CSCMsgCustomAdapterException An exception occurred in the custom adapter.
*/
public void start() throws CSCMsgCustomAdapterException {
try {
log("start");
Properties properties = this.adapterContext.getProperties();
String init = properties.getProperty("init");
if (init == null) {
// The init value must definitely be specified
throw new CSCMsgCustomAdapterException("init");
}
// Secure the resources (Resources used throughout the life cycle of the adapter)
this.counter = new Counter(Integer.parseInt(init));
docBuilderFactory = DocumentBuilderFactory.newInstance();
//docBuilderFactory.setNamespaceAware(true);
docBuilder = docBuilderFactory.newDocumentBuilder();
} catch (CSCMsgCustomAdapterException e) {
// Output the log required for failure analysis on the custom adapter side
log(e);
throw e;
} catch (Exception e) { // Also catch RuntimeException
// Output the log required for failure analysis on the custom adapter side
log(e);
// Throw again after wrapping with CSCMsgCustomAdapterException
throw new CSCMsgCustomAdapterException("start failed", e);
}
}
/**
* Implement the service component invocation processing.
* @param request Request message
* @param response Response message
* @throws CSCMsgCustomAdapterException An exception occurred in the custom adapter.
*/
public void invoke(CSCMsgRequestMessage request,
CSCMsgResponseMessage response)
throws CSCMsgCustomAdapterException {
try {
log("invoke [" + request.getOperationName() + "]");
// Distribute by operation name
if (request.getOperationName().equals("increment")) {
// Count increment processing
execIncrement(request, response);
} else if(request.getOperationName().equals("decrement")) {
// Count decrement processing
try {
execDecrement(request, response);
} catch(IllegalStateException e) { // Failed to decrement count
// Log output
log(e);
// Fault setting
response.setFault("invoke error", "decrement failed",
this.adapterContext.getAdapterName(), (Document)null);
}
} else {
throw new CSCMsgCustomAdapterException("unknown operation");
}
// Output current count
log("Count:" + counter.getCount());
} catch (CSCMsgCustomAdapterException e) {
// Output the log required for failure analysis on the custom adapter side
log(e);
throw e;
} catch (Exception e) { // Also catch RuntimeException
// Output the log required for failure analysis on the custom adapter side
log(e);
// Throw again after wrapping with CSCMsgCustomAdapterException
throw new CSCMsgCustomAdapterException("invoke failed", e);
}
}
/**
* Count increment processing
* @param request Request message
* @param response Response message
* @throws CSCMsgCustomAdapterException An exception occurred in the custom adapter.
* @throws CSCMsgIllegalMessageTypeException The message is not in the binary format.
* @throws CSCMsgInvalidMessageException An invalid message is specified.
*/
private void execIncrement(
CSCMsgRequestMessage request,
CSCMsgResponseMessage response)
throws CSCMsgCustomAdapterException,
CSCMsgIllegalMessageTypeException,
CSCMsgInvalidMessageException {
// Asynchronous operation: increment
if (response != null) {
// The communication model is synchronous
throw new CSCMsgCustomAdapterException("Invalid communication model");
}
if (request.getMessageType() != CSCMsgMessageConstant.MESSAGE_TYPE_BINARY) {
// The message is not in the binary format
throw new CSCMsgCustomAdapterException("Invalid message format (Request)");
}
byte[] data = request.getBytes();
if (data.length != 1) {
throw new CSCMsgCustomAdapterException("Invalid data");
}
int loop = Math.abs(data[0]);
for (int i = 0; i < loop; ++i) {
counter.increment();
}
}
/**
* Count decrement processing
* @param request Request message
* @param response Response message
* @throws CSCMsgCustomAdapterException An exception occurred in the custom adapter.
* @throws CSCMsgIllegalMessageTypeException The message is not in the binary format.
* @throws CSCMsgInvalidMessageException An invalid message is specified.
* @throws CSCMsgMultipleMessageInsertionException A message or fault information is already saved.
*/
private void execDecrement(
CSCMsgRequestMessage request,
CSCMsgResponseMessage response)
throws CSCMsgCustomAdapterException,
CSCMsgIllegalMessageTypeException,
CSCMsgInvalidMessageException,
CSCMsgMultipleMessageInsertionException {
// Synchronous operation: decrement
if (response == null) {
// The communication model is asynchronous
throw new CSCMsgCustomAdapterException("Invalid communication model");
}
if (request.getMessageType() != CSCMsgMessageConstant.MESSAGE_TYPE_XML) {
// The message is not in the XML format
throw new CSCMsgCustomAdapterException("Invalid message format (Request)");
}
if (response.getMessageType() != CSCMsgMessageConstant.MESSAGE_TYPE_XML) {
// The message is not in the XML format
throw new CSCMsgCustomAdapterException("Invalid message format (Response)");
}
// Request message analysis processing
NodeList nodeList = request.getXMLDocument().getElementsByTagName("request");
if (nodeList.getLength() != 1) {
// The root node cannot be found
throw new CSCMsgCustomAdapterException("Invalid request message");
}
Text text = (Text)nodeList.item(0).getChildNodes().item(0);
int loop = Math.abs(Integer.parseInt(text.getNodeValue()));
for (int i = 0; i < loop; ++i) {
this.counter.decrement();
}
// Build response message
Document responseDoc = docBuilder.newDocument();
Element rootElement = responseDoc.createElement("response");
responseDoc.appendChild(rootElement);
Text countTextNode = responseDoc.createTextNode(Integer.toString(counter.getCount()));
rootElement.appendChild(countTextNode);
// Save response message
response.setXMLDocument(responseDoc);
}
/**
* Perform termination processing and resource release
*/
public void stop() {
log("stop");
// Release resources
this.counter = null;
this.adapterContext = null;
this.docBuilderFactory = null;
this.docBuilder = null;
}
/**
* Log output
* @param message Message to be output
*/
public void log(String message) {
// The output results in standard output are output in the user output log
System.out.printf("[%s] %s\n",
this.adapterContext.getAdapterName(), message);
System.out.flush();
}
/**
* Log output
* @param message Exception to be output
*/
public void log(Exception e) {
// The output results in standard error output are output in the user error log
e.printStackTrace();
System.err.flush();
}
}
|
The following are the property files used in the sample program:
with the custom adapter development framework operation definition file, specify the class name of the protocol converter along with the package name.
<?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE properties SYSTEM "http://java.sun.com/dtd/properties.dtd"> <properties> <entry key="classname">protocolconverter.MyProtocolConverter</entry> </properties> |
With the custom adapter property file, set up properties to be used in the protocol converter.
A property file in which the initial value of the counter service count is set to 1 is as follows:
<?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE properties SYSTEM "http://java.sun.com/dtd/properties.dtd"> <properties> <entry key="init">1</entry> </properties> |
Create a JAR file that includes a protocol converter class file and a custom adapter development framework operation definition file.
For creating a protocol converter JAR file, use the jar command and archive the protocol converter class file, the class files that uses the protocol converter class file, and the custom adapter development framework operation definition file into a JAR file.
For details about the directory configuration of JAR files when using the jar command to archive, see 3.3.14(5) Creating a JAR file.
Arrange the created file in the current directory and sub directory as follows:
framework_properties.xml protocolconverter/CustomProtocolConverter.class service/Counter.class |
Archive the created JAR file with the file name MyProtocolConverter.jar.
If you execute the following command, the JAR file will be created:
jar cf ..\MyProtocolConverter.jar .\ |
Create the EAR file required for registering a new custom adapter. Archive the created EAR file with the file name CustomAdapter.ear.
When creating an EAR file, use the jar command and archive the JAR file provided with the Cosminexus Service Platform in the EAR file.
For details about the directory configuration of EAR files when using the jar command for archiving, see 3.3.14(6) Creating an EAR file.
Save a copy of the following file in the current directory:
Service-Platform-installation-directory\CSC\lib\cscmsg_adpejb.jar
Set name of the file to be created as CustomAdapter.ear.
If you execute the following command, the EAR file will be created:
jar cf ..\CustomAdapter.ear .\ |
To enable the usage of the file as a custom adapter, you must register the created EAR file in HCSC-Definer using the Adapter Addition Wizard. For details about how to register, see 3.2.14 Adding a new custom adapter.
All Rights Reserved. Copyright (C) 2015, Hitachi, Ltd.