http://www.cytoscape.org/images/logo.png http://www.osgi.org/www/osgi_logos_supporter_final.png http://static.springframework.org/images/spring25.png

Cytoscape 3 Developer's Guide

Status

Cytoscape 3 Design Concept

Introduction

Cytoscape 3 is based on new technologies such as OSGi or Spring to provide maximum flexibility and expandability for all plugin writers. These technologies are very powerful, but you need to understand some new concepts to utilize them. The purpose of this document is to introduce new concepts you need to understand to develop Cytoscape 3 code and giving you a hands-on introduction to actual Cytoscape 3 code development.

Design and Implementation

The goal of Cytoscape 3 is clear: make more modularized, expandable, and maintainable version of Cytoscape. To achieve this goal, we should follow several design principles.

Important Design Principle of Cytoscape 3

Interface Oriented Design

The most important design concept throughout Cytoscape 3 is Interface Oriented Design. Since Cytoscape 3 is a platform rather than a stand-alone desktop application, we need to carefully design and implement the mechanism to make components as modular as possible. All of the technologies described above are for archiving this goal. The basic idea of interface oriented design is simple: building system wired through interfaces, not through the concrete classes' methods. You need to remember two simple rules when you develop Cytoscape 3 code:

  1. Hide unnecessary classes - you should expose only limited number of interfaces. This makes your module (plugin) easy-to-use for other developers. This can be done by OSGi.
  2. Separate implementation from API - If you export only small set of interfaces, it is easy to replace implementations without breaking other modules because they access your classes only through exported interfaces. Spring DM is one of the best tools to do this job.

In other words, you need to be very careful when you design public interfaces which will be accessed by other modules.

Dependency Injection

(under construction!)

Micro Core Architecture

architecture1.png

In Cytoscape 3, all modules are equal and there is no clear borderline between Core and Plugins. Instead of running Cytoscape on the top of Java Virtual Machine, we will insert one extra layer called OSGi (this will be supported in Java SE 7). In short, Cytoscape 3 is a set of bundles running on OSGi micro core.

Why Do We Have To Learn These New Technologies?

Cytoscape 2 has several architectural problems. They are:

The main purpose of new technologies we use is solving these problems.

OSGi

OSGi is relatively complex technology, but important points you need to understand for Cytoscape 3 development are only four:

  1. OSGi framework manages modules as bundle. Bundle is a new kind of JAR files with set of metadata.

  2. In Cytoscape 3, everything is a bundle. The border between plugin and core is very ambiguous.

  3. You can explicitly define which classes are accessible from others. Also, you can define which classes must be imported to run your bundle. This includes version numbers of the library, so different versions of the same library can exists on the same JVM.
  4. You can export any object as OSGi Service to the OSGi Service Registry. All bundles can access those registered services.

These solves lots of problems we had in version 2.x:

   1 public interface ClusteringService {
   2     // Run my clustering algorithm for a given network "parent" and return clusters as a set of subnetworks.
   3     public Set<CyNetwork> getClusters(CyNetwork parent);
   4 }
   5 

Spring Framework and Spring Dynamic Modules

Spring is the defacto standard of lightweight container for dependency injection. Tons of books and documents are available for Spring, and you can learn its mechanism by reading them. The role of Spring in Cytoscape 3 is simple: defining relationships between objects.

Wiring Objects

spring1.png

The diagram above shows the relationships between objects in Cytoscape 3 desktop application. In Spring, objects are defined as beans.

spring2.png

This diagram represents the cytoscapeDesktop bean, which is defined in a Bean Configuration XML file:

<bean name="cytoscapeDesktop" class="cytoscape.view.internal.CytoscapeDesktop">
    <constructor-arg ref="cytoscapeMenus" />
    <constructor-arg ref="networkViewManager" />
    <constructor-arg ref="networkPanel" />
    <constructor-arg ref="cytoscapeVersion" />
</bean>

Cytoscape Desktop is the main GUI component which includes some other components such as Network Panel or Menu Bar. To create an instance of Cytoscape Desktop, we need to provide those objects prepared somewhere outside of it. Instead of creating new instances of those required objects inside Cytoscape Desktop, you can inject them by Spring. In this case, all of the required dependency (cytoscapeMenus, networkViewManager, networkPanel, and cytoscapeVersion) are defined as beans in the Bean configuration file, and Spring injects those automatically to Cytoscape Desktop.

Separate Implementation from API

Spring is a powerful tool, but if we use Spring Dynamic Modules (Spring DM) along with it, we can take advantage of both Spring and OSGi.

Remember the ClusteringService in the last section. Without Spring, users of this object should do:

   1 public class ClusteringServiceUser {
   2   private ClusteringService service;
   3 
   4   public ClusteringServiceUser() {
   5      // Now ClusteringServiceUser depends on an implementation ClusteringServiceImpl. 
   6     service = new ClusteringServiceImpl();
   7   }
   8 }
   9 

This creates a dependency to specific implementation of ClusteringService API. With Spring, we can avoid this dependency:

   1     AbstractApplicationContext ctx
   2       = new ClassPathXmlApplicationContext(new String []{"bean-configuration.xml"});
   3     service = ctx.getBean("clusteringServiceBean");
   4 

However, this introduces a new dependency to Spring Framework itself (AbstractApplicationContext). With Spring DM, the client code looks like the following:

   1 public class ClusteringServiceUser {
   2   private ClusteringService service;
   3 
   4   public ClusteringServiceUser(ClusteringService service) {
   5      // No dependency to frameworks! 
   6     this.service = service;
   7   }
   8 
   9   // Sample client code to find clusters for each network passes as parameter.
  10   public Map<Integer, Set<CyNetwork>> analyzeNetwork(Set<CyNetwork> networks) {
  11     final Map<Integer, Set<CyNetwork>> clusterMap = new HashMap<Integer, Set<CyNetwork>>();
  12 
  13     for(CyNetwork net:networks) {
  14       clusterMap.put(net.getSUDI(), service.getClusters(net));
  15     }
  16     return clusterMap;
  17   }
  18 }
  19 

In this case, the user object depends on ClusteringService interface only and completely independent from implementations or framework. But what's the magic behind this? The answer is the combination of service configuration file and Spring OSGi Extender bundle.

Service Provider

To create an instance of ClusteringServiceImpl, you can define it as a regular Spring bean:

<bean name="clusteringServiceBean" class="org.foo.clustering.iternal.ClusteringServiceImpl">
    <constructor-arg ...
</bean>

Now you need to export this as an OSGi service:

<osgi:service id="clusteringServiceBeanService" ref="clusteringServiceBean"
                interface="org.foo.clustering.ClusteringService" />

Spring OSGi Extender read the configuration file and export clusteringServiceBeanService as an OSGi service automatically.

Service Consumer

In the client (ClusteringServiceUser), you need to import clusteringServiceBeanService to inject the service to the client. This can be done by writing a simple enty in the XML file:

<osgi:reference id="clusteringServiceBeanServiceRef" interface="org.foo.clustering.ClusteringService" />

Once client import the service, you can use it as a regular Spring bean. Therefore, you can inject it like:

<bean name="clusteringServiceUserBean" class="org.bar.client.iternal.ClusteringServiceUserImpl">
    <constructor-arg ref="clusteringServiceBeanServiceRef" />
</bean>

As you can see the example above, if we use Spring DM, Cytoscape 3 code is independent from OSGi API and Spring API. This means all of the Cytoscape objects are POJOs and we can replace the framework later when necessary.

Building System

This is not actually the architecture/design issue of Cytoscape 3, but is very important to understand to develop Cytoscape 3. In Cytoscape 2, we use build tool called Apache Ant. This is fairly flexible an powerful building tool, but have some issues:

  1. Developers have to manage module dependency manually

    • Cytoscape is a fairly complex application software using lots of public libraries (JARs). This means developers have to find correct version of libraries and copy them manually to the project directory. The bad news is most library JARs depends on other libraries and you need to figure out how they are related.
  2. Need to repeat same thing again and again

    • Probably, the first thing developer do to begin Cytoscape 2 plugin development is copying build.xml file from somewhere (from your old project or other plugin code). This is because most developers follow very similar process, like compile, test, create jar, publish JavaDoc to web site, etc.

To solve these issues and time saving, we decide to use Apache Maven for official build tool for Cytoscape 3.

Convention over Configuration

The basic idea of Maven is Convention over Configuration. In most cases, Java developers follow very similar process: write code, compile, test, build JAR files, create JavaDoc, and publish it. In Maven, this model development style is defined as a convention and it is designed not to repeat the same configuration again and again. Instead of writing build.xml at the beginning of plugin development, you can start with type some maven command to create basic directory structure for your plugin. It looks like the following:

src
test
pom.xml

Because maven creates the basic directory structure automatically Also, Maven 2 has a very useful feature

Please try this example to understand basic concept of Maven2.

Working with Cytoscape 3 Code

/!\ Need to update the sections below.

Related Frameworks and Technologies

From 3.0, new technologies/frameworks will be used for implementation. The following is the list of links to documents related to those frameworks/technologies.

Developer's Tutorials and References

For Eclipse Users

Basic Tutorial

Optional

For Netbeans Users

Other OSGi Tools and Technical Notes

Books

Spring

Spring DM and OSGi

Maven


Questions? Please e-mail me (kono_at_ucsd_edu)

Funding for Cytoscape is provided by a federal grant from the U.S. National Institute of General Medical Sciences (NIGMS) of the Na tional Institutes of Health (NIH) under award number GM070743-01. Corporate funding is provided through a contract from Unilever PLC.

MoinMoin Appliance - Powered by TurnKey Linux