Differences between revisions 7 and 27 (spanning 20 versions)
Revision 7 as of 2009-03-10 23:37:56
Size: 8877
Editor: KeiichiroOno
Comment:
Revision 27 as of 2009-03-18 20:24:38
Size: 21587
Editor: nebbiolo
Comment:
Deletions are marked like this. Additions are marked like this.
Line 6: Line 6:
== Status ==
 * 1st draft of concept guide finished - Kei (3/10/2009)
 * Concept guide section updated - Kei (3/11/2009)

= Cytoscape 3 Design Concept =
Line 8: Line 13:
Cytoscape 3 is based on new technologies such as [[http://www.osgi.org/Main/HomePage|OSGi]] or [[http://www.springsource.org/about|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. A central goal of Cytoscape 3 is to make a more __'''modularized, expandable, and maintainable'''__ version of Cytoscape. To achieve this goal, we follow several design principles and take advantage of three new technologies:
 * [[http://www.osgi.org/Main/HomePage|OSGi]]
 * [[http://www.springsource.org/about|Spring]]
 * [[http://maven.apache.org/|Maven]]
These technologies are very powerful, but you'll need to understand a few new concepts to use them easily and effectively. The purpose of this document is to introduce the new design concepts that you will need to develop Cytoscape 3 code.
Line 11: Line 20:
Cytoscape 2 has several architectural problems. They are:

 * Modularity
   * View and models are coupled in some places and hard to run in command line or server backend.
   * Unnecessary packages are open to public access. The result is broken plugins every time core developer update some implementations.
 * Expandability
   * There are no mechanism for plugins to communicate to each other.
   * Cytoscape crashes if different versions of a same library load at once.

The main purpose of new technologies we use is solving these problems.
Cytoscape 2.x has several architectural problems. They are:

  * There is no clear module structure and thus many circular dependencies.
  * Unnecessary packages are open to public access. This results in broken plugins every time core developers update code we thought no one was using!
  * Cytoscape 2.x has a package dependency graph that looks like this:
     (insert graph here)
  * View and model are tightly coupled in many places and make it hard to run in command line mode or as a server backend.
  * There is no mechanism for allowing plugins to communicate with each other.
  * Cytoscape has no mechanism for supporting different versions of libraries causing conflicts between plugins.

Central to each of these problems is a lack of a module system. Unfortunately, [[http://www.jquantlib.org/public/docs/osgi/OT_TS-5122_295122_191-1_v1.pdf|Java lacks an effective mechanism for defining modules.]] To address this need, we have decided to use OSGi as a mechanism for enforcing modularization. While OSGi provides many benefits, its most important is that it provides a new scoping mechanism that allows java packages to be declared public or private. This is accomplished by adding a few lines of metadata to the manifest file of a jar. Aside from the metadata the jars (which OSGi calls bundles) are ''normal java jar files.''

OSGi developers have built upon this scoping mechanism and developed a framework (i.e. the Service Registry) as well as design patterns that allow developers to write very clean and simple code. Taking advantage of this framework, however, requires knowledge of and use of the OSGi API, which is not necessarily a simple thing. Dealing with this concern brings us to Spring.

Spring (specifically [[http://springsource.org/osgi|Spring Dynamic Modules]]) allows us to remove all OSGi dependencies from our code yet still take advantage of the Service Registry and other OSGi features. This means that you continue to write normal java POJOs. The cost is that your code is now initialized using Spring XML configuration code.

Finally, because OSGi breaks applications into many jars (called bundles) with dependencies and version numbers we have decided to use a build tool that has an explicit model for dealing with dependencies: Maven. You can think of Maven as a formalized version of [[http://ant.apache.org|Ant]] or even '''make'''. Unlike other tools, Maven provides a simple structure for declaring and using dependencies. We will take advantage of Maven's dependency handling to simplify the Cytoscape build process.
  

=== Important Design Principle of Cytoscape 3 ===
==== Interface Oriented Design ====
Fundamental throughout Cytoscape 3 and OSGi is it's enforcement of'''''Interface Oriented Design'''''. Rather than make both interfaces and implementations publicly available, Cytoscape 3 will only make interfaces public. All implementations of interfaces will be hidden in internal packages and will only be available through the OSGi Service Registry and Spring. The benefit of this approach is that you only need to concern yourself with an interface. You will never need to worry about specific implementation details. As long as you code to the interface, your code should continue to work.

From a plugin writer's perspective, you should:

 1. Hide unnecessary classes and only expose a limited number of interfaces. This makes your module (plugin) easy-to-use for other developers. OSGi provides the enforcement mechanisms for this.
 1. Separate implementation from API. This makes it 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 for this job.

==== Dependency Injection ====

An important aspect of Cytoscape 3 development is the idea of [[http://en.wikipedia.org/wiki/Dependency_injection|Dependency Injection]]. In practical terms, this means that all dependencies for your classes should be specified in your constructor and you should no longer be creating (most) objects on your own.

For instance, if you need to create a new CyNetwork you will not call the constructor of a particular implementation of the CyNetwork interface. Instead you will have a CyNetworkFactory ''injected'' into your class (via its constructor) and then you will ask CyNetworkFactory to provide you with a new instance of CyNetwork. The benefit of this approach is that you ''never'' see the implementation of CyNetwork which frees us from a particularly onerous dependency - the ability to change implementation easily.

==== Micro Core Architecture ====

In Cytoscape 3, all modules are equal and there is no clear distinction between ''Core'' and ''Plugins''. Instead of running Cytoscape on the top of Java Virtual Machine, we will insert one extra layer called the '''''OSGi''''' runtime. Cytoscape 3 is simply a set of bundles running on top of an OSGi micro core.

The diagram above shows overall architecture of Cytoscape 3. The most important point is that all of the inter-bundle communication is managed by the OSGi service registry, meaning through interfaces only, and not through concrete classes.

{{attachment:architecture1.png}}
Line 24: Line 64:
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.
 1. In Cytoscape 3, '''''everything is a bundle'''''. The border between plugin and core is very ambiguous.
 1. 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.
 1. 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:
 * Plugins developers can publish small set of public functions for other developers. If you define an '''''OSGi manifest file (metadata for OSGi bundles)''''', you can export only selected class(es) for other developers and hide all other classes '''EVEN IF THEY ARE PUBLIC CLASSES'''. Suppose you want to develop a plugin to find clusters in a large network. You want to make your clustering algorithms accessible from other plugin developers. In that case, all you have to do is exporting the following interface:
OSGi is relatively complex technology, but the broad points that you should understand are as follows:

 1. OSGi's unit of modularity is the '''''bundle'''''. A '''''bundle''''' is simply a jar file with extra metadata included in the manifest.
 1. In Cytoscape 3, '''''everything is a bundle'''''. This means there is no longer a distinction between plugin and core.
 1. You must define which packages in your bundle are accessible to other bundles.
 1. You must define which classes are imported by your bundle. While seemingly cumbersome, this is generally automated and has the advantage of allowing you to specify specific version numbers of the library. OSGi allows different versions of the same library can exists in the same instance of a framework.
 1. Any java interface can serve as the definition of an '''''OSGi Service'''''. Any implementation of an interface can thus be registered as an instance of that service in the '''''OSGi Service Registry'''''. All bundles can access those registered services.

These solves several problems we had in version 2.x:
 * Plugins can now communicate in a well defined way with other plugins. Plugins developers can publish small set of public interfaces for other developers while hiding your implementation classes from other developers '''EVEN IF THEY ARE PUBLIC CLASSES'''.
 * Library version conflict. In Cytoscape 2, the entire application sometimes crashes due to library version conflicts. For example, if you use JAXB v2.0 in your plugin and other developer uses v2.1, the result is unpredictable. If we run Cytoscape on OSGi framework, this does not happen because you can specify which version of JAXB is required for your plugin and two different version of JAXB can run safely on the same JVM.
 * Cytoscape developers can hide implementation details that plugin writers shouldn't have to worry about. This will allow us to change implementation details without fear of breaking plugins.

Suppose you want to develop a plugin to find clusters in a large network. You want to make your clustering algorithms accessible from other plugin developers. In that case, all you have to do is exporting the following interface:
Line 36: Line 81:
    // Run my clustering algorithm and return clusters as a set of CyNetwork
    public Set<CyNetwork> getClusters(CyNetwork network);
    // Run my clustering algorithm for a given network "parent" and return clusters as a set of subnetworks.
    public Set<CyNetwork> getClusters(CyNetwork parent);
Line 42: Line 87:
 * Library version conflict
    * In Cytoscape 2, the entire application sometimes crashes due to library version conflict. For example, if you use JAXB v2.0 in your plugin and other developer uses v2.1, the result is unpredictable. If we run Cytoscape on OSGi framework, this does not happen because you can specify which version of JAXB is required for your plugin and two different version of JAXB can run safely on the same JVM.
 
Line 50: Line 94:

The diagram below shows the relationships between objects in Cytoscape 3 desktop application. In Spring, objects are defined as '''''beans'''''.
Line 52: Line 99:
The diagram above shows the relationships between objects in Cytoscape 3 desktop application. In Spring, objects are defined as '''''beans'''''.
Line 55: Line 102:

This diagram represents the '''cytoscapeDesktop''' bean, which is defined in a '''''Bean Configuration XML file''''':
Line 63: Line 112:
}}}

''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 [[http://www.springsource.org/osgi|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:

{{{#!java
public class ClusteringServiceUser {
  private ClusteringService service;

  public ClusteringServiceUser() {
     // Now ClusteringServiceUser depends on an implementation ClusteringServiceImpl.
    service = new ClusteringServiceImpl();
  }
}
}}}
This creates a dependency to specific implementation of !ClusteringService API. With Spring, we can avoid this dependency:

{{{#!java
    AbstractApplicationContext ctx
      = new ClassPathXmlApplicationContext(new String []{"bean-configuration.xml"});
    service = ctx.getBean("clusteringServiceBean");
}}}

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

{{{#!java
public class ClusteringServiceUser {
  private ClusteringService service;

  public ClusteringServiceUser(ClusteringService service) {
     // No dependency to frameworks!
    this.service = service;
  }

  // Sample client code to find clusters for each network passes as parameter.
  public Map<Integer, Set<CyNetwork>> analyzeNetwork(Set<CyNetwork> networks) {
    final Map<Integer, Set<CyNetwork>> clusterMap = new HashMap<Integer, Set<CyNetwork>>();

    for(CyNetwork net:networks) {
      clusterMap.put(net.getSUDI(), service.getClusters(net));
    }
    return clusterMap;
  }
}
}}}

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 [[http://en.wikipedia.org/wiki/POJO|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 [[http://ant.apache.org/|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.
 1. '''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 [[http://maven.apache.org/|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
Line 65: Line 216:
==== Separate Implementation from API ====
Spring is a powerful tool, but if we use '''''Spring Dynamic Modules (Spring DM)''''', we can take advantage of both Spring and OSGi.

If we use Spring DM, Cytoscape 3 code is '''independent from OSGi API and Spring API'''. This means all of the Cytoscape objects are [[http://en.wikipedia.org/wiki/POJO|POJOs]] and we can replace the framework later when necessary.
  
The most important design concept you need to understand to develop Cytoscape 3 code is '''''Interface-Oriented Design'''''. Since Cytoscape 3 is a ''platform'' rather than a stand-alone desktop application,
Because maven creates the basic directory structure, you do not have to configure details, such as location of source code, test cases, resource files, etc.
 
Also, Maven 2 has a very useful feature to import dependent libraries automatically over the internet. If you want to use library A, all you have to do is adding it to the ''pom.xml'' file. Then maven finds the dependent library for you.

Please try [[http://maven.apache.org/guides/getting-started/maven-in-five-minutes.html|this example]] to understand basic concept of Maven2.


= Working with Cytoscape 3 Code =
/!\ Need to update the sections below.

== Introduction ==
In this section, you are going to learn how to write Cytoscape 3 style code in the new building system.

== Create OSGi-Spring Based Project ==
 * [[Cytoscape_3.0/Developer/CreateProject|Minimal Spring-OSGi Project]]
 * [[Cytoscape_3.0/Developer/PortModules|Port Non-OSGi projects to OSGi+Spring DM environment]]
 * [[Cytoscape_3.0/Developer/TestWithSpring|Unit/Integration test with Spring, EasyMock, and JUnit4)]]
Line 119: Line 281:

== Books ==
=== Spring ===
 * [[http://www.apress.com/book/view/1590599799|Spring Recipes]] - Nice ''cookbook''-style introduction to Spring framework and related projects. Based on 2.5.
 * [[http://www.manning.com/walls3/|Spring In Action]] - Based on version 2, but still good introduction to the framework.

=== Spring DM and OSGi ===
 * [[http://www.apress.com/book/view/1430216123|Pro Spring Dynamic Modules for OSGi™ Service Platforms]] - As far as I know, the only book which covers both Spring and OSGi.

=== Maven ===
 * [[http://www.sonatype.com/products/maven/documentation/book-defguide|Maven: The Definitive Guide]] - The best Maven 2 book on market, and online version is '''free'''!

----
Questions? Please e-mail me (kono_at_ucsd_edu)

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

  • 1st draft of concept guide finished - Kei (3/10/2009)
  • Concept guide section updated - Kei (3/11/2009)

Cytoscape 3 Design Concept

Introduction

A central goal of Cytoscape 3 is to make a more modularized, expandable, and maintainable version of Cytoscape. To achieve this goal, we follow several design principles and take advantage of three new technologies:

These technologies are very powerful, but you'll need to understand a few new concepts to use them easily and effectively. The purpose of this document is to introduce the new design concepts that you will need to develop Cytoscape 3 code.

Why Do We Have To Learn These New Technologies?

Cytoscape 2.x has several architectural problems. They are:

  • There is no clear module structure and thus many circular dependencies.
  • Unnecessary packages are open to public access. This results in broken plugins every time core developers update code we thought no one was using!
  • Cytoscape 2.x has a package dependency graph that looks like this:
    • (insert graph here)
  • View and model are tightly coupled in many places and make it hard to run in command line mode or as a server backend.
  • There is no mechanism for allowing plugins to communicate with each other.
  • Cytoscape has no mechanism for supporting different versions of libraries causing conflicts between plugins.

Central to each of these problems is a lack of a module system. Unfortunately, Java lacks an effective mechanism for defining modules. To address this need, we have decided to use OSGi as a mechanism for enforcing modularization. While OSGi provides many benefits, its most important is that it provides a new scoping mechanism that allows java packages to be declared public or private. This is accomplished by adding a few lines of metadata to the manifest file of a jar. Aside from the metadata the jars (which OSGi calls bundles) are normal java jar files.

OSGi developers have built upon this scoping mechanism and developed a framework (i.e. the Service Registry) as well as design patterns that allow developers to write very clean and simple code. Taking advantage of this framework, however, requires knowledge of and use of the OSGi API, which is not necessarily a simple thing. Dealing with this concern brings us to Spring.

Spring (specifically Spring Dynamic Modules) allows us to remove all OSGi dependencies from our code yet still take advantage of the Service Registry and other OSGi features. This means that you continue to write normal java POJOs. The cost is that your code is now initialized using Spring XML configuration code.

Finally, because OSGi breaks applications into many jars (called bundles) with dependencies and version numbers we have decided to use a build tool that has an explicit model for dealing with dependencies: Maven. You can think of Maven as a formalized version of Ant or even make. Unlike other tools, Maven provides a simple structure for declaring and using dependencies. We will take advantage of Maven's dependency handling to simplify the Cytoscape build process.

Important Design Principle of Cytoscape 3

Interface Oriented Design

Fundamental throughout Cytoscape 3 and OSGi is it's enforcement ofInterface Oriented Design. Rather than make both interfaces and implementations publicly available, Cytoscape 3 will only make interfaces public. All implementations of interfaces will be hidden in internal packages and will only be available through the OSGi Service Registry and Spring. The benefit of this approach is that you only need to concern yourself with an interface. You will never need to worry about specific implementation details. As long as you code to the interface, your code should continue to work.

From a plugin writer's perspective, you should:

  1. Hide unnecessary classes and only expose a limited number of interfaces. This makes your module (plugin) easy-to-use for other developers. OSGi provides the enforcement mechanisms for this.
  2. Separate implementation from API. This makes it 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 for this job.

Dependency Injection

An important aspect of Cytoscape 3 development is the idea of Dependency Injection. In practical terms, this means that all dependencies for your classes should be specified in your constructor and you should no longer be creating (most) objects on your own.

For instance, if you need to create a new CyNetwork you will not call the constructor of a particular implementation of the CyNetwork interface. Instead you will have a CyNetworkFactory injected into your class (via its constructor) and then you will ask CyNetworkFactory to provide you with a new instance of CyNetwork. The benefit of this approach is that you never see the implementation of CyNetwork which frees us from a particularly onerous dependency - the ability to change implementation easily.

Micro Core Architecture

In Cytoscape 3, all modules are equal and there is no clear distinction between Core and Plugins. Instead of running Cytoscape on the top of Java Virtual Machine, we will insert one extra layer called the OSGi runtime. Cytoscape 3 is simply a set of bundles running on top of an OSGi micro core.

The diagram above shows overall architecture of Cytoscape 3. The most important point is that all of the inter-bundle communication is managed by the OSGi service registry, meaning through interfaces only, and not through concrete classes.

architecture1.png

OSGi

OSGi is relatively complex technology, but the broad points that you should understand are as follows:

  1. OSGi's unit of modularity is the bundle. A bundle is simply a jar file with extra metadata included in the manifest.

  2. In Cytoscape 3, everything is a bundle. This means there is no longer a distinction between plugin and core.

  3. You must define which packages in your bundle are accessible to other bundles.
  4. You must define which classes are imported by your bundle. While seemingly cumbersome, this is generally automated and has the advantage of allowing you to specify specific version numbers of the library. OSGi allows different versions of the same library can exists in the same instance of a framework.
  5. Any java interface can serve as the definition of an OSGi Service. Any implementation of an interface can thus be registered as an instance of that service in the OSGi Service Registry. All bundles can access those registered services.

These solves several problems we had in version 2.x:

  • Plugins can now communicate in a well defined way with other plugins. Plugins developers can publish small set of public interfaces for other developers while hiding your implementation classes from other developers EVEN IF THEY ARE PUBLIC CLASSES.

  • Library version conflict. In Cytoscape 2, the entire application sometimes crashes due to library version conflicts. For example, if you use JAXB v2.0 in your plugin and other developer uses v2.1, the result is unpredictable. If we run Cytoscape on OSGi framework, this does not happen because you can specify which version of JAXB is required for your plugin and two different version of JAXB can run safely on the same JVM.
  • Cytoscape developers can hide implementation details that plugin writers shouldn't have to worry about. This will allow us to change implementation details without fear of breaking plugins.

Suppose you want to develop a plugin to find clusters in a large network. You want to make your clustering algorithms accessible from other plugin developers. In that case, all you have to do is exporting the following interface:

   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 
  • If you export this as OSGi service, other developers can easily access your clustering algorithms programatically (or even from scripts because it's a part of Cytoscape 3 function). In addition, you can modify its implementation later without breaking other plugins because you are exposing interface (API) only and its implementation is completely hidden.

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

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

spring1.png

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, you do not have to configure details, such as location of source code, test cases, resource files, etc.

Also, Maven 2 has a very useful feature to import dependent libraries automatically over the internet. If you want to use library A, all you have to do is adding it to the pom.xml file. Then maven finds the dependent library for you.

Please try this example to understand basic concept of Maven2.

Working with Cytoscape 3 Code

/!\ Need to update the sections below.

Introduction

In this section, you are going to learn how to write Cytoscape 3 style code in the new building system.

Create OSGi-Spring Based Project

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.

  • OSGi - Cytoscape will be modularized by following this standard.
    • OSGi in Practice

    • OSGi Alliance

    • Apache Felix: Although OSGi is implementation-independent, this implementation will be used as standard development/testing tool.

    • OPS4J Products: This project has a lot of usuful scripts to develop OSGi bundles

    • SpringSource Bundle Repository: To use existing plain JAR libraries in an OSGi environment, we need to add metadata to it. This repository is a collection of OSGi-ed popular libraries, i.e., repository of OSGi bundles managed by Spring Source.

  • Dependency Injection Frameworks - One of the scopes of 3.0 is modulalization and make Cytoscape usable as a part of other programs, including server-side application or command -line tools. The following DI frameworks are POJO-base and popular among server-side application developers.
  • Apache Maven: 3.0 project will be moved from Ant to Maven.

  • Server-Side / SCA - Once Cytoscape is modulalized based on OSGi, we can use Cytoscape bundles and these frameworks to build server-side applications or web services.
  • Scripting Language Support - There are several implementations of scripting languages running on JVM. These will be used to implement scripting feature in Cytoscape.

Developer's Tutorials and References

For Eclipse Users

Basic Tutorial

Optional

For Netbeans Users

Other OSGi Tools and Technical Notes

Books

Spring

  • Spring Recipes - Nice cookbook-style introduction to Spring framework and related projects. Based on 2.5.

  • Spring In Action - Based on version 2, but still good introduction to the framework.

Spring DM and OSGi

Maven


Questions? Please e-mail me (kono_at_ucsd_edu)

Outdated_Cytoscape_3.0/Developer (last edited 2011-02-24 16:16:23 by PietMolenaar)

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