It has become customary when learning a new programming language or testing an unfamiliar programming environment to write a 'Hello world!' program. So, without breaking the tradition let us create our first HelloWorldService that will service the “Hello World!” string.
To create a service first we need to inherit from the JService class and implement all the ClaRA interface methods.
public class HelloWorldService extends JService {
According to the ClaRA terminology we are writing a hello-world service engine that is going to be deployed in one of the service containers of a data processing environment of a ClaRA cloud. So, in order to present our hello-world engine as a service we need to implement abstract methods of the JService class. These methods are designed to interface the user code with the framework that assures proper registration and execution of the user code as a service.
@Override
public String getName() {
return "hello";
}
@Override
public String getAuthor() {
return "Gyurjyan";
}
@Override
public String getDescription() {
return "Hello World service";
}
@Override
public String getVersion() {
return "1.0";
}
@Override
public String getLanguage() {
return CConstants.LANG_JAVA;
}
@Override
public JioSerial execute(JioSerial[] data) {
return null;
}
@Override
public void configure(JioSerial data) {
}
@Override
public void destruct() {
}
It is important to mention that the getName interface method defines the name of our hello-world service engine that is going to be used by the framework to construct the canonical name of the service. The canonical name of the service is the name that is going to be used for further service registration, discovery, composition and execution. In the above example code the name of the hello-world service engine is set to be “hello”. The rest of the interface methods are used to describe the functionality of a service, informing the framework and future service customer about the hello-world service engine author, version, language, and etc. The operational details, i.e. the actual functionality of our hello-world service, are going to be described in the execute method of the ClaRA interface.
@Override
public JioSerial execute(JioSerial data) {
// output transient data object
JioSerial out = new JioSerial();
out.setLanguage(CConstants.LANG_JAVA);
// check the input data mime-type
if(data.getMimeType().type().equals(MimeType.STRING.type())){
// get input data object from the JioSerial transient data
String inputDataObject = data.getStringObject();
// we do not care about the input data content
// generate the output data
out.setData(“Hello World!”);
out.setDataDescription("response to "+inputDataObject);
out.setStatus(CConstants.info);
} else {
// Reject with an execution status = error
out.setData(CConstants.REJECT);
out.setDataDescription("I can accept only strings");
out.setStatus(CConstants.error);
}
return out;
}
In order to make the hello-world code ClaRA “ready” we need to compile and copy the compiled byte-code into the $CLARA_SERVICES directory.
>javac -cp $CLARA_SERVICES/lib/clara.jar:$CLARA/lib/jtools-1.0.jar:$CLARA_SERVICES/lib/cMsg-3.3.jar HelloWorldService.java -d $CLARA_SERVICES/
How do I make my service available to the public?
In a previous exercise we named our hello-world example as a service, which is not a correct description of the created class. What we actually coded in the previous example was the engine of the hello-world service. In order to offer the hello-world engine as a ClaRA service we need to deploy it inside of the ClaRA service container. If you have read the entire manual up to this point, you already know that a ClaRA service container is the framework component that presents user engines as services. Containers are also used for logical grouping of services. In order to create a container or use the existing container for our hello-world engine deployment, we must communicate with the ClaRA framework administrative services. To do that let us write our first orchestrator that connects to the ClaRA framework and asks the framework normative services to create a service container and deploy the required engine in it. The code of our simple DeployService orchestrator is shown below.
public class DeployService extends JOrchestrator {
As you see user orchestrators must inherit from the JOrchestrator class. This is the class that provides public methods to communicate with the ClaRA framework. The constructor of the orchestrator simply calls the parent constructor, which will establish a connection between this orchestrator and the ClaRA framework (platform).
/**
* Constructor
* Connects to the ClaRA platform
*
* @param name of this orchestrator
*/
public DeployService(String name) {
super(name);
}
It is important to be reminded that any ClaRA service or orchestrator must have a unique name. In this particular case the name will be defined by the user as a parameter to the main method of the DeployService orchestrator.
public static void main(String[] args){
String oName = args[0];
String host = args[1];
String container = args[2];
String engineName = args[3];
String engineClass = args[4];
// get textual representation of the host IP address
host = CUtil.getIPAddress(host);
// an instance of this class
DeployService dso = new DeployService(oName);
// print orchestrator info
System.out.println(dso);
// container canonical name
String conCanName = host.trim()+"/"+container.trim();
// service canonical name
String serCanName = conCanName+"/"+engineName.trim();
// get registration information form the platform normative services
dso.updateRegistration();
The local variable oName is the user specified name of this orchestrator. For the deployment of our hello-world engine as a service, we need to specify the name of the host of the service where it will be running, the service container name, the name of the engine and finally the class name of the engine. As you see from the code this information is used to create both the service container and service canonical names. As you already know, the ClaRA naming convention requires that a service container name be constructed as
host/container_name
and a service name be constructed as
host/container_name/engine_name.
Now you might ask, what is the name of the hello-world engine? The answer to this question is in the hello-world engine code where you defined a name of the engine when you implemented the getName() ClaRA interface method. The rest of the code, where we actually communicate with the normative services and ask them to start the container and the service is listed below.
// create a container if it is not already registered
if(!dso.isContainerRunning(conCanName)){
if(!dso.startServiceContainer(host,container)){
System.out.println("Error: Failed to create a service container on the host ="+host);
System.exit(1);
}
}
// wait until service container is fully registered
CUtil.sleep(500);
// start a service on the specified container if it is not already deployed
if(!dso.isServiceRunning(serCanName)){
if(!dso.startService(host,container,engineName,engineClass)){
System.out.println("Error: Failed to create a service on the container = "+conCanName);
System.exit(2);
} else {
System.out.println("Started "+serCanName+" at: "+ CUtil.getCurrentTime());
}
} else {
System.out.println("Service "+serCanName+" exists on the platform.");
}
dso.exit();
}
Let us now compile and run DeployService class. The example below of the compilation command will install compiled class file into $CLARA_SERVICES dir.
>javac -cp $CLARA_SERVICES/lib/clara.jar:$CLARA_SERVICES/lib/jtools-1.0.jar:$CLARA_SERVICES/lib/cMsg-3.3.jar DeployService.java -d $CLARA_SERVICES/
Before execution make sure that the ClaRA platform is up and running. DeployService requires 3 parameters:
-
host where the hello-world service will run
-
name of the service container (arbitrary, for example xContainer)
-
hello-world service class name (examples.service.HelloWorld - take a look at the package statement of the HelloWoirld.java).
The registration name of an orchestrator can be auto-generated using generateName() method of the ClaRA utility package CUtil (see appendix B). This way you will avoid name conflict, resulting in a orchestrator registration rejection. However, we will not recommend auto-generating the service container name since this is part of the future service canonical name.
After running the DeployService class you will get the following console:
>java -cp "$CLARA_SERVICES/.:$CLARA_SERVICES/lib/*" examples.orchestrator.DeployService xName localhost xContainer hello examples.service.HelloWorldService
**************************************************
* ClaRA 2 client = xName
**************************************************
- Name = xName
- Host = 192.168.1.132
- Start time = 2012/08/06 19:51:20
- UDL = cMsg://192.168.1.132:45000/cMsg/129.57.29.62_platform
- Platform = 129.57.29.62_platform
- Platform TCP port = 45000
- Platform UDP port = 45000
-Connected to host = 192.168.1.132
**************************************************
Started 192.168.1.132/xContainer/hello at: 2012/08/06 19:51:21
The result of the hello-world service deployment will be indicated on the platform console:
>bin/clara-platform
>> **** cMsg server successfully started at Mon Aug 06 19:28:11 EDT 2012 **** <<
**************************************************
* CLARA-2 Platform *
**************************************************
- Name = 192.168.1.132_platform
- Host = 192.168.1.132
- TCP port = 45000
- UDP port = 45000
- Start time = 2012/08/06 19:28:12
**************************************************
**************************************************
* CLARA-2 Data Processing Environment *
**************************************************
- Name = 192.168.1.132_admin
- Host = 192.168.1.132
- Start time = 2012/08/06 19:28:12
-
- Platform host = 192.168.1.132
- Platform name = 192.168.1.132_platform
- Platform TCP port = 45000
- Platform UDP port = 45000
**************************************************
192.168.1.132_admin registered with the platform at 2012/08/06 19:28:12
192.168.1.132/xContainer registered with the platform at 2012/08/06 19:51:20
192.168.1.132/xContainer/Hello registered with the platform at 2012/08/06 19:51:21
Share with your friends: |