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:

Web Services

CoreServices webservice framework

Interface Builder

Project Builder

OmniGene's Analysis Service Framework

The WSMakeStubs application

Connecting to OmniGene through WebServicesCore API

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.

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.

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

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:

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:

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.

Figure 1. Choosing a new Cocoa Project.

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.

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.

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.

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.

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:

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.

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:

The ID of the algorithm that is registered with the engine

The name of the algorithm

The java class that executes this algorithm

A textual description of the algorithm

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.