To use the Wrapper program, you first need to initialize it with a private key/public certificate pair which will be accepted by whichever services you're going to use, and with the public certificates for these services. Then you just need to submit requests to the Wrapper with some header information to identify the target service and, optionally, proxy configuration information for accessing the service. The response from the Wrapper for each request will include both completion information from the Wrapper and the actual response from the service, if appropriate.

Initializing the Wrapper private key/public certificate

The Wrapper program needs to use a private key and public certificate pair for signing messages sent to a service, and for decrypting messages received back from a service. It initially loads this key/certificate pair from a wrapper.pfx file, checking each time the program is started to determine if a file with that name is present in the directory from which the Wrapper program was launched. If the wrapper.pfx file is found, the Wrapper will read the password required to access the key/certificate pair from a file named password.txt, which should consist of a single line of password text. The key/certificate pair will then be added into the Wrapper's own .keystore file, and the wrapper.pfx file will be deleted.

You can change the key/certificate pair in use by the Wrapper on any startup. Once set, the values will be persisted until again changed. If the Wrapper does not have a key/certificate pair set (and the wrapper.pfx file is not present), it will fail on startup.

Initializing the service certificates

Server certificates are kept in the Wrapper's .keystore file, along with the key/certificate pair discussed in the last section. Certificates may be added to the .keystore using a Web browser interface integrated into the Wrapper program. The .keystore file can also be manipulated directly using any tool able to work with the JKS (Java Key Store) format, including GUI tools such as Portecle.

To add a certificate using the Web browser interface, enter the URL http://{host}:{port}/cert on a browser which has access to the system running the Wrapper, where {host} is the host name or IP address and {port} is the port number set in the wrapper.properties file (see the Configuration page for details on this). So if you're using a browser running on the same system as the Wrapper, and using the default port number in the supplied configuration, you'd go to http://localhost:7123/cert. This will display a web page which allows you to upload a new server certificate file - just click on "Browse..." and select the certificate file, then click "Upload" to add that certificate. When adding a certificate in this way the name of the file (with any extension removed) must match the name of the service using that certificate.

To work directly with the .keystore file using Portecle, start the Portecle program and select the "File/Open Keystore File..." menu item. This opens a file selection dialog. Navigate the directory structure to the Wrapper installation directory, then type the ".keystore" name directly in the "File Name:" text field (necessary since the leading '.' causes the file to be skipped in the display) and click "Open". This should bring up a dialog asking for the password. If you're using the .keystore file included in the distribution the password is "secret" (if you want to change this in your own .keystore, note that you'll also need to change it in the wrapper.properties file - see the Configuration page for details). The Portecle main window should then display a list of the certificates and the single key/certificate pair (with the name "wrapper") present in the store.

Once you have the .keystore opened in Portecle you can view the details of certificates and the key/certificate pair directly. You can also delete existing certificates from the store, and can add new service certificates to the .keystore using Portecle's "Tools/Import Trusted Certificate..." menu item. Once you're done with your changes, just use the "File/Save Keystore" menu selection to save your changes.

The Wrapper associates certificates with particular Web services by matching the alias name given to the certificate with the service name in the WSDL service definition file (the "name" attribute value on the <wsdl:service> element start tag). When you add a certificate to the store, you must make sure you use an alias name for the certificate which is the name of the service converted to all lowercase. For example, if you want to use a service named "SecureUpLoad2" you'd add the certificate for that service with the alias "secureupload2". When adding certificates through the Web page interface the Wrapper just takes the file name (with extension removed, and converted to all lowercase) as the alias name.

Submitting a request

To send a request to the Wrapper (and on to the destination service), you need to issue an HTTP POST request to the URL http://{host}:{port}/wrapper, where {host} is the host name or IP address and {port} is the configured port number (see the Configuration page for details on this). The POST data is an XML message in a particular form, with a <request> root element and a <service> child element, optionally followed by a <proxy> element, and then by the request data to be sent to the service (the content for the <SOAP:Body> element of the request).

The Wrapper code includes a test program that gives example code for making the request and processing a response, the org.soagate.wsswrapper.TestClient class in the /test source tree (view SVN). Here's a (slightly modified, to obscure non-public details) capture of a message sent by the test program:

POST /wrapper HTTP/1.1
Content-type: text/xml
Cache-Control: no-cache
Pragma: no-cache
User-Agent: Java/1.5.0_07
Host: 127.0.0.1:7123
Accept: text/html, image/gif, image/jpeg, *; q=.2, */*; q=.2
Connection: keep-alive
Content-Length: 1020

<request>
<service>http://example.com/webservices/DRI-DriServiceX509-Tst-01.00.00.wsdl</service>
<Message xmlns="urn:moe:dri:driservice:2.0.0">
 <type>1</type>
 <version>1</version>
 <parameters>
  <meta>
   <location>Paraparaumu</location>
   <user>Dennis</user>
   <date>2005-12-30</date>
   <time>23:50:40</time>
  </meta>
 </parameters>
 <data>
  <message>abcdefghijklmnop</message>
 </data>
</Message>
</request> 

The first part of the capture shows the actual HTTP headers, followed by the XML message to the Wrapper (the <request> element and content). The <service> element gives the location of the WSDL service description, which must be accessible to the Wrapper. The Wrapper reads this WSDL in order to find both the service name (the "name" attribute value on the <wsdl:service> element start tag) and the endpoint address to use to access the service (the "location" attribute value on the <soap:address> element, within the <wsdl:port> element, within the <wsdl:service> element). In this case the <service> element in the request message is directly followed by the message data to be sent to the service, the <Message> element and content.

This works fine as long as both the WSDL and the actual service endpoint are directly accessible to the Wrapper. If a proxy is needed for access to either the WSDL or the service, you can give the proxy configuration information to the Wrapper using a <proxy> element immediately following the <service> element in the request. Here's the format of this element:

  <proxy>
    <address>192.168.1.17</address>
    <port>127</port>
    <user>username</user>
    <pass>password</pass>
  </proxy>

If the <proxy> element is used, the <address> and <port> child elements are always required. The <user> and <pass> elements are optional, but if one is present they both must be present. All the child elements must be in the order shown.

Receiving a response

The Wrapper returns a response to your request once it has completed processing of the message (which may take anywhere from several seconds to potentially minutes, depending on the size of your message data and the speed of the connection to the service). The response indicates success or failure, and also gives the returned data from the service in the case of success, or an error code and message in the case of failure. Here's the capture of a response returned to the test program:

HTTP/1.1 200 OK
Transfer-Encoding: chunked
Connection: keep-alive
Server: Jetty(6.0.1)

C0
<response>
  <success>
    <MessageResponse xmlns="urn:moe:dri:driservice:2.0.0">
      <MessageResult>
        <ack>
          <code>0</code>
          <info>OK</info>
        </ack>
      </MessageResult>
    </MessageResponse>
  </success>
</response>
0

This response is reporting the successful completion of the request to the service, with the <MessageResponse> element and content the actual data returned by the service (the content of the <SOAP:Body> element of the response). The "C0" value before the XML response, and the "0" after, come from the HTTP/1.1 chunked encoding, and are not part of the actual data.

As a failure response example, the following is the XML body (with HTTP headers and chunking removed) returned by an attempt to access a WSDL from an invalid host name:

<response>
  <fail>
    <error-code>WSDL01</error-code>
    <error-text>Error reading service WSDL: xxx.example.com</error-text>
  </fail>
</response>

The <error-code> gives a simple code name for the problem, while the <error-text> gives specific details of the problem encountered. The full list of error codes reported by the Wrapper are defined in the following table.

Error codes and causes

READ01

Error in reading or parsing the XML content of the submitted request message.

REQ01

Error in the structure of the XML request message (such as missing the required <service> element).

REQ02

Error in the XML request message proxy configuration structure.

WSDL01

Unable to retrieve the service WSDL from the supplied address.

WSDL02

Error in processing the retrieved service WSDL (such as missing the expected <wsdl:service> element).

SECU01

Error accessing the keystore.

SECU02

No certificate alias matching the service name was found in the keystore.

SERV01

Error in making the request to the service (unable to access the server, etc.).

UNKNOWN01

Catch-all internal Wrapper program error. This should never occur unless you run into an error within the actual Wrapper code.