Example test clients

This sample client uses invokes the SMART web service to predict possible catalytic inactivity on a protein sequence. Its input is a sequence of amino acids and a UniProt ID, and its output is a list of regions or features on that sequence. Because SMART should return deterministic results for a particular input sequence, we can afford to check that these are exactly what we expect, at least for a small sample of sequences (in this case, just one!). We’ll assume here that if the values are correct for our sample, they are going to be correct for the whole database.

#!/usr/bin/python
# the first line of the script must tell us which language interpreter to use,
# in this case its python


# import the modules we need for this test; SOAPpy is included on the server
# by default, and we'll need the 'sys' module in order to be able to use
# exit to return a value from this script
from SOAPpy import WSDL
from sys import exit

# set up the input values we need for this service...
# an amino acid sequence
seq_str =  'MANLGCWMLVLFVATWSDLGLCKKRPKPGGWNTGGSRYPGQGSPGGNRYPPQGGGGWG' \
           + 'QPHGGGWGQPHGGGWGQPHGGGWGQPHGGGWGQGGGTHSQWNKPSKPKTNMKHMAGAA' \
           + 'AAGAVVGGLGGYMLGSAMSRPIIHFGSDYEDRYYRENMHRYPNQVYYRPMDEYSNQNN' \
           + 'FVHDCVNITIKQHTVTTTTKGENFTETDVKMMERVVEQMCITQYERESQAYYQRGSSM' \
           + 'VLFSSPPVILLISFLIFLIVG'
# and the corresponding UniProt ID
ID= 'P04156'

# we'll include the whole main body in a try:except clause so that if something
# unexpected happens, we can return a sensible error value

try:
    # Get web service proxy
    proxy = WSDL.Proxy('http://smart.embl-heidelberg.de/webservice/SMART_webservice.wsdl')
    
    # Execute the SMART service
    features = proxy.doSMART(protein_sequence=seq_str, protein_ID=ID)
    
    # Get the features that are returned
    feature_list = features._getItemAsList('feature')
    
    # Assume that everything will work, so start with a returnvalue of 0 / Ok
    returnvalue = 0
    
    # we're expecting exactly two features for our input sequence, so test this 
    # first
    if len(feature_list) != 2:
        # write a comment to stdout, and return a value of 2. This will be interpreted as
        # a 'warning' status
        print "SMART returned the wrong number of features for this sequence"
        returnvalue= 2
    else:
        # we got exactly two features, so check that the start and end values are 
        # exactly what we'd expect for this sequence
        if ((int(feature_list[0].start) != 1) or (int(feature_list[0].end) != 22) 
            or (feature_list[0].type != "INTRINSIC")):
                returnvalue = 3
                print "Data Error in first feature"
        
        if ((int(feature_list[1].start) != 23) or (int(feature_list[1].end) != 240) 
            or (feature_list[1].type != "SMART")):
                returnvalue = 4
                print "Data Error in second feature"
except:
    print "Failed to talk to SMART service"
    returnvalue = 1

if returnvalue == 0:
    print "Everything worked fine"
    
exit(returnvalue)

Things to note about this sample python client:

  1. It uses SOAPpy to access the service. SOAPpy is a fairly low-level way of doing this, and it can be cumbersome to construct the right parameters for services, especially when they use complex types. But for this particular service it keeps the client code simple, and it’s one of the packages installed on the server for us, so we don’t need to do anything special in order to use it. If we really needed to use something else in Python to access our service, we would have to include the source files in the zip we upload.
  2. The try:except: clause isn’t entirely necessary, since if the script crashes or aborts for any reason (for example, using SOAPpy if the service isn’t available, it may cause an exception at the point we try to get a proxy or invoke the doSMART function), then the registry’s harness will in fact catch this for us and record a failed test execution. But it doesn’t do any harm to trap this more elegantly within our own script.
  3. This script returns 0 for Ok, 1 for ‘failed to talk to SMART for some reason’, and then 2, 3 or 4 if we could talk to the service but the results aren’t what we wanted. The 2, 3 and 4 return values are all interpreted by the registry as meaning the same test ‘warning’; we only return different values here so that if someone looks in detail at the log and compares it with our test script, its possible to see exactly which bit caused the problem.
  4. Remember, you MUST explicitly exit your script with a meaningful return value. otherwise the harness will pick up whatever the default return value for your programming language happens to be.
  5. Over half the lines in this example are comments; the actual code required is quite minimal.

Here's a similar example, but this time written in Perl. This script uses XMLCompile to access the Jaspar service.

#!/usr/bin/perl
# the first line of the script must tell us which language interpreter to use,
# in this case its perl

use strict;

# import the modules we need for this test; XML::Compile is included on the server
# by default.
use XML::Compile::WSDL11;
use XML::Compile::Transport::SOAPHTTP;

eval
{	
	# Retriving and processing the WSDL
	my $wsdl  = XML::LibXML->new->parse_file('http://api.bioinfo.no/wsdl/JasparDB.wsdl');
	my $proxy = XML::Compile::WSDL11->new($wsdl);
	
	# Generating a request message based on the WSDL
	my $getAllMatrices = $proxy->compileClient('getAllMatrices');
	
	# Calling the service and getting the response
	my $answer = $getAllMatrices->( Format => 'PFM', Database => 'CORE' );
	
	# If the response arrived, look for a specific value that is supposed to be equal to 40
	# If the value is 40, return 0 because the test passed.
	# If the value is something else, return 2 to indicate a warning.
	# If no answer has arrived, return 1 to indicate the test failed.
	if ( defined $answer ) {
		if (@{@{ $answer->{parameters}{Matrix} }[0]->{A}->{col}}[3] == 40){
			print "Passed\n";
			exit 0;
		} else {
			print "Unexpected data\n";
			exit 2;
		}
	} else {    
		print "Failed\n";
		exit 1;
	}
};

if ($@)
{
	print "Caught an exception\n";
	exit 1;
}

Things to note about this sample perl client:

  1. It uses XML::Compile::SOAP to access the web service. We strongly recommend this approach as a more robust alternative to SOAP::Lite
  2. Note the use of the 'eval' clause around much of the test body, and the 'if ($@)' test towards the end. Perl's standard return values are rather complex, and encode more information than we want here, so it's good practice to trap exceptions and make sure we return a '1'. Not doing this doesn't mean anything catastrophic will happen, since perl will exit with some non-zero number in any case, and the registry will interpret this as being a warning (whereas with the trap we can promote this to being an Error).

Here's a third example, written in Java. This code uses the Axis toolkit to access the DSSP service.

import org.apache.axis.client.Call;
import org.apache.axis.client.Service;
import javax.xml.namespace.QName;

public class TestClient {
  public static void main(String [] args) throws Exception {
	String endpoint =
		"http://utopia.cs.manchester.ac.uk/cgi-bin/dssp.cgi";

	Service  service = new Service();
	Call     call    = (Call) service.createCall();

	call.setTargetEndpointAddress( new java.net.URL(endpoint) );
	call.setOperationName(new QName("http://utopia.cs.manchester.ac.uk/", "runDSSPByID"));

	String ret = (String) call.invoke( new Object[] { "3EBX" } );

    if (ret.startsWith("==== Secondary Structure Definition by the program DSSP, updated CMBI version by ElmK / April 1,2000 ==== DATE="))
    {
	  System.out.println("Seems like the server is sending back something sane:");
	  System.out.println(ret);
	  System.exit(0);
    }
    else
    {
	  System.out.println("Got back invalid DSSP format:");
	  System.out.println(ret);
	  System.exit(1);
	}
  }
}

Things to note about this sample java client:

  1. It uses the Axis toolkit to access the web service.
  2. This is a simple example that shows direct access to a web service. It is recommended for anything other than such simple services to make use of Axis' WSDL2Java program to create this code for you.
  3. Given that java is not an interpreted language, you will find no execution directive in this example (the '#!/usr/bin/something'). In order to use this code in a registry test, you must package a shell script that in turn executes this java program (i.e. calls 'java TestClient').