Samples
This section discusses the creation and deployment of the Web services insurance example. Using the concepts demonstrated by this example should be beneficial in constructing your own Web services.
Insurance example
Let's suppose that you have a Smalltalk application already written that you want to expose as a Web service. After loading the Web services feature, you will have in your image an application called SstWebServicesInsuranceExample. If you browse this app, you will notice five instance methods categorized as @WS-API in the class SstWSInsurancePolicyInterface. These represent the operations that we want to expose. This class mimics a database of health insurance polices by using a class variable to hold onto SstWSInsurancePolicy objects that are created by reading the file VASTInsuranceExampleDatabase.xml. This and other files required by the insurance example can be found in the ./samples/sstws directory of your VAST Platform (VA Smalltalk) installation. There is a README file in the samples directory that contains most of the code examples referenced in this section.
Modifying deployment files to customize service behavior
As described in the
Creating a Web service, initial deployment files can be created automatically using the provided
SstWSXmlGenerationTool. The code below stores initial service description files into the default XML directory.
ie) SstWSXmlGeneration forClass: SstWSInsurancePolicyInterface
For the simplest of service operations, generated files can be used unmodified to govern the behavior of services deployed to the Web services container. However, modification of these files is typically necessary to completely describe the desired behavior of more interesting services.
The next few sections discuss common file modifications that service creators can make to accurately capture the interface and implementation requirements for a service.
Renaming WSDL operations and messages
The deployment file generation tool derives names for WSDL operations and messages by replacing all colons (:) in a method with underscore characters. If these names are not acceptable, modify the names in the '<class>-interface' WSDL file and the deployment descriptor file (<class>.xml).
Defining custom schema types
Services that pass complex data arguments typically require the definition of custom types. Types can be defined in the types section of the WSDL document or included using a WSDL import tag that references an external location for an XML schema. The insurance example WSDL file named SstWSInsurancePolicyInterface-interface.wsdl demonstrates how to define custom types for a service. The example creates a schema <complexType> for each class used by the service. The complex schema types contain <element> definitions for each of the attributes of the Smalltalk class.
For example, the class SstWSPerson is represented as follows:
<xsd:complexType name="SstWSPerson">
<xsd:sequence>
<xsd:element minOccurs="1" maxOccurs="1" name="tin" type="xsd:string"/>
<xsd:element minOccurs="1" maxOccurs="1" name="name" type="xsd:string"/>
<xsd:element minOccurs="1" maxOccurs="1" name="policyNumber" type="xsd:string"/>
<xsd:element minOccurs="1" maxOccurs="1" name="address" type="tns:SstWSAddress"/>
</xsd:sequence>
</xsd:complexType>
Notice that the address element of SstWSPerson has a type tns:SstWSAddress. The type SstWSAddress is defined within the same XML schema as SstWSPerson. The prefix tns is a namespace prefix which indicates that the SstWSPerson type is defined in the namespace http://www.SstWSInsurancePolicyInterface.com/SstWSInsurancePolicyInterface-impl. The association between the 'tns' prefix and the http://www.SstWSInsurancePolicyInterface.com/SstWSInsurancePolicyInterface-impl namespace is established in the root schema tag using the special xmlns attribute prefix.
Specifying types for WSDL messages
The deployment file generation tool creates all WSDL parts with their type set to xsd:string. WSDL parts represent the arguments of a message, and service developers should modify the type attribute to contain the actual argument types.
The WSDL messages below are taken from the insurance example. Notice that the type attribute setting is modified to reflect the argument types for input and output messages of the ratePolicy operation.
<message name="ratePolicyIn">
<part name="ratePolicy" type="tin:SstWSInsurancePolicy"/>
</message>
<message name="ratePolicyOut">
<part name="outMsgFloat" type="xsd:float"/>
</message>
Specifying correct endpoint
When a service is deployed, the VAST Web services support attempts to activate any endpoints required to host the defined services. Prior to deploying a service, the service developer should modify the implementation WSDL file to specify the correct endpoint for the service. The WSDL port below is defined to host services on port 63003 on the host named vasthost.
<port name="SstWSInsurancePolicyInterfacePort"
binding="vastif:SstWSInsurancePolicyInterfaceBinding">
<soap:address location="http://vasthost:63003/SstWSServlet"/>
</port>
Customizing the service deployment descriptor
Service deployment descriptor files contain information used to configure services in a Web services container. Deployment descriptors are XML files that adhere to the schema defined in file sstwsdep.xsd. This section describes how to customize the contents of a service deployment descriptor.
imageComponentUrls - Specify the image components that should be loaded during deployment of the referenced services. Individual image components must be resolvable using standard IC loading protocol; therefore, the image component must be fully qualified, or it must be locatable in the IC_ROOT directory.
ie)
<imageComponentUrls>
<imageComponentUrl>myservice.ic</imageComponentUrl>
</imageComponentUrls>
mappingSpecUrls - Specify the mapping specification resources that should be initialized during service deployment. All listed mapping specification files are parsed and stored by the serializationManager of the container. The rules in these mapping specifications are used at execution time to map incoming SOAP messages into application domain objects.
ie)
<mappingSpecUrls>
<mappingSpecUrl>http://vasthost:63001/VASTInsuranceExample.map</mappingSpecUrl>
</mappingSpecUrls>
wsdlUrls - Specify the WSDL implementation resources that are required to describe the services being deployed. WSDL resources that are resolved via WSDL import elements should not be listed here.
ie)
<wsdlUrls>
<wsdlUrl>http://vasthost:63001/SstWSInsurancePolicyInterface.wsdl</wsdlUrl>
</wsdlUrls>
handlers - Specify the Web service handlers for a specified namespace. Handlers defined in this section are typically referenced by one or more 'operation' elements from the service provider definition. Multiple handlers elements are permitted, and each handlers element contains one or more handler, chain, or operationHandler elements.
ie)
<handlers namespace=
"http://www.SstWSInsurancePolicyInterface.com/SstWSInsurancePolicyInterface">
<handler name="QueryString" class="SstWSSampleBusinessPartnerVerifyHandler"/>
</handlers>
<handlers namespace="urn:SstWSInsurancePolicyInterface">
<operationHandler name="companyInfoHandler" class="SstWSServiceOperationHandler">
<input name="companyInfoInputHandler" class="SstWSSampleCompanyInfoHandler"/>
<output name="companyInfoOutputHandler" class="SstWSNoOperationHandler"/>
<fault name="companyInfoOutputHandler" type="vastwsc:wsServiceFaultServerHandler"/>
</operationHandler>
</handlers>
Specify handlers to override default processing for one or more messages in the SOAP Body or Header. Use an operationHandler to provide a complete service handler for a given operation. The operationHandler allows specification of input, output, and fault behavior in a single handler.
The service description definition
service - This element identifies a WSDL service name and namespace that MUST match the name and namespace for a WSDL service element. The namespace for a service is usually the same as the targetNamespace of the definitions element that contains it. The contents of the service element are used to configure the implementation of a VAST Web service.
ie)
<service name="SstWSInsurancePolicyInterface"
namespace="http://www.SstWSInsurancePolicyInterface.com/SstWSInsurancePolicyInterface-impl">
serviceInterfaceClass - This element specifies the name of the service proxy class for the service. The default (SstWSService) is sufficient for most cases, but can be replaced by a user-written interface class if desired.
ie)
<serviceInterfaceClass>SstWSService</serviceInterfaceClass>
provider - This complex element is used to map the WSDL operation interfaces to the Smalltalk method implementations.
vast:provider - This extension to the provider element allows for specification of the service implementation class. The prefix 'vast' is associated with the namespace "Smalltalk". The 'vast:provider' extension is only required when describing hosted services. If the extension is not supplied, the service being described is assumed to be a remote service.
ie)
<vast:provider className="SstWSInsurancePolicyInterface" creationMethod="new"/>
operations - This element contains a collection of operation elements that describe how to invoke the WSDL operations for the service.
operation - An individual operation mapping.
The name attribute of the operation indicates a selector from the vast:provider instance.
The qName attribute is the qualified name of a WSDL operation. The prefix for the qualified name must be associated with the namespace that is used to resolve the operation at runtime. For SOAP messages encoded as rpc, the message namespace is specified in the soap:body extension of the interface WSDL.
The flow attribute is the qualified name of a Web services handler that is invoked to process the operation.
<operations>
<operation name="ratePolicy:" qName="swsipi:ratePolicy">
</operation>
<operation qName="swsipi:getCompanyInfo" flow="swsipi:companyInfoHandler">
</operation>
</operations>
Running the example
One of the ways to create a container is to deploy an XML file that conforms to the deployment descriptor schema that is included with the product (sstwsdep.xsd). An example container deployment descriptor can be found in the samples directory and it is called SstWSSampleContainer.xml. Towards the bottom of this file, you will see the line: <serviceUrl>http://vasthost:63001/SstWSInsurancePolicyInterface.xml</serviceUrl>.
The <serviceUrls> section of a container deployment descriptor is used to supply a collection of resources that describe services to be deployed into the container. The content of our serviceUrl tag is a service deployment descriptor resource named SstWSInsurancePolicyInterface.xml. The service deployment descriptor specifies the implementation mappings and required resources for the insurance example service.
Starting the container
Here is the code that demonstrates how to deploy a container from a container deployment descriptor (it is assumed for the following code snippets that you have an HTTP server running on vasthost using port 63001 that can serve up all the documents that exist in the samples directory):
SstWSContainer clearAll.
[ SstWSContainer deploy: 'http://vasthost:63001/SstWSSampleContainer.xml'.
System logError: 'Deployment completed' ] fork.
Creating the client container
When the deployment is finished, you should see the message 'Deployment completed' in your Transcript window. Now we have created a container and deployed our service into it. Since we will be hosting and invoking our service in the same image, we recommend creating another container from which to invoke our service. Here's how:
SstWSContainer createContainerNamed: 'VastSampleClientContainer'.
Invoking an operation
It is important to understand the difference between the file SstWSInsurancePolicyInterface.xml (discussed above) and SstWSInsurancePolicyClientInterface.xml. The latter is a "client" deployment descriptor that happens to be the same file with one line removed:
<vast:provider className="SstWSInsurancePolicyInterface" creationMethod="new"/>
This line tells the container the name of the Smalltalk class that actually implements the service. If that line is removed, that means that you are not "hosting" a service; rather you are a "client" that wants to invoke a service that is hosted somewhere else (in our case, the service is hosted in the VastSampleContainer that was created when SstWSSampleContainer.xml was deployed). We are now ready to deploy our "client" into this new container and invoke our first service operation. This example invokes the getAllPolicies operation.
[|aContainer serviceCollection|
aContainer := SstWSContainer containerNamed: 'VastSampleClientContainer'.
serviceCollection := aContainer deploy:
'http://vasthost:63001/SstWSInsurancePolicyClientInterface.xml'.
serviceCollection first getAllPolicies inspect ] fork.
During service deployment, the <service> section of the deployment descriptor is used to construct an SstWSService proxy object, and the API of the proxy is determined from the mappings defined in the <operations> collection of the service provider description. For the example above, the constructed SstWSService proxy understands the message #getAllPolicies because the operation mapping was specified in the deployment descriptor.
Invoking a series of operations
OK, so you should see an open inspector on an OrderedCollection of SstWSInsurancePolicy objects. How did this magic happen? By creating a mapping file that maps the types listed in the WSDL to the Smalltalk class names that represent those types. The file VASTInsuranceExample.map lists the types that we want represented as Smalltalk classes. In particular, we can see that SstInsurancePolicyCollection is mapped to OrderedCollection, and we also have an attribute mapping that takes all the policy sub-elements and does an addAll: to the OrderedCollection. The location of the map file is specified in the deployment descriptor under the <mappingSpecUrls> section. When you deploy using a deployment descriptor, all the mappings specified are read in and cached in the serialization manager of the container. Now let's look at some more code. If the owner of policy '85496328' needs to update it because they are adding another dependent, then here is how that could be done using our service:
[|aContainer service newPerson policy updatedPolicy newRate|
aContainer := SstWSContainer containerNamed: 'VastSampleClientContainer'.
service := aContainer serviceNamed: 'SstWSInsurancePolicyInterface'
inNamespace: 'http://www.SstWSInsurancePolicyInterface.com/SstWSInsurancePolicyInterface-impl'.
"Retrieve the policy we want to update"
(policy:= service getInfoForPolicy: '85496328' ) inspect.
"Create the new person by cloning the owner, add them as a dependent and get a new
quote for the updated policy"
"The premium for a policy is based on the number of dependents listed on the policy"
newPerson:= policy owner deepCopy.
newPerson name: 'New Person'; tin: '694-17-0804'.
updatedPolicy := policy deepCopy.
updatedPolicy dependents add: newPerson.
(newRate:= service ratePolicy: updatedPolicy ) inspect.
"Update the policy with the new premium so we can update the database with it"
updatedPolicy premium: newRate.
(service updatePolicy: updatedPolicy ) ifTrue:[ Transcript cr;
show: 'Policy was successfully updated']
ifFalse:[ self error: 'Policy update failed'].
] fork.
Using SOAP arrays
The getAllPolicies operation demonstrated how a collection of objects can be exchanged using the framework. Another way to represent collections is to use the built in mechanism in SOAP called SOAP arrays. The Smalltalk class SstSoapArray is used to represent a SOAP array. To illustrate this, we can create a new operation called getAllPoliciesUsingSoapArrays. Here are the changes required to implement this new operation:
In the file SstWSInsurancePolicyInterface-interface.wsdl, you will notice that in the <portType> section, there is the following additional operation:
<operation name="getAllPoliciesUsingSoapArrays">
<input message="tns:getAllPoliciesIn"/>
<output message="tns:getAllPoliciesOutUsingSoapArrays"/>
</operation>
Notice that the input is exactly the same as the operation getAllPolicies, only the output is different. When we look at that message, we see it defined as follows:
<message name="getAllPoliciesOutUsingSoapArrays">
<part name="outMsgUsingSoapArrays" type="tin:ArrayOfSstWSInsurancePolicy"/>
</message>
Notice that the type as defined in the message getAllPoliciesOut has changed from being an SstInsurancePolicyCollection to ArrayOfSstWSInsurancePolicy. This is defined in the <types> section like this:
<xsd:complexType name ="ArrayOfSstWSInsurancePolicy">
<xsd:complexContent>
<xsd:restriction base="SOAP-ENC:Array">
<xsd:attribute ref="SOAP-ENC:arrayType" arrayType="tns:SstWSInsurancePolicy[]"/>
</xsd:restriction>
</xsd:complexContent>
</xsd:complexType>
This new type is defined as a restricted type of SOAP array. The restriction is that the array can only contain elements of type SstWSInsurancePolicy (as specified in the fourth line above).
In the file SstWSInsurancePolicyInterface.xml (the service deployment descriptor), there is another operation specified:
<operation name="getAllPolicies"
qName="swsipi:getAllPoliciesUsingSoapArrays"></operation>
So now we have two operations with the same name, but different qName. This means that the same selector #getAllPolicies will be executed for both operations, but one will return an OrderedCollection of policies and the other will return a SstSoapArray of policies. Similarly, the same addition is made to the client deployment descriptor, SstWSInsurancePolicyClientInterface.xml.
The code below demonstrates invocation of the getAllPoliciesUsingSoapArrays operation. The message #abtXmlMappedObject is sent to the resulting SstSoapArray to extract the Array that it represents.
[|aContainer service |
aContainer := SstWSContainer containerNamed: 'VastSampleClientContainer'.
service := aContainer serviceNamed: 'SstWSInsurancePolicyInterface'
inNamespace: 'http://www.SstWSInsurancePolicyInterface.com/SstWSInsurancePolicyInterface-impl'.
service getAllPoliciesUsingSoapArrays abtXmlMappedObject inspect ] fork.
Using WSDL to process SOAP Headers
For some cases, it may be desirable to include information that supplements the message being sent. SOAP allows the content of messages to be extended using SOAP Header elements. The insurance example contains an operation named getInfoForPolicyWithVerification which demonstrates how to use WSDL to enable automatic inclusion of SOAP Headers in outgoing messages. The entries below are from the WSDL file named 'SstWSInsurancePolicyInterface-interface.wsdl.
The abstract WSDL input message for the operation getInfoForPolicyWithVerification is as follows:
<message name="getInfoForPolicyWithVerificationIn">
<part name="getInfoForPolicy" type="xsd:string"/>
<part name="QueryInfoIn" element="tin:QueryString"/>
</message>
By default, WSDL specifies that both the getInfoForPolicy and QueryInfoIn parts are to be passed as part of the SOAP Body. SOAP extensions to the WSDL can be customized to refine the encoding rules for the message.
ie)
<soap:body use="encoded"
parts="getInfoForPolicy"
namespace="urn:SstWSInsurancePolicyInterface"
encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"/>
soap:header use="literal"
namespace="http://www.SstWSInsurancePolicyInterface.com/SstWSInsurancePolicyInterface-impl"
message="tns:getInfoForPolicyWithVerificationIn" part="QueryInfoIn"/>
The soap:body WSDL extension above indicates that only the getInfoForPolicy part should be included in the SOAP Body.
The soap:header WSDL extension above indicates that the QueryInfoIn part of the getInfoForPolicyWithVerificationIn message should be rendered as part of the SOAP header.
The number and order of arguments passed must match the WSDL parts defined in the abstract WSDL message. Therefore, the getInfoForPolicyWithVerificationIn message is constructed from two arguments. The getInfoForPolicy string argument is passed first followed by the QueryInfoIn argument. The code example below demonstrates invocation of the getInfoForPolicyWithVerification operation:
[|aContainer service args newPerson policy updatedPolicy newRate |
aContainer := SstWSContainer containerNamed: 'VastSampleClientContainer'
ifNone: [ SstWSContainer createContainerNamed: 'VastSampleClientContainer' ].
service := aContainer serviceNamed: 'SstWSInsurancePolicyInterface'
inNamespace: 'http://www.SstWSInsurancePolicyInterface.com/SstWSInsurancePolicyInterface-impl'.
(policy:= service getInfoForPolicy: '85496328'
withVerification: 'Acme Insurance') inspect.
] fork.
Using custom handlers to process SOAP headers
Applications can also add header entries to outbound SOAP messages using custom handlers. For example, it may be useful to include client identification information in all outgoing messages. The example handler class named SstWSSampleContainerHeaderOutputHandler demonstrates how information about a VAST Web service container can be added as a SOAP header using the addHeaderElement: method of the SstSoapEnvelope. Be aware that any added header elements must be capable of properly rendering themselves as XML.
To activate the SstWSSampleContainerHeaderOutputHandler in a Web services client, add the handler to the message construction handler chain as shown below.
| chain |
chain := (SstWSContainer containerNamed: 'VastSampleClientContainer') handlerFactory
handlerNamed: 'wsClientInputMessageConstructor'.
chain addHandler: (SstWSSampleContainerHeaderOutputHandler
new name: 'containerHeaderHandler' )
After executing the code above, all outgoing messages from the client container will contain a SOAP Header like that shown below:
<SOAP-ENV:Header>
<vast1:vastContainer
xmlns:vast1="urn:vastSampleGlobals">
<vast1:containerName>VastSampleClientContainer</vast1:containerName>
<vast1:vastVersion>60</vast1:vastVersion>
</vast1:vastContainer>
</SOAP-ENV:Header>
<SOAP-ENV:Body>
A service provider that receives a SOAP message containing the above header is not obligated to process it. Headers that must be processed by a service provider can specify a mustUnderstand value of true to force service providers to pay attention to the header.
Try executing one of the scripts from our previous examples. Was a message written to the Transcript by the SstWSSampleContainerHeaderInputHandler?
The SstWSInsurancePolicyInterface.xml deployment descriptor contains the handler definition shown below:
<handlers namespace="urn:vastSampleGlobals">
<handler name="vastContainer" class="SstWSSampleContainerHeaderInputHandler"/>
</handlers>
Therefore, the vastContainer element that is passed as a header by our client container is processed by our hosted service using the handler with class named SstWSSampleContainerHeaderInputHandler. The vastContainer handler was automatically registered during deployment of SstWSInsurancePolicyInterface.xml.
Note:
By default, the SST HTTP server traps and handles exceptions that occur during processing message. Prior to debugging the behavior of hosted services in the VAST Platform development environment, you should disable the default SST exception handlers using the menu selections:
•Tools->SST->Trap exceptions.
•Tools->SST->Forward exceptions.
Summary
Although the code in the steps above is somewhat contrived and doesn't check for all possible error conditions, it hopefully illustrates how easy it is to create a Web service from an existing application and invoke it. Once again, the mapping file is what allows us to deal directly with the business objects, i.e., SstWSInsurancePolicy which contains an SstWSPerson which contains an SstWSAddress. If at any time you want to modify the VASTInsuranceExampleDatabase.xml file, or just want to re-initialize the database, executing the following code will cause the database file to be read when any code is run that tries to access it:
SstWSInsurancePolicyInterface policies: nil.
Container Administration service
Also included as an example of the Web services framework is a service that exposes some of the core functions of the SstWSContainer. This service is for demonstration only. Since the service has no security features, usage in a production environment is NOT recommended.
The container administration service interface is implemented in a class called SstWSContainerAdminInterface in application SstWebServicesAdminApp. This example service performs administrative functions on the container in which it is deployed. The service currently exposes the following functions of the VAST Web services container.
| |
deploy: | Deploy a new service to the container by passing a service resource location. Ie) WSDL file or service deployment descriptor |
disableServiceNamed:inNamespace: | Disable the passed service name by marking it unavailable for invocation |
enableServiceNamed:inNamespace: | Enable the passed service name by marking it available for invocation |
shutDownContainer | Shut down the Web services container. By default, this causes the runtime image to shut down. |
undeployServiceNamed:inNamespace: | Remove the passed service from the container. |
undeploy: | Remove services described by the passed resource from the container. |
The files required to configure the administration service are found in the product XML directory. They are:
•sstwsadm.wsd - Implementation WSDL for the service.
•sstwsadi.wsd - Interface WSDL for the service.
•sstwsadm.xml - Deployment descriptor for the service.
Below are some code examples that demonstrate invocation of the sample container administration service.
Deploy the container administration service to the server container.
| cont |
SstWSContainer clearAll.
cont := SstWSContainer createContainerNamed: 'VastSampleServerContainer'.
[ cont deploy: 'http://vasthost:63001/sstwsadm.xml'.
Transcript cr; show: 'Deployment completed' ] fork
Deploy the container administration implementation WSDL to the client container.
[ | cont |
cont := SstWSContainer createContainerNamed: 'VastSampleClientContainer'.
cont deploy: 'http://vasthost:63001/sstwsadm.wsd'.
Transcript cr; show: 'Deployment completed' ] fork
Deploy the insurance example service via the deploy operation of the container administration service.
|service aContainer |
[ aContainer := SstWSContainer containerNamed: 'VastSampleClientContainer'.
service := aContainer serviceNamed: 'SstWSContainerAdminInterface'
inNamespace: 'http://www.SstWSContainerAdminInterface.com/SstWSContainerAdminInterface'.
(service deploy: 'http://vasthost:63001/SstWSInsurancePolicyInterface.xml') inspect ] fork.
Undeploy the insurance example service via the undeploy operation of the container administration service.
|service aContainer |
[ aContainer := SstWSContainer containerNamed: 'VastSampleClientContainer'.
service := aContainer serviceNamed: 'SstWSContainerAdminInterface'
inNamespace: 'http://www.SstWSContainerAdminInterface.com/SstWSContainerAdminInterface'.
(service undeploy: 'http://vasthost:63001/SstWSInsurancePolicyInterface.xml') inspect ] fork.
Undeploy a specific service
|service aContainer args|
[ aContainer := SstWSContainer containerNamed: 'VastSampleClientContainer'.
service := aContainer serviceNamed: 'SstWSContainerAdminInterface'
inNamespace: 'http://www.SstWSContainerAdminInterface.com/SstWSContainerAdminInterface'.
args := Array new: 2.
args
at: 1 put: 'SstWSInsurancePolicyInterface' ;
at: 2 put: 'http://www.SstWSInsurancePolicyInterface.com/SstWSInsurancePolicyInterface-interface'.
(service invoke: 'undeployServiceNamed_inNamespace' withArguments: args ) inspect ] fork.
Disable a service to prevent it from being invoked.
|service aContainer args|
[ aContainer := SstWSContainer containerNamed: 'VastSampleClientContainer'.
service := aContainer serviceNamed: 'SstWSContainerAdminInterface'
inNamespace: 'http://www.SstWSContainerAdminInterface.com/SstWSContainerAdminInterface'.
args := Array new: 2.
args at: 1 put: 'SstWSInsurancePolicyInterface' ;
at: 2 put: 'http://www.SstWSInsurancePolicyInterface.com/SstWSInsurancePolicyInterface'.
(service invoke: 'disableServiceNamed_inNamespace'
withArguments: args ) inspect ] fork.
Enable a service for invocation.
|service aContainer args|
[ aContainer := SstWSContainer containerNamed: 'VastSampleClientContainer'.
service := aContainer serviceNamed: 'SstWSContainerAdminInterface'
inNamespace: 'http://www.SstWSContainerAdminInterface.com/SstWSContainerAdminInterface'.
args := Array new: 2.
args at: 1 put: 'SstWSInsurancePolicyInterface' ;
at: 2 put: 'http://www.SstWSInsurancePolicyInterface.com/SstWSInsurancePolicyInterface'.
(service invoke: 'enableServiceNamed_inNamespace'
withArguments: args ) inspect ] fork.
Shutdown the container. In a runtime image, this operation shuts down the image.
|service aContainer args|
aContainer := SstWSContainer containerNamed: 'VastSampleClientContainer'.
service := aContainer serviceNamed: 'SstWSContainerAdminInterface'
inNamespace: 'http://www.SstWSContainerAdminInterface.com/SstWSContainerAdminInterface'.
service shutDownContainer inspect ] fork.