Specification: Ballerina SOAP Library
Owners: @shafreenAnfar @MadhukaHarith92 @Nuvindu
Reviewers: @shafreenAnfar
Created: 2023/06/07
Updated: 2023/12/01
Edition: Swan Lake
Introduction
This is the specification for the SOAP package of Ballerina language, which provides APIs to send an ordinary XML request to a SOAP backend by specifying the necessary details to construct a SOAP envelope.
The SOAP package specification has evolved and may continue to evolve in the future. The released versions of the specification can be found under the relevant GitHub tag.
If you have any feedback or suggestions about the package, start a discussion via a GitHub issue or in the Discord server. Based on the outcome of the discussion, the specification and implementation can be updated. Community feedback is always welcome. Any accepted proposal, which affects the specification is stored under /docs/proposals
. Proposals under discussion can be found with the label type/proposal
in GitHub.
The conforming implementation of the specification is released and included in the distribution. Any deviation from the specification is considered a bug.
Contents
- Overview
- Components
- 2.1 Client
- 2.2 Supported APIs
- 2.2.1 Send & Receive
- 2.2.2 Send Only
- 2.2.3 Examples
- 2.2.3.1
sendReceive()
with SOAP 1.1 - 2.2.3.2
sendReceive()
with SOAP 1.2 - 2.2.3.3
sendOnly()
with SOAP 1.1 - 2.2.3.4
sendOnly()
with SOAP 1.2
- 2.2.3.1
- 2.3 Response Types
- 2.3.1
xml
- 2.3.2
mime:Entity[]
- 2.3.3 Examples
- 2.3.1
- Security
1. Overview
This specification elaborates on the functions available in the SOAP package.
The soap module abstracts out the details of the creation of a SOAP envelope, headers, and the body in a SOAP message.
2. Components
This section describes the components of the Ballerina SOAP package. To use the Ballerina SOAP package, a user must import one of the following sub modules of the Ballerina SOAP package first.
-
Importing SOAP 1.1 Module
import ballerina/soap.soap11;
-
Importing SOAP 1.2 Module
import ballerina/soap.soap12;
2.1 Client
The Client
is used to connect to and interact with SOAP endpoints.
NOTE: The SOAP module supports SOAP 1.1 and 1.2 versions. Users can specify the SOAP version when importing the SOAP package. In the SOAP package there are sub modules as
soap11
andsoap12
to support SOAP 1.1 and SOAP 1.2 in that order.
2.1.1 SOAP 1.1 Client
import ballerina/soap.soap11; soap11:Client soapClient = check new ("http://www.dneonline.com/calculator.asmx?WSDL");
2.1.2 SOAP 1.2 Client
import ballerina/soap.soap12; soap12:Client soapClient = check new ("http://www.dneonline.com/calculator.asmx?WSDL");
2.2 Supported APIs
This section outlines the APIs supported by the Ballerina SOAP package, providing an overview of their functionalities.
2.2.1 Send & Receive
The sendReceive()
API provides a mechanism to send SOAP requests to a specified endpoint and receive a relevant response. This is a synchronous operation where the client sends a SOAP request and waits for the service to process the request and return a response. This API is suitable for scenarios where the client requires both sending a request and receiving the associated response to proceed with further actions.
2.2.2 Send Only
The sendOnly()
API is designed for scenarios where the client needs to send a SOAP request but does not require or expect a response from the service. Here, it follows the "fire and forget" approach, where the client sends a SOAP request to the service without waiting for or processing any response. This API is useful when the client is only interested in triggering a specific action on the service side without needing the result.
The SOAP 1.1 specification requires the inclusion of the action
parameter as a mandatory component within its APIs. In contrast, SOAP 1.2 relaxes this requirement, making the action parameter optional.
2.2.3 Examples
Following examples provideds practical use cases for both sendReceive()
and sendOnly()
APIs.
2.2.3.1 sendReceive()
with SOAP 1.1
import ballerina/soap.soap11; public function main() returns error? { soap11:Client soapClient = check new ("http://www.dneonline.com/calculator.asmx?WSDL"); xml envelope = xml `<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/" soap:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"> <soap:Body> <quer:Add xmlns:quer="http://tempuri.org/"> <quer:intA>2</quer:intA> <quer:intB>3</quer:intB> </quer:Add> </soap:Body> </soap:Envelope>`; xml response = check soapClient->sendReceive(envelope, "http://tempuri.org/Add"); }
2.2.3.2 sendReceive()
with SOAP 1.2
import ballerina/io; import ballerina/soap.soap12; public function main () returns error? { soap12:Client soapClient = check new("http://ws.cdyne.com/phoneverify/phoneverify.asmx?wsdl"); xml envelope = xml `<soap:Envelope xmlns:soap="http://www.w3.org/2003/05/soap-envelope" soap:encodingStyle="http://www.w3.org/2003/05/soap-encoding"> <soap:Body> <quer:CheckPhoneNumber xmlns:quer="http://ws.cdyne.com/PhoneVerify/query"> <quer:PhoneNumber>18006785432</quer:PhoneNumber> <quer:LicenseKey>0</quer:LicenseKey> </quer:CheckPhoneNumber> </soap:Body> </soap:Envelope>`; xml response = check soapClient->sendReceive(envelope); io:println(response); }
2.2.3.3 sendOnly()
with SOAP 1.1
import ballerina/soap.soap11; public function main() returns error? { soap11:Client soapClient = check new ("http://www.dneonline.com/calculator.asmx?WSDL"); xml envelope = xml `<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/" soap:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"> <soap:Body> <quer:Add xmlns:quer="http://tempuri.org/"> <quer:intA>2</quer:intA> <quer:intB>3</quer:intB> </quer:Add> </soap:Body> </soap:Envelope>`; check soapClient->sendOnly(envelope, "http://tempuri.org/Add"); }
2.2.3.4 sendOnly()
with SOAP 1.2
import ballerina/io; import ballerina/soap.soap12; public function main () returns error? { soap12:Client soapClient = check new("http://ws.cdyne.com/phoneverify/phoneverify.asmx?wsdl"); xml body = xml `<soap:Envelope xmlns:soap="http://www.w3.org/2003/05/soap-envelope" soap:encodingStyle="http://www.w3.org/2003/05/soap-encoding"> <soap:Body> <quer:CheckPhoneNumber xmlns:quer="http://ws.cdyne.com/PhoneVerify/query"> <quer:PhoneNumber>18006785432</quer:PhoneNumber> <quer:LicenseKey>0</quer:LicenseKey> </quer:CheckPhoneNumber> </soap:Body> </soap:Envelope>`; check soapClient->sendOnly(body); }
2.3 Response Types
Responses of the SOAP APIs supports either xml
or mime:Entity[]
types. Since these APIs supports type inference, either type can be assign to the variables as a single type instead of a union type of xml
and mime:Entity[]
.
2.3.1 xml
The xml
type is the common return type for SOAP responses. When a SOAP request is made using either the sendReceive()
API, the response is typically in xml
format. The xml
type captures this response, allowing users to work with and manipulate the xml
data received from the SOAP service.
2.3.2 mime:Entity[]
The mime:Entity[]
type represents the return type for SOAP endpoints that support multimedia types in responses. In scenarios where SOAP services return multimedia content, such as images or files, the response is represented as an array of MIME entities (mime:Entity[]
). This allows users to handle and process multimedia data received from SOAP services.
2.3.3 Examples
The following examples provides details on handling SOAP responses with different types (xml and mime:Entity[]).
2.3.3.1 Send & Receive with xml
Response
import ballerina/io; import ballerina/soap.soap12; public function main () returns error? { soap12:Client soapClient = check new("http://ws.cdyne.com/phoneverify/phoneverify.asmx?wsdl"); xml envelope = xml `<soap:Envelope xmlns:soap="http://www.w3.org/2003/05/soap-envelope" soap:encodingStyle="http://www.w3.org/2003/05/soap-encoding"> <soap:Body> <quer:CheckPhoneNumber xmlns:quer="http://ws.cdyne.com/PhoneVerify/query"> <quer:PhoneNumber>18006785432</quer:PhoneNumber> <quer:LicenseKey>0</quer:LicenseKey> </quer:CheckPhoneNumber> </soap:Body> </soap:Envelope>`; xml response = check soapClient->sendReceive(envelope); io:println(response); }
2.3.3.2 Send & Receive with mime:Entity[]
Response
import ballerina/io; import ballerina/soap.mime; import ballerina/soap.soap12; public function main () returns error? { soap12:Client soapClient = check new ("http://soap-endpoint-url"); xml body = xml `<soap:Envelope xmlns:soap="http://www.w3.org/2003/05/soap-envelope" soap:encodingStyle="http://www.w3.org/2003/05/soap-encoding"> <soap:Body> <quer:Add xmlns:quer="http://tempuri.org/"> <quer:intA>2</quer:intA> <quer:intB>3</quer:intB> </quer:Add> </soap:Body> </soap:Envelope>`; mime:Entity[] mtomMessage = []; mime:Entity envelope = new; check envelope.setContentType("application/xop+xml"); envelope.setContentId("<soap@envelope>"); envelope.setBody(body); mtomMessage.push(envelope); mime:Entity bytesPart = new; string readContent = check io:fileReadString(FILE_PATH); bytesPart.setFileAsEntityBody(FILE_PATH); string|byte[]|io:ReadableByteChannel|mime:EncodeError bytes = mime:base64Encode(readContent.toBytes()); if bytes !is byte[] { return error("Encoded characters are not in the correct format"); } bytesPart.setBody(bytes); check bytesPart.setContentType("image/jpeg"); bytesPart.setContentId("<image1>"); mtomMessage.push(bytesPart); mime:Entity[] response = check soapClient->sendReceive(mtomMessage, "http://tempuri.org/Add"); }
3. Security
The SOAP client module introduces a robust framework for configuring security measures in SOAP communication. Security is a critical concern when exchanging data via web services, and this module offers comprehensive options to fortify SOAP requests and responses.
There are two primary security configurations available for SOAP clients:
-
outboundSecurity
: This configuration is applied to the SOAP envelope when a request is made. It includes various ws security policies such as Username Token, Timestamp Token, X509 Token, Symmetric Binding, Asymmetric Binding, and Transport Binding, either individually or in combination with each other. -
inboundSecurity
: This configuration is applied to the SOAP envelope when a response is received. Its purpose is to decrypt the data within the envelope and verify the digital signature for security validation.
3.1 Policies
This package currently supports the following WS Security policies:
- Username Token: Provides authentication through username and password credentials.
- Timestamp Token: Enhances message integrity by incorporating timestamp information.
- X509 Token: Allows the use of X.509 certificates for secure communication.
- Symmetric Binding: Enables symmetric key-based security mechanisms.
- Asymmetric Binding: Facilitates the use of asymmetric cryptography for enhanced security.
These policies empower SOAP clients to enhance the security of their web service communications by selecting and implementing the appropriate security mechanisms to safeguard their SOAP envelopes.
3.2 Security Policy Configuration Types
This subsection introduces the configuration types for inbound and outbound security, providing detailed information on each type.
3.2.1 Outbound Security Configurations
-
TimestampTokenConfig
: Represents the record for Timestamp Token policy.- Fields:
int
timeToLive : The time to get expired
- Fields:
-
UsernameTokenConfig
: Represents the record for Username Token policy.- Fields:
string
username : The name of the userstring
password : The password of the userPasswordType
passwordType : The password type of the username token
- Fields:
-
SymmetricBindingConfig
: Represents the record for Symmetric Binding policy.- Fields:
crypto:PrivateKey
symmetricKey : The key to sign and encrypt the SOAP envelopecrypto:PublicKey
servicePublicKey : The key to encrypt the symmetric keySignatureAlgorithm
signatureAlgorithm : The algorithm to sign the SOAP envelopeEncryptionAlgorithm
encryptionAlgorithm : The algorithm to encrypt the SOAP envelopestring
x509Token : The path or token of the X509 certificate
- Fields:
AsymmetricBindingConfig
: Represents the record for Asymmetric Binding policy.- Fields:
SignatureConfig
signatureConfig : Configuration for applying digital signaturesEncryptionConfig
encryptionConfig : Configuration for applying encryptionstring
x509Token : The path or token of the X509 certificate
- Fields:
3.2.2 Inbound Security Configurations
InboundSecurityConfig
: Represents the record for outbound security configurations to verify and decrypt SOAP envelopes.- Fields:
crypto:PublicKey
verificationKey : The public key to verify the signature of the SOAP envelopecrypto:PrivateKey
|crypto:PublicKey
decryptionKey : The private key to decrypt the SOAP envelopeSignatureAlgorithm
signatureAlgorithm : The algorithm to verify the SOAP envelopeEncryptionAlgorithm
decryptionAlgorithm : The algorithm to decrypt the SOAP body
- Fields:
3.3 Configure Security Policies
The following examples shows on configuring security policies for SOAP clients, covering scenarios like Username Token with Transport Binding and Asymmetric Binding with SOAP 1.2 clients.
3.3.1 UsernameToken and TranportBinding Policy with SOAP 1.1 Client
import ballerina/crypto; import ballerina/soap; import ballerina/soap.soap11; public function main() returns error? { soap11:Client soapClient = check new ("https://www.secured-soap-endpoint.com", { outboundSecurity: [ { username: "username", password: "password", passwordType: soap:TEXT }, TRANSPORT_BINDING ] }); xml envelope = xml `<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/" soap:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"> <soap:Body> <quer:Add xmlns:quer="http://tempuri.org/"> <quer:intA>2</quer:intA> <quer:intB>3</quer:intB> </quer:Add> </soap:Body> </soap:Envelope>`; xml response = check soapClient->sendReceive(envelope, "http://tempuri.org/Add"); }
3.3.2 Asymmetric Binding and Outbound Security Configuration with SOAP 1.2 Client
import ballerina/crypto; import ballerina/soap; import ballerina/soap.soap12; public function main() returns error? { configurable crypto:PrivateKey clientPrivateKey = ?; configurable crypto:PublicKey clientPublicKey = ?; configurable crypto:PublicKey serverPublicKey = ?; soap12:Client soapClient = check new ("https://www.secured-soap-endpoint.com", { outboundSecurity: { signatureConfig: { keystore: { path: KEY_STORE_PATH_2, password: PASSWORD }, privateKeyAlias: ALIAS, privateKeyPassword: PASSWORD, canonicalizationAlgorithm: wssec:C14N_EXCL_OMIT_COMMENTS, digestAlgorithm: wssec:SHA1 }, encryptionConfig: { keystore: { path: KEY_STORE_PATH_2, password: PASSWORD }, publicKeyAlias: ALIAS, encryptionAlgorithm: wssec:AES_128 } }, inboundSecurity: { keystore: { path: KEY_STORE_PATH_2, password: PASSWORD }, decryptionAlgorithm: wssec:AES_128 } }); xml envelope = xml `<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/" soap:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"> <soap:Body> <quer:Add xmlns:quer="http://tempuri.org/"> <quer:intA>2</quer:intA> <quer:intB>3</quer:intB> </quer:Add> </soap:Body> </soap:Envelope>`; xml response = check soapClient->sendReceive(envelope, "http://tempuri.org/Add"); }