3683
Comment:
|
13496
|
Deletions are marked like this. | Additions are marked like this. |
Line 1: | Line 1: |
{{http://www.cytoscape.org/images/logo.png}} {{http://www.osgi.org/www/osgi_logos_supporter_final.png}} {{http://static.springframework.org/images/spring25.png}} |
|
Line 3: | Line 5: |
<<TableOfContents>> == Status == * 1st draft of concept guide finished - Kei (3/10/2009) = Cytoscape 3 Design Concept = == Introduction == 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. == Why Do We Have To Learn These New Technologies? == 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. === 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. 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: {{{#!java public interface ClusteringService { // Run my clustering algorithm and return clusters as a set of CyNetwork public Set<CyNetwork> getClusters(CyNetwork network); } }}} 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. * 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. === 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 ==== {{attachment:spring1.png}} The diagram above shows the relationships between objects in Cytoscape 3 desktop application. In Spring, objects are defined as '''''beans'''''. {{attachment: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 [[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; } } }}} 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 Spling 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. == The Most Important Design Principle of Cytoscape 3 == === Interface Oriented Design and Implementation === 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 sections below needs to be updated. = Working with Cytoscape 3 Code = |
|
Line 51: | Line 199: |
== 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) |
Cytoscape 3 Developer's Guide
Contents
Status
- 1st draft of concept guide finished - Kei (3/10/2009)
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.
Why Do We Have To Learn These New Technologies?
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.
OSGi
OSGi is relatively complex technology, but important points you need to understand for Cytoscape 3 development are only four:
OSGi framework manages modules as bundle. Bundle is a new kind of JAR files with set of metadata.
In Cytoscape 3, everything is a bundle. The border between plugin and core is very ambiguous.
- 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.
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:
1 public interface ClusteringService {
2 // Run my clustering algorithm and return clusters as a set of CyNetwork
3 public Set<CyNetwork> getClusters(CyNetwork network);
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.
- 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.
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 above shows the relationships between objects in Cytoscape 3 desktop application. In Spring, objects are defined as beans.
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
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 Spling 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.
The Most Important Design Principle of Cytoscape 3
Interface Oriented Design and Implementation
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 sections below needs to be updated.
Working with Cytoscape 3 Code
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.
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.
Google Guice: Currently focused on DI only.
Spring Framework: De facto standard framework for DI and AOP.
Spring-DM: Integration of Spring Framework and OSGi
Apache Maven: 3.0 project will be moved from Ant to Maven.
Maven Repository Search - Note: Cytoscape cannot use most of these libraries directly. To use these, they should be re-packed as an OSGi bundle.
- 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.
Apache Tuscany: An open-source implementation of Service Component Architecture.
SpringSource Application Platform: OSGi-Spring powered application server.
- Scripting Language Support - There are several implementations of scripting languages running on JVM. These will be used to implement scripting feature in Cytoscape.
JRuby: Ruby scripting language running on JVM. Actively developed by Sun.
Rhino: JavaScript. Bundled with Java SE 6.
Jython: Python implementation.
Developer's Tutorials and References
For Eclipse Users
Basic Tutorial
Optional
Create Cytoscape 3 plugin from Maven Archetype (incomplete)
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
Pro Spring Dynamic Modules for OSGi™ Service Platforms - As far as I know, the only book which covers both Spring and OSGi.
Maven
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)