Introduction
On this day we will focus on preparing the initial implementation of our first component. By the end of the day, we expect the groups to:
- Go through "HelloComponent" implementation for the assigned programming language
- Inheritance from IDL interface to be implemented
- Basic implementation of the methods
- Modifying CDB configuration in your test directory
- Exercising your component implementation from objexp and/or a PySimpleClient instance
Guides
As a guide, we're going to show you a very simple component implementation.
The UML description for our component is:
First we create the directory for the IDL:
getTemplateForDirectory MODROOT_WS idlHelloComp
cd idlHelloComp/src
touch ../idl/HelloComponent.idl
We fill the IDL with the following:
#ifndef _HELLOCOMPONENT_IDL_
#define _HELLOCOMPONENT_IDL_
#pragma prefix "acsws"
#include <acscomponent.idl>
module workshop {
interface HelloComponent : ACS::ACSComponent {
string printHello();
};
};
#endif
We modify the Makefile:
...
IDL_FILES = HelloComponent
HelloComponentStubs_LIBS = acscomponentStubs
...
COMPONENT_HELPERS=on
...
We then compile and install the IDL definitions:
Configuration
The following image depicts the deployment configuration needed:
Add the following configuration in the $ACS_CDB/CDB/MACI/Components/Components.xml:
...
<e Name="CPP_HELLO_COMP"
Code="HelloComponentImpl"
Type="IDL:acsws/workshop/HelloComponent:1.0"
Container="bilboContainer"
ImplLang="cpp"/>
<e Name="JAVA_HELLO_COMP"
Code="acsws.workshop.HelloComponentImpl.HelloComponentComponentHelper"
Type="IDL:acsws/workshop/HelloComponent:1.0"
Container="frodoContainer"
ImplLang="java"/>
<e Name="PY_HELLO_COMP"
Code="ws.HelloComponentImpl"
Type="IDL:acsws/workshop/HelloComponent:1.0"
Container="aragornContainer"
ImplLang="py"/>
...
The above configuration is assuming that we're going to use the default 3 containers.
Implementation
Python
getTemplateForDirectory MODROOT_WS pyHelloComp
cd pyHelloComp/src
mkdir ws
touch ws/__init__.py
touch ws/HelloComponentImpl.py
We modify the Makefile for this component:
We fill the component code as follows:
# Client stubs and definitions, such as structs, enums, etc.
import workshop
# Skeleton infrastructure for server implementation
import workshop__POA
# Base component implementation
from Acspy.Servants.ACSComponent import ACSComponent
# Services provided by the container to the component
from Acspy.Servants.ContainerServices import ContainerServices
# Basic component lifecycle (initialize, execute, cleanUp and aboutToAbort methods)
from Acspy.Servants.ComponentLifecycle import ComponentLifecycle
class HelloComponentImpl(workshop__POA.HelloComponent, ACSComponent, ContainerServices, ComponentLifecycle):
def __init__(self):
ACSComponent.__init__(self)
ContainerServices.__init__(self)
self._logger = self.getLogger()
def printHello(self):
print("Just printing 'Hello World!'")
return "Hello World!"
Java
getTemplateForDirectory MODROOT_WS jHelloComp
cd jHelloComp/src
mkdir -p acsws/workshop/HelloComponentImpl
touch acsws/workshop/HelloComponentImpl/HelloComponentImpl.java
cp ../../idlHelloComp/src/acsws/workshop/HelloComponentImpl/HelloComponentComponentHelper.java.tpl acsws/workshop/HelloComponentImpl/HelloComponentComponentHelper.java
We modify the Makefile for this component:
...
JARFILES = HelloComponentImpl
HelloComponentImpl_DIRS = acsws
...
We fill the component code as follows:
//Suggested: import alma.<Module>.<Interface>Impl; //But anything, really
package acsws.workshop.HelloComponentImpl;
//Base component implementation, including container services and component lifecycle infrastructure
import alma.acs.component.ComponentImplBase;
//Skeleton interface for server implementation
import acsws.workshop.HelloComponentOperations;
//ClassName usually is <Interface>Impl, but can be anything
public class HelloComponentImpl extends ComponentImplBase implements HelloComponentOperations {
public HelloComponentImpl() {
}
public String printHello() {
System.out.println("Just printing 'Hello World!'");
return new String("Hello World!");
}
}
C++
We create the needed directories:
getTemplateForDirectory MODROOT_WS cppHelloComp
cd cppHelloComp/src
touch HelloComponentImpl.cpp
touch ../include/HelloComponentImpl.h
We modify the Makefile for this component:
...
INCLUDES = HelloComponentImpl.h
...
LIBRARIES = HelloComponentImpl
HelloComponentImpl_OBJECTS = HelloComponentImpl
HelloComponentImpl_LIBS = HelloComponentStubs acscomponent
...
We fill the component code as follows:
#ifndef _HELLO_COMPONENT_IMPL_H
#define _HELLO_COMPONENT_IMPL_H
#ifndef __cplusplus
#error This is a C++ include file and cannot be used from plain C
#endif
//Base component implementation, including container services and component lifecycle infrastructure
#include <acscomponentImpl.h>
//Skeleton interface for server implementation
#include <HelloComponentS.h>
//Error definitions for catching and raising exceptions
class HelloComponentImpl : public virtual acscomponent::ACSComponentImpl, public virtual POA_workshop::HelloComponent {
public:
HelloComponentImpl(const ACE_CString& name, maci::ContainerServices * containerServices);
virtual ~HelloComponentImpl();
char* printHello();
};
#endif
#include <HelloComponentImpl.h>
HelloComponentImpl::HelloComponentImpl(const ACE_CString& name, maci::ContainerServices * containerServices) : ACSComponentImpl(name, containerServices) {
}
HelloComponentImpl::~HelloComponentImpl() {
}
char* HelloComponentImpl::printHello() {
std::cout << "Just printing 'Hello World!'" << std::endl;
return CORBA::string_dup("Hello World!");
}
/* --------------- [ MACI DLL support functions ] -----------------*/
#include <maciACSComponentDefines.h>
MACI_DLL_SUPPORT_FUNCTIONS(HelloComponentImpl)
/* ----------------------------------------------------------------*/
With this information we are ready to compile our first component that will print the "Hello World" message.
Client
First launch your acs container with the modified ACS CDB
acsStartContainer -py aragornContainer
acsStartContainer -java frodoContainer
acsStartContainer -cpp bilboContainer
For simplicity, we implement a simple client in Python to communicate with the 3 programming languages:
from Acspy.Clients.SimpleClient import PySimpleClient
client = PySimpleClient()
hc_py = client.getComponent("PY_HELLO_COMP")
print(hc_py.printHello())
hc_java = client.getComponent("JAVA_HELLO_COMP")
print(hc_java.printHello())
hc_cpp = client.getComponent("CPP_HELLO_COMP")
print(hc_cpp.printHello())
Output
The output is seen on each container:
Py
...
2020-07-28T21:14:29.850 aragornContainer run - Calling maci::CBComponentInfo::done with descOut.id_tag = 2 for 'PY_HELLO_COMP'
2020-07-28T21:14:29.858 aragornContainer run - Call to maci::CBComponentInfo::done with descOut.id_tag = 2 for 'PY_HELLO_COMP' completed
Just printing 'Hello World!'
...
Java
...
2020-07-28T21:09:13.385 DELOUSE [frodoContainer] Calling maci::CBComponentInfo::done with descOut.id_tag = %d.1 for 'JAVA_HELLO_COMP'
2020-07-28T21:09:13.411 DELOUSE [frodoContainer] Call to maci::CBComponentInfo::done with descOut.id_tag = %d.1 for 'JAVA_HELLO_COMP' completed
2020-07-28T21:09:16.598 DELOUSE [frodoContainer] intercepted a call to 'JAVA_HELLO_COMP#printHello'.
Just printing 'Hello World!'
2020-07-28T21:09:16.599 DELOUSE [frodoContainer] returning from JAVA_HELLO_COMP#printHello after 0 ms.
...
C++
...
2020-07-28T21:19:53.080 [Container-ActivationMethod - maci::ActivationMethod::call] Calling maci::CBComponentInfo::done with descOut.id_tag = 4.
2020-07-28T21:19:53.082 [Container-ActivationMethod - maci::ActivationMethod::call] Call to maci::CBComponentInfo::done with descOut.id_tag = 4 completed.
Just saying 'Hello World!'
...
PySimpleClient
...
Hello World!
Hello World!
Hello World!
...