implementing web services and running orchestrations
DESCRIPTION
Implementing Web Services and running Orchestrations. Mario Caruso Claudio Di Ciccio Vincenzo Forte Ettore Iacomussi Massimo Mecella. From the Offline Synthesis Engine we obtained a composition Now the composition will be orchestrated . System Overview. Onine Phase. Offline Phase. - PowerPoint PPT PresentationTRANSCRIPT
Implementing Web Servicesand running Orchestrations
Mario CarusoClaudio Di CiccioVincenzo Forte
Ettore IacomussiMassimo Mecella
• From the Offline Synthesis Engine we obtained a composition
• Now the composition will be orchestrated
System Overview
OffSen
Orchestrator
Light Service Bed Service
Cont
ext A
war
enes
s
sdd
TargetService
OrchestratorClient
map
Alarm Service
composition
composition
Offline Phase Onine Phase
Orchestrator Client
• Its only role is to trigger an orchestration by passing a composition to the Orchestrator Engine
System Overview
OffSen
Orchestrator
Light Service Bed Service
Cont
ext A
war
enes
s
sdd
TargetService
OrchestratorClient
map
Alarm Service
composition
composition
Offline Phase Onine Phase
Orchestrator engine
• Given – a composition – a map of the available services – and the current state of the services (thanks to the
Context Awareness)• Produces an orchestration and invokes the
proper services operations <transition action="doSwitchOnLight" invoke="BedroomLight">
<target state="lightSwitchedOn"/><postcondition variable="lightStatus">
<set-value value="1"/></postcondition>
</transition>
Context Awareness
• The Context Awareness is a publish/subscribe component– Services play the role of publishers, they publish
events related to their conversational state and their variables whenever an update occurs
– Orchestration Engine (and other SM4All components) are subscribers, they are always aware of the service’s changes trough the CA notifications
Context Awareness
Service
ContextAwareness
OrchestratorEngine
Service
ContextAwareness
OrchestratorEngine
System Overview
OffSen
Orchestrator
Light Service Bed Service
Cont
ext A
war
enes
s
sdd
TargetService
OrchestratorClient
map
Alarm Service
composition
composition
Offline Phase Onine Phase
The role of the map• In the SM4All project there is a Repository, a system component in charge
of dynamically maintain and provide information about the currently available services
• For the sake of simplicity such component has been replaced by the map file, a static description of the available services in the form of a dictionary:
<service_key, service_endpoint> • It plays the role of a bridge between the offline phase and the online phase
– the offline synthesis engine produces compositions containing service’s keys (it doesn’t know where the services are deployed)
– the orchestrator engine invokes services by replacing keys with the endpoints where the services are deployed
• Example:
BedroomLight = http://127.0.0.1:9697/BedroomLight?wsdlAlarm = http://127.0.0.1:9697/Alarm?wsdlBed = http://127.0.0.1:9697/Bed?wsdl
Sdd -> Cbl -> Map -> Services
<conversational-orchestration-state><community-state>
<service-conversational-state service="Alarm" state="unique"/>
<service-conversational-state service="Bed" state="up"/><service-conversational-state service="BedroomLight"
state="on"/><variable-value name="lightStatus" value="1"/><variable-value name="bedStatus" value="1"/>
</community-state>...<transition action="doSwitchOnLight" invoke="BedroomLight">
<target state="lightSwitchedOn"/><postcondition variable="lightStatus">
<set-value value="1"/></postcondition>
</transition>
BedroomLight = http://127.0.0.1:9697/BedroomLight?wsdlAlarm = http://127.0.0.1:9697/Alarm?wsdlBed = http://127.0.0.1:9697/Bed?wsdl
<home …<service-instance name="BedroomLight" description="Light in the bedroom" type="blightServiceType.sbl.xml" siid="bedroom_light" wsa="BedroomLight"><properties><service-property name="room" value="bedroom"/></properties></service-instance><service-instance name="Bed" description="Bed in the bedroom" type="bedServiceType.sbl.xml" siid="bedroom_bed" wsa="Bed"></service-instance><service-instance name="BedRoomAlarm" description="Alarm in the bedroom" type="alarmServiceType.sbl.xml" siid="bedroom_alarm" wsa="Alarm"></service-instance></home>
sdd
cbl
map
Services
off
on
doSwitchOffLight, E2
doSwitchO
ffLight, E2doSw
itchO
nLig
ht, E
1
doSwitchOnLight, E1
Variables:lightStatus ∈ {0.1}
Effects:E1 : lightStatus = 1E2 : lightStatus = 0
@WebService@SOAPBinding(style = Style.DOCUMENT, use=Use.LITERAL)public interface LightServer {
/*In this case we specify the operation name to match the name of the operation declared of the sbl*/
@WebMethod(operationName="doSwitchOnLight") boolean turnOn();
@WebMethod(operationName="doSwitchOffLight") boolean turnOff();
/*In this case we don't need to explicitly specify the operation name because the java method
has the same name of the operation declared of the sbl*/
@WebMethod String getState();@WebMethod int getValue();
}
The service has • all the operations defined in its behaviour• two aditional operations (getState and getValue)
used to synchronously retrieve the internal state of the service (the asynchronous way is implemented trough the Context Awareness component)
Services
• The service maintains its internal state by updating a state data member and some variables members according to its behaviour.
@WebService(endpointInterface = "it.uniroma1.dis.caruso.light.LightServer") public class LightServerImpl implements LightServer{
...//The value of the variableprivate int value;//The conversational state of the serviceprivate String state;...
State and variables
<variable-model ..<value value="0" id="0"/><value value="1" id="1"/> ..
<variable name="lightStatus" type="custom" model="blight_status.vml.xml" />
blightServiceType.sbl
variables.vdd
blight_status.vml
public class LightServerImpl implements LightServer{public static final String STATE_A = "off";public static final String STATE_B = "on";
public static final int valueOn = 1;public static final int valueOff = 0;
static final String variableEventTypeName = "lightStatus";
<involved-variables><involved-variables>
<variable name="lightStatus”..<state name="off" type="initial-final">
<transition action="doSwitchOnLight"><target state="on" /><postcondition
variable="lightStatus"><set-value
value="1" /></postcondition>
</transition><transition action="doSwitchOffLight">
<target state="off" /><postcondition
variable="lightStatus"><set-value
value="0" /></postcondition>
</transition></state>
Operation names@WebService@SOAPBinding(style = Style.DOCUMENT, use=Use.LITERAL)public interface LightServer {
@WebMethod(operationName="doSwitchOnLight") boolean turnOn();@WebMethod(operationName="doSwitchOffLight") boolean turnOff(); @WebMethod String getState();@WebMethod int getValue();
}
<involved-variables><involved-variables>
<variable name="lightStatus”..<state name="off" type="initial-final">
<transition action="doSwitchOnLight"><target state="on" /><postcondition
variable="lightStatus"><set-value
value="1" /></postcondition>
</transition><transition action="doSwitchOffLight">
<target state="off" /><postcondition
variable="lightStatus"><set-value
value="0" /></postcondition>
</transition></state>
blightServiceType.sbl
Service lifecycle
Initialization
Running
Termination
Set initial stateand variables values
Register event types In CA (state and variables)
Register the serviceas a publisher wrt CA
Whenever an operation is invoked, and the state/variables changes, publish events accordingly
Gracefully shutdown: Unregister the publisher Unregister event types(state, variables)
NOTE: do not stop the service abruptly, in case you must restart the CA and consequently the whole system (or manually perform unregistrations)
Publish initial stateand variables values
Service lifecycle@WebService(endpointInterface = "it.uniroma1.dis.caruso.light.LightServer") public class LightServerImpl implements LightServer{
public LightServerImpl(String name){state = STATE_A;value = valueOff;System.out.println("Registering events");eventTypeService.type(MediaType.APPLICATION_XML).put(ClientResponse.class,
CopalClient.eventType(stateEventTypeName));eventTypeService.type(MediaType.APPLICATION_XML).put(ClientResponse.class,
CopalClient.eventType(variableEventTypeName));System.out.println("Setting ttl");WebResource test =
service.path(EVENTS_PATH+"/"+stateEventTypeName+"/ttl");response = test.type(MediaType.TEXT_PLAIN).put(ClientResponse.class,
""+Integer.MAX_VALUE);test = service.path(EVENTS_PATH+"/"+variableEventTypeName+"/ttl");response = test.type(MediaType.TEXT_PLAIN).put(ClientResponse.class,
""+Integer.MAX_VALUE);String[] eventNames = {stateEventTypeName, variableEventTypeName};System.out.println("Registering publisher");publishersService.type(MediaType.APPLICATION_XML).put(ClientResponse.class,
CopalClient.publisher(publisherName,eventNames));myPublisher.type(MediaType.APPLICATION_XML).post(ClientResponse.class,
CopalClient.event(stateEventTypeName,state));myPublisher.type(MediaType.APPLICATION_XML).post(ClientResponse.class,
CopalClient.event(variableEventTypeName,""+value));
Service lifecycle@Override
public boolean turnOff() {System.out.println(name + " turning off");state = STATE_A;value = valueOff;ClientResponse response =
myPublisher.type(MediaType.APPLICATION_XML).post(ClientResponse.class, CopalClient.event(stateEventTypeName,state));
myPublisher.type(MediaType.APPLICATION_XML).post(ClientResponse.class, CopalClient.event(variableEventTypeName,""+value));
return true;}@Overridepublic boolean turnOn() {
System.out.println(name + " turning on");state = STATE_B;value = valueOn;myPublisher.type(MediaType.APPLICATION_XML).post(ClientResponse.class,
CopalClient.event(stateEventTypeName,state));myPublisher.type(MediaType.APPLICATION_XML).post(ClientResponse.class,
CopalClient.event(variableEventTypeName,""+value));return true;
}
Service lifecycleRuntime.getRuntime().addShutdownHook(new Thread() {
public void run() {//Remove publisherSystem.out.println("Removing publisher");ClientResponse response =
myPublisher.delete(ClientResponse.class);System.out.println(response.toString());
System.out.println(response.getEntity(String.class).toString());
System.out.println("Removing events");WebResource wr =
service.path(EVENTS_PATH+"/"+stateEventTypeName);response = wr.delete(ClientResponse.class);System.out.println(response.toString());
System.out.println(response.getEntity(String.class).toString());
wr = service.path(EVENTS_PATH+"/"+variableEventTypeName);
response = wr.delete(ClientResponse.class);System.out.println(response.toString());
System.out.println(response.getEntity(String.class).toString());}
});
Since we are deploying web services without using any application server we terminate them by sending a termination signal (ctrl + c). It is not possible to catch such signal from the Eclipse environment, that’s why we create a jar to be launched from a console.
Publishing servicespublic class ServicesPublisher {
public static void main(String[ ] args) {if (args.length<2){
System.out.println("usage: java -jar LightServices.jar ip-address port\nexample: java -jar LightServices.jar 127.0.0.1 9697");
}else{
String address = args[0];String port = args[1];String endpointBase = "http://"+address+":"+port;String endpoint1 = endpointBase+"/BedroomLight";Endpoint ep = Endpoint.publish(endpoint1, new
LightServerImpl("BedroomLight"));System.out.println("Web service published @ " + endpoint1);
String endpoint2 = endpointBase+"/Bed";Endpoint ep2 = Endpoint.publish(endpoint2, new
BedServerImpl("Bed"));System.out.println("Web service published @ " + endpoint2);
String endpoint3 = endpointBase+"/Alarm";Endpoint ep3 = Endpoint.publish(endpoint3, new
AlarmServerImpl("Alarm"));System.out.println("Web service published @ " + endpoint3);
}}
}
Endpoint
String endpointBase = "http://"+address+":"+port;..String endpoint1 = endpointBase+"/BedroomLight”;Endpoint ep = Endpoint.publish(endpoint1, new LightServerImpl("BedroomLight"));System.out.println("Web service published @ " + endpoint1);
BedroomLight = http://127.0.0.1:9697/BedroomLight?wsdlAlarm = http://127.0.0.1:9697/Alarm?wsdlBed = http://127.0.0.1:9697/Bed?wsdl
Map file
Services publisher
Services must be published to the endpoints declared in the map file. When the Orchestrator Engine finds a service symbolic name it looks at the map and replaces such name with the corresponding endpoint.
<transition action="doSwitchOnLight" invoke="BedroomLight"><target state="lightSwitchedOn"/><postcondition variable="lightStatus">
<set-value value="1"/></postcondition>
</transition> 127.0.0.1:9697/BedroomLight
Contains useful methods to communicate with COPAL through REST servicesMain class in charge of deploying web services without an application server
Light Service Interface
Light Service Implementation
Different services belong to different packages
Libraries needed to implement the communication whith the REST Copal services
These files constitute the service/variable archives.They are not needed to build the project, but they are useful to continously check that the service you are implementing complies with the specifications.
Inspecting Web Services
Avoid Target Namespace collision
Target Namespacesdo not collide:
http://alarm.caruso.dis.uniroma1.it/
http://bed.caruso.dis.uniroma1.it/
http://light.caruso.dis.uniroma1.it/
Exporting runnable jar
Exporting runnable jar
Make sureIt is checked
A tool to test WS: SoapUI
A free generic graphical client to test Web services:• Given a web service definition (wsdl) it automatically generates all the request for
each operation.• Then you can invoke the operation with just one click
http://www.soapui.org
The tool is already installed in the Orchestrator Engine Virtual Machine @ /home/sm4all/Desktop/Tools/soapui-3.6.1
Invoking an operation
Context Awareness REST interface• http://localhost:7878/copal/events
– return current context event types• http://localhost:7878/copal/events/{name}
– return context event type with specified name• http://localhost:8080/copal/events/{name}/schema
– return schema in context event type with specified name• http://localhost:8080/copal/publishers
– return current context publishers registered• http://localhost:8080/copal/publishers/{sourceID}
– return context publisher with specified source ID• http://localhost:8080/copal/publishers/{sourceID}/publishedTypes
– return all published types in context publisher with specified source ID
Context Awareness REST via browser
Start the whole system• Starting from the sdd file build your Web Services and export the runnable jar
file (e.g. Services.jar)• Start the Orchestrator Engine Virtual Machine (VM)• Copy the composition file obtained from the Offline Composition Engine in
any location of the VM (e.g. /home/sm4all/Desktop/OrchestratorClient/mycomposition.xml)
• Copy the jar in any location of the VM (e.g. /home/sm4all/ServicesExamples/)• Configure the mapping file
/usr/share/jboss-6.0.0.Final/server/default/deploy/Sm4allUorOrchestrator.war/WEB-INF/classes/ServiceRepository.prop according to the sdd filee.g.BedroomLight = http://127.0.0.1:9697/light?wsdlBedRoomAlarm = http://127.0.0.1:9697/alarm?wsdlBed = http://127.0.0.1:9697/bed?wsdl
Start the whole system
• Start Context Awareness System (COPAL):– open a new console – cd /home/sm4all/OSGI_Copal_0.5.2/– ./run.sh– wait few seconds until the log will display in the
last line something similar to "endpoint.service.id=38}”
– COPAL will we available @ http://localhost:7878
Start the whole system• [OPTIONAL] set the Orchestration Engine properties that you can find
in: /usr/share/jboss-6.0.0.Final/server/default/deploy/Sm4allUorOrchestrator.war/WEB-INF/classes/Orchestrator.prop– change the COPAL base address and the OrchestratorStateManager address;
by default they are set to http://localhost:7878 and http://localhost:8081 respectively
• [OPTIONAL] set the StateManager properties that you can find in: /usr/share/jboss-6.0.0.Final/server/default/deploy/Sm4allUorOrchestratorStatesManager.war/WEB-INF/classes/OrchestratorStatesManager.prop– change the COPAL base address and the OrchestratorStateManager address;
by default they are set to http://localhost:7878 and http://localhost:8081 respectively
Start the whole system
• Start the Orchestrator Engine– open a new console– cd /usr/share/jboss-6.0.0.Final/bin– ./run.sh -b 0.0.0.0– wait few seconds until the log will display in the
last line something similar to "Started in 40s:384ms”
Start the whole system
• Start the Services– open a new console– move to the directory where you copied the jar (e.g. cd /home/sm4all/ServicesExamples/)
– java -jar LightServices.jar address port (e.g. java -jar Services.jar 127.0.0.1 9697)• NOTE: the address and the port of the base endpoint must be
specified according to the map file:
BedroomLight = http://127.0.0.1:9697/BedroomLight?wsdlBedRoomAlarm = http://127.0.0.1:9697/Alarm?wsdlBed = http://127.0.0.1:9697/Bed?wsdl
Start the whole system
• Start the Orchestrator Client– cd ~/Desktop/OrchestratorClient/– java -jar OrchestratorClient.jar <cblPath> e.g. java -jar OrchestratorClient.jar mycomposition.xml • you may either specify an absolute or relative path
– [OPTIONAL] if you want to run a client on a location different from localhost: java -jar OrchestratorClient.jar <cblPath> <orchestratorWsdlLocation>
Orchestration results
• The Orchestrator Client passes the composition file to the orchestrator
• The Orchestrator Engine start to invoke the operations offered by the services
• In the web services console see how services are orchestrated (which operations are invoked)
Context Awareness (COPAL)
Web Services
Orchestrator ClientOrchestrator Engine
Shutdown the whole system
You can run the orchestration client as many times as you want …When you finally want to stop the whole system:1. Shutdown the services (ctrl+c)2. Shutdown the Orchestrator Engine (ctrl+c)3. Shutdown the Context Awareness System
(ctrl+c and then Enter)