MacDevCenter    
 Published on MacDevCenter (http://www.macdevcenter.com/)
 See this if you're having trouble printing code examples


A Bioinformatics Web Service with Mac OS X
Using Objective-C and Mac OS X's Core Web Services to Construct an OmniGene Analysis Engine Client

by Brian Gilman
02/04/2003

Introduction to OmniGene

Releasing algorithms to the biological community (or any research environment) is typically a painstaking and error prone process. This stems from the fact that bioinformaticians do not usually write their programs with a user interface in mind and, instead, depend on a command line interface.

Typically, command line interfaces satisfy only a subset of so-called power users in an organization, leaving others in the dark in terms of input parameters, file formats, and output generated from these programs. READMEs and other documentation are usually left unread, forcing the developer of the program to answer the same questions time and time again.

Worse still, once a command line program becomes popular to the not so tech savvy biologist, the bioinformatician is left running their program each and every time data is ripe for analysis. One common solution to this problem is to set up a web interface for the popular program and let the biologist run it for themselves. This works well for a single program but becomes quite cumbersome when there are hundreds.

The OmniGene Analysis Engine (OAE) solves this problem by providing a runtime engine that interfaces with any command line driven program by exposing these programs as web services using a single common interface and a little glue code. The algorithm developer writes a single client application in their favorite programming language and makes this available to their biologist counterpart. After the interface has been produced the algorithm developer is freed from having to run their programs for the biologist. The bioinformatician can then concentrate on writing programs that solve the next set of interesting biological problems.

In this series of articles I will be describing the use of Objective-C, the CoreServices web services framework, and the WSMakeStubs application to produce a trivial OAE Mac OS X Aqua client application. This demonstration application is by no means complete: many features are missing, like robust error checking.

Specifically, I will be describing:

This article presupposes that you have a basic understanding of Cocoa programming, Objective-C and the developer tools that are bundled with Mac OS X 10.2. You must install the developer tools off the bundled CD to build the applications describe in this article. If you are not acquainted with these tools or languages please refer to the resources section at the end of this article.

Building Cocoa Applications: A Step by Step Guide

Related Reading

Building Cocoa Applications: A Step by Step Guide
By Simson Garfinkel, Michael Mahoney

The Web Services Revolution

Microsoft, IBM, HP and other large application server and software vendors are investing a lot of time, energy and money in web services. In fact, Microsoft has released .NET, a suite of frameworks and programming tools to produce web service applications. IBM has released the Web Services Tool Kit (WSTK) as well as many other web services frameworks that build on the WebSphere application server. In this article we'll be using the Apache Axis web services framework, an open source web services toolkit, and OS X's WebServicesCore API to build an OmniGene Analysis Engine client that inspects and executes OmniGene analysis tasks.

O'Reilly Bioinformatics Technology Conference Coverage
Get latest weblogs, photos, and articles from the O'Reilly Bioinformatics Conference in San Diego.

You might expect Microsoft, IBM, and the other major proponents of web services to be offering a wide variety of web service applications as part of their core offerings and operating systems. Unfortunately this is just not the case. Windows XP does allow users to look up applications that may handle certain file extensions it does not recognize using web services. Other than this example, the landscape is quite barren in terms of applications bundled with the OS that leverage web services. This is certainly not the case for applications built outside or not bundled with the major vendors OSes. A quick search on x-methods shows a significant number of web services that have been produced for experimentation. I encourage readers to explore the services that have been built and exposed on the x-methods web site.

Unsurprising to Mac users, Apple has been producing web service frameworks and applications which seamlessly integrate into the core OS for quite some time now. Apple has even bundled web service applications free for end users to use on an everyday basis. Apple has allowed users to use web services to search the Internet, find items on eBay, and even get answers to common computer related questions through the Sherlock application for a few years now. Apple's new release of Sherlock, version 3, allows users to plug other web services into this application and aggregate data from a wide variety of sources all over the Internet.

Apple provides a wide range of APIs to ease the integration of web services into native OS X applications using their CoreServices frameworks. We will be exploring these frameworks in the next few sections, and we'll build a simple tool to explore the OmniGene Analysis Engine. OAE is a middleware component that allows bioinformatics tools to be exposed as web services without having to change the underlying code. So, strap in, get comfy, grab a cup of your favorite caffeinated beverage, and read on to learn what can be done with Apple's web services APIs.

The WebServices Framework API's

Let's examine the low level frameworks that allow OS X developers to seamlessly integrate web services into their applications.

Apple has released WebServicesCore.Framework as part of the CoreServices API. CoreServices is a set of general use, low-level APIs which sit underneath both Carbon and Cocoa. These APIs include CoreFoundation, CarbonCore, WebServicesCore, and CoreGraphics. In this article we will be dealing with the WebServicesCore APIs.

Apple developer documentation can be found on the Apple developer site. Apple describes the WebServicesCore APIs as the toolkits and frameworks for accessing Web services from Mac OS X.

On an OS X 10.2 system the WebServicesCore APIs can be found in the folder:

/System/Library/Frameworks/CoreServices.framework/Frameworks/
   WebServicesCore.framework

The WebServicesCore API's contain two header files, WSMethodInvocation.h and WebServicesCore.h.

These files describe the methods that can be used to build web services client applications using either XML-RPC or SOAP/WSDL. We will be using the W3C's recommended SOAP style of web service invocation. For an introduction to XML-RPC Cocoa application and XML-RPC web services see http://ranchero.com/cocoa/xmlrpcdemo/.

The WSMethodInvocation.h file defines the most primitive ways to invoke a web service. The most important object defined in this file is the WSMethodInvocationRef, which is the main object used to invoke a web service, get the results back from the service, or check to see if any errors occurred. While we could use the objects that are defined in this file, Apple has supplied an application called WSMakeStubs that reads in a WSDL file and generates stubs that use this WebServicesCore.framework to execute methods against a web service that has been defined through SOAP and WSDL.

If your service does not expose its interface via WSDL, you are stuck writing all the supporting code for the service by yourself.

The WSMakeStubs Application

WSMakeStubs is a command line tool that consumes a WSDL file and generates Objective-C, C++ classes, or AppleScript code to execute methods that are defined by WSDL. A good introduction to WSDL can be found at the W3Schools web site.

The WSMakeStubs application comes with the Mac OS X 10.2 developer tools CD. Once the developer tools have been installed on your system you can find the WSMakeStubs application in /Developer/Tools/WSMakeStubs.

When invoked, the WSMakeStubs application outputs the following information:

Generates stubs for use with WebServices.framework.  
One of -url or -file must be specified.    

         -x:  the development language to use        
        -dir:  a path to the output directory where the stubs 
	           will be generated.         
               If not specified, defaults to the current working 
               directory        
       -name:  the name to be used for the root of the output file. 
               An appropriate extension will be added to
               the file[s]. The default name is WSStub.        
        -url:  url to a valid WSDL file        
       -file:  path to a valid WSDL file in the filesystem.  If 
               this is '-', the file is read from stdin        

     Available language emitters: (c++ is the default)    
         c++:  CoreFoundation with C++ bindings.  
               Additionally creates WSGeneratedStub.{cp.h}        
        ObjC:  CoreFoundation with Objective-C bindings. 
               Additionally creates WSGeneratedObj.{m,h}        
 applescript:  AppleScript        

    Tool version 0.2 (smz)

Generating the OmniGene Analysis Engine Stubs

We will be using the WSMakeStubs application to point at the OmniGene Analysis Engine. See the resources section or the OmniGene web page for a complete description of the framework. You will need to have the OmniGene Analysis Engine installed in order to follow along with the code examples.

Once OAE is installed and configured with the example "echo" service, point the WSMakeStubs application at the web service using the following command:

WSMakeStubs -x ObjC -name AnalysisStub -dir \ 
    <path_for_output_files> -url \
    http://<servername>:<port>/axis/services/Analysis?wsdl

Where <path_for_output_files> is the path where you would like to save the generated files, and <port> is the port that the OAE is listening on (typically 8080).

This will generate Objective-C stubs that can be used to execute the methods that are described in the OAE WSDL file. These stubs will be used in our example application to gain access to the OAE at runtime.

Writing The Cocoa Application

To get started writing the Cocoa application, open Project Builder, which can be found on your system at /Developer/Applications/Project Builder.app, and go to the File menu and choose "New Project".

Choose "Cocoa application" from the menu and then name the application "AnalysisApp" as shown in figures 1 and 2.

Screen shot.
Figure 1. Choosing a new Cocoa Project.



Screen shot.
Figure 2. Saving the application as AnalysisApp.

These two steps produce a default Cocoa project in the location you specified in the Project Directory path as shown in figure 2. After these steps have been completed, the Project Builder IDE will display your newly created project as shown in figure 3.

Screen shot.
Figure 3. Project Builder Default Project View.

In order for our new application to use the stubs created by the WSMakeStubs application, we need to add them to our newly created project. Go to the Project Builder menu Project and select "Add Files". Find the files that you generated with the WSMakeStubs application (AnaysisStub.h, AnalysisStub.m, WSGeneratedObj.h and WSGeneratedObj.m) and add them to the AnalysisApp project. Figure 4 shows the dialog box that you will be presented with.

Screen shot.
Figure 4. Adding the AnalysisStubs to the project.

You have now added the files to your project. Click on the AnalysisStub.h or AnalysisStub.m; you'll be presented with the source code that was generated by the WSMakeStubs application. Figure 5 shows the AnalysisStub.h source code as presented by Project Builder. You can browse all source code by using the method described above.

Screen shot.
Figure 5. Showing source code in Project Builder.

Now that the generated files have been added to the project, we need to add the CoreServices framework to our project so that it can link against this framework and use the WebServices APIs. To do this, go to the Project Builder IDE "Project" menu and select the "Add Frameworks" menu item. Browse to /System/Library/Frameworks/ and select CoreServices.framework to add the WebServiceFramework to the project.

Making A User Interface With Interface Builder

We are now ready to start building the interface to our application code with the Interface Builder. Interface Builder is an application bundled with developer tools that is tightly integrated with Project Builder. It allows the developer of Cocoa/Aqua applications to easily build a GUI for an application.

Interface Builder allows a developer to concentrate on the look and feel of an application without having to care about the programmatic details of low-level event handling, widget layout, etc. All you have to do is drop a few buttons, windows, and text fields onto the default window and off you go. Interface Builder hides a lot of the details of writing a GUI by hiding widget location information and signaling details in a file format called a NIB.

This article will not delve too deeply into Interface Builder; there are some very good resources available online from O'Reilly author Mike Beam. Mike has written a series of articles that describe how to program for OS X. Another great resource is the book Building Cocoa Applications a Step by Step Guide. I encourage readers of this article to visit the O'Reilly MacDevcenter.com site, build and run the Working with Tables: Writing an Address Book Application example and then proceed with the rest of this article.

With the Analysis Application open, double click on the MainMenu.nib. This will open up Interface Builder. The GUI for our application will consist of a tab pane, two buttons, a drop down menu, and a table view.

Drag these items on the main menu so that they appear as shown in Figure 6 below:

Screen shot.
Figure 6: Analysis App GUI layout.

Next you will need to make a controller class to handle events and act as a data source for the table view that will be populated with analysis task details. Subclass NSObject and name the generated class AnalysisController.

We need to add outlets that correspond to the drop down and table view that we set up in Interface Builder to send data to these objects. Add to the controller class the outlets dropdown and textField. You will also need to add the action getTasks to the AnalysisController. This action will get fired when the user clicks on the "Get Tasks" button.

After you've set up these outlets and actions, go to the Interface Builder and instantiate the controller class. Then you need to make the necessary connections between the buttons, views, and drop downs to the AnalysisController class (remember that you need to "control-drag" to make connections between components). After you are finished making all the connections, you will need to select the AnalysisController in the classes tab in Interface Builder and then select "Create files for controller". Two new files, AnalyisController.m and AnalysisController.h, will be added to your project. Now we're almost done.

Related Reading

Web Services Essentials
Distributed Applications with XML-RPC, SOAP, UDDI & WSDL
By Ethan Cerami

Connecting The Table View Object to the Controller Class

Connecting the table view to the controller class and making this class your data source is the one tricky part.

Select the table view object in Interface Builder by double clicking it (it will turn grey). Control-drag a connection from the table view object to the AnalysisController class. The directionality of this connection is very important, so you must make sure that you drag from the table view to the controller class. What we are doing is telling Interface Builder that the table view will be getting its data from the controller class and to make calls to it for all its data.

Once you have made the connection from the table view to the controller class, you will see a list of outlets available to choose from. Choose "datasource" from the list of outlets and then select the "connect" button at the bottom of the info window. This tells the table view widget that our controller class is the source of data for this widget.

Next, we need to define an identifier for each column in our table view. We do this for two reasons. First, we will pass this identifier to our NSDictionary full of web service details to and pull out algorithm specific information defined above. Second, using identifiers makes our programming life easier.

The OAE getTasks method provides us with 4 pertinent pieces of information that we would like to display:

We will display this information in our table view after the "Get Tasks" button is pressed in out GUI.

Now that we know what pieces of information we want to display to the user, let's set up the table view to handle them. In Interface Builder, double click on the table view object (it will become grey). Press command-1 to get a list of attributes displayed for this widget and set the number of columns to 5 by typing "5" in the #Colmn field.

Next, double click on the leftmost column in the table view and give this NSTableColumn object an identifier of ID by typing "ID" in the identifier text field found in Interface Builder's info window. Give the next four columns name, taskClassName, description, and parameterInfo identifiers.

Wrap Up

Congratulations, you have now successfully built Objective-C stubs using the WSMakeStubs utility provided by Apple, integrated the autogenerated files into a project using Project Builder, and wired up your graphical user interface for the OAE client application.

We'll finish up the project next week and show you how to write the Objective-C code to execute the web service, respond to user input, and populate the widgets that you dropped onto the graphical user interface.

Brian Gilman is a Group Leader in the Medical And Population Genetics Department at the Whitehead Institute Center For Genome Research.


Return to Mac DevCenter.

Copyright © 2009 O'Reilly Media, Inc.