uCosminexus Service Platform, Reception and Adapter Definition Guide

[Contents][Glossary][Index][Back][Next]

Appendix B.3 Sample program of the custom adapter development framework

This section describes the sample program of the custom adapter that uses the custom adapter development framework.

Organization of this subsection
(1) Overview of the sample program
(2) Message format
(3) Sample codes
(4) Property files
(5) Protocol converter JAR file
(6) EAR file

(1) Overview of the sample program

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

[Figure]

The counter service and the protocol converter of the custom adapter are as follows:

(a) Counter service

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:

(b) Protocol converter

The protocol converter invokes the counter service.

The protocol converter performs the following two operations:

(2) Message format

The message formats used in the sample program are as follows:

(a) Request message format of increment

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.

(b) Request message format for decrement

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>
(c) Response message format for decrement

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>

(3) Sample codes

The counter service used in the sample program, and the sample code of the protocol converter are as follows:

(a) Counter service

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;
 }
}
(b) Protocol converter

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();
 }
}

(4) Property files

The following are the property files used in the sample program:

(a) Custom adapter development framework operation definition file

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>
(b) Custom adapter property file

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>

(5) Protocol converter JAR file

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.

(a) Prerequisites

Arrange the created file in the current directory and sub directory as follows:

framework_properties.xml
protocolconverter/CustomProtocolConverter.class
service/Counter.class
(b) Creating the file

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 .\

(6) EAR file

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.

(a) Prerequisites

Save a copy of the following file in the current directory:

 
Service-Platform-installation-directory\CSC\lib\cscmsg_adpejb.jar
 
(b) Creating a file

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 .\
(c) Registering the file

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.