Page tree

Versions Compared

Key

  • This line was added.
  • This line was removed.
  • Formatting was changed.

This article describes extending Integrated Genome Browser using the weblinks module as an example.

...

Prerequisites

You must have a basic understanding of the maven project management tool. If you're new to Maven:

...

maven and Java syntax. See Maven in five minutes

...

Table of Contents

Introduction to weblinks module

The Weblinks module enables users to link annotation features to Web-based resources using regular expressions. for a quick introduction to maven.

About Weblinks

When users right-click an annotation, they see a context menu appears containing that contains one or more links to external resources. It accomplishes this feat by allowing regular expression patterns to options called "linkouts," menus that run a Google Web search or open a Web page related to the selected item on some external site. The Weblinks module is responsible for creating and adding linkout menu items to the context menu.

The Weblinks module also lets users create all-new custom linkouts using regular expressions. It accomplishes this feat by allowing regular expression patterns to be applied to the annotation or track currently selected to dynamically populate a context menu for a given selection.  If an annotation or track id matches a user-defined pattern, then IGB creates a linkout menu item with URL defined in the custom linkout

Where the Weblinks hooks into IGB

The Weblinks module has two user interface hooks into the IGB application.

  1. The IGB Toolbar
    1. Image Removed
      1. Clicking this menu item results in the following window being displayed
        1. Image Removed
  2. The right click context menu of annotations selected in the Data Display Area.
    1. Image Removed

 

Creating the Maven project

As of this writing, we have not yet supplied any Maven archetypes to generate the scaffolding of new IGB plugins (stay tuned); however, it is very easy to get started with little more work than setting up any generic Maven project.  

Directory Structure

We do not deviate from the standard Maven project structure, so the directory structure of the Weblinks module should look very familiar.

Image Removed

Setting up the pom.xml

...

  1. menu contains a menu option labeled Configure Web Links. This is the first hook.
    1. Image Added
  2. Selecting Configure Web Links opens the Web links configuration window. IGB includes several built-in linkout patterns in the top section. The middle section contains user-defined Custom Web Links.
    1. Image Added
  3. When users right-click an annotation, a context menu appears that contains menu items for each matching Web Link pattern. This is the second hook. Note that if only one Web Link pattern matches, it appears in the main menu, not in sub menus as shown below. 

 

    1. Image Added

 

...

Web links project and directory structure

The Web Links module, like all other modules in IGB, uses maven to compile and deploy the web links jar file, called an "artifact." The Web Links project resides in the IGB code repository. It uses the same directory structure as any other maven-based project. The following image shows Web Links directory structure within the larger IGB project:

Image Added

...

Project configuration file - pom.xml

Lets look at the basic structure of the pom.xml of the Weblinks Module and then dissect its content.

...

languagexml
titleWeblinks pom.xml
firstline1
linenumberstrue

...

Parent Tag

Code Block
languagexml
<parent>
   <groupId>com.affymetrix</groupId>
   <artifactId>igb-project</artifactId>
   <version>8.4.0</version>
   <relativePath>../../pom.xml</relativePath>
</parent>

The parent tag here is important as the mechanism by which dependency inheritance is able to be calculated.  See https://maven.apache.org/guides/introduction/introduction-to-dependency-mechanism.html for more details on how the inheritance mechanism in Maven works.  The benefits will be obvious when we discuss the dependency tag below.

Packaging Tag  

Code Block
languagexml
<packaging>bundle</packaging>

...

You may have noticed we are using a non traditional packaging type of "bundle" which takes advantage of the pluggable architecture of Maven itself and the custom packaging type which is defined in the Apache Felix Maven Bundle Plugin.  Throughout the IGB project we use this maven plugin to generate all of the OSGi meta-data which makes are jar a module in the OSGi runtime.  

Dependencies Tag

This section will highlight some of the important dependencies used in this module. 

biz.aQute.bnd:bndlib

Code Block
languagexml
<dependency>
   <groupId>biz.aQute.bnd</groupId>
   <artifactId>bndlib</artifactId>
   <scope>provided</scope>
</dependency>

This dependency contains the Declarative Services annotations used throughout the IGB project and its use will be highlighted further in a discussion of the services provided by the Weblinks bundle. Note the lack of a version tag, and the inclusion of the scope tag with the value provided (note compile would also be an appropriate scope in this instance, so either/or).  The reason the version tag is not included is because this is a library with a version already declared in the dependencyManagement tag of the parent pom, so it is inherited.  

 

com.affymetrix:genometry

Code Block
languagexml
<dependency>
       <groupId>com.affymetrix</groupId>
       <artifactId>genometry</artifactId>
       <scope>provided</scope>
</dependency>  

This dependency is a module which contains many utility classes and much of the core data model content of the IGB project.  In the case of the Weblinks module, much of the logic which drives the dynamic content of the context menu is derived from the selections a user makes in the Data Display Area and these selections are represented by the data model object types defined in the genometry module.  

com.affymetrix:igb-services

Code Block
languagexml
<dependency>
       <groupId>com.affymetrix</groupId>
       <artifactId>igb-services</artifactId>
       <scope>provided</scope>
</dependency> 

This module is an API module which contains most of the service interfaces which allow hooks into the IGB platform.  The Weblinks modules implements several of the interfaces contained in this module.  This will be discussed in more detail below.

com.affymetrix:igbSwingExt

Code Block
languagexml
<dependency>
     <groupId>com.affymetrix</groupId>
     <artifactId>igbSwingExt</artifactId>
     <scope>provided</scope>
</dependency> 

This module contains many custom swing components which are commonly used throughout the project.  In some cases the interfaces contained in the igb-services modules require the use of some of the custom swing components contained in this module.  We do this because we often have the need to add additional functions to basic swing components (e.g. weight for Menu Items to allow sorting in the context of a pluggable system).

com.google.guava:guava

Code Block
languagexml
<dependency>
   <groupId>com.google.guava</groupId>
   <artifactId>guava</artifactId>
   <scope>provided</scope>
</dependency> 

A very useful utility module which is used extensively in our project.  We highly recommend you take a look at the content of this project (see https://code.google.com/p/guava-libraries/), and occasionally even demmand in our interfaces you leverage some of the collection data structures from Guava (e.g. Multimap). You will thank us later!

org.slf4j:slf4j-api

Code Block
languagexml
<dependency>
    <groupId>org.slf4j</groupId>
    <artifactId>slf4j-api</artifactId>
    <scope>provided</scope>
</dependency>

This module is the logging API we expect all module developers to use to hook into our logging system.  For more information see http://www.slf4j.org/manual.html

Other Dependencies

A discussion of the remaining dependencies are omitted since they are primarily specific to the content of this specific module.

Maven Plugins

maven-clean-plugin

The utility of this plugin in our pom is largely context specific.  In our case, we are simply  hooking into the clean phase of the maven lifecycle to delete a copy of the compiled module we make using the maven-dependency-plugin.  

maven-dependency-plugin

Again, the utility of this plugin is specific to the context of our build, but this plugin is used to hook into the install phase of the maven lifecycle and make a copy of the module in a location where we will later have OSGi install it during development runs.  

maven-bundle-plugin

This is the most important plugin to be aware of as an IGB module developer.  This plugin is a wrapper around the bnd project which is known as the "Swiss army knife of OSGi".

Code Block
languagexml
<plugin>
     <groupId>org.apache.felix</groupId>
     <artifactId>maven-bundle-plugin</artifactId>
     <extensions>true</extensions>
     <configuration>
         <instructions>
             <Bundle-SymbolicName>${project.artifactId}</Bundle-SymbolicName>
             <Import-Package>*</Import-Package>
             <Export-Package/>
             <Service-Component>*</Service-Component>
         </instructions>
     </configuration>
</plugin> 

Instructions Tag

Bundle-SymbolicName 

This tag is used to provide the unique module name which will be used by OSGi along with the version to identify your module.

Import-Package

We use a wildcard import in this tag to specify we want to let bnd leverage Maven to populate the imports of our OSGi Manifest file. For more information on this tag see http://wiki.osgi.org/wiki/Import-Package

Export-Package

We include this tag here mostly for reference, and as you can see, we do not specify any exports from this implementation module.  This means no classes from this module will ever be available to other modules and we have successfully hidden all of our implementation details.

Service-Component

This is a special tag which instructs the felix bundle plugin to scan our modules classes for the Declarative Service annotations and generate the required service descriptor meta-data for OSGi.  For more information on this topic see http://wiki.osgi.org/wiki/Service-Component and http://www.aqute.biz/Bnd/Components

Weblinks Use of IGB-Services

IgbService

IgbService is a collection of useful utilities provided by IGB to modules for reference.  In the case of the Weblinks module, this service is used to register itself as a "ContextualPopupListener" and for little else.  Its worth pointing out that this would not be necessary if the ContextualPopupListener instances were tracked using the OSGi service registry, but since we cannot migrate the entire project to OSGi services all at once this more manual listener registration mechanism is still in use at this location. 

How IgbService is accessed

Weblinks accesses the IgbService implementation from the service registry. There are several ways this could be done; however, our preferred way to access services is with the use of the Declarative Service annotations referenced earlier in this article.  

...

In the above code block, you can see the @Component annotation is used to declare that this class will be managed as a component by the OSGi runtime.  See the Declarative Services specification for more details (http://wiki.osgi.org/wiki/Declarative_Services).  Next, there is the creation of a privately scoped IgbService variable along with a setter for this variable.  The setter is annotated with the @Reference annotation to signal to the OSGi component runtime that this setter in an injection point for another component managed by the runtime.  When IgbService becomes available it will be "injected" (in the dependency injection sense of the terminology) into this service for reference before the component is "Activated".  As you can see, there is an activate method annotated with the @Activate annotation to signal that this method should be called once all service dependencies have been satisfied.  The content of the method makes it clear that the igbService variable must have been instantiated before this reference.  This short block of code is a great example of the power of Declarative Services to manage the lifecycle of our services.  With almost no work, we can publish and consume services from the registry.

IgbMenuItemProvider

This interface is designed allow module developers to hook into the applications main toolbar.

...

The interface is simple enough, but the getParentMenuName method will likely not return a String literal in the eventual 1.0 release of our API (a custom enum type would be more appropriate).  

Weblinks use of IgbMenuItemProvider

The WebLinksAction class implements this interface resulting in the following menu item being created.

WindowServiceLifecycleHook

This interface allows a module to hook into the global application lifecycle events of startup and shutdown.  In the case of the Weblinks module, we want to be signaled about the application shutdown in order to export any user generated "Linkouts".  

Weblinks use of WindowServiceLifecycleHook

Code Block
languagejava
@Component(name = WebLinkExportRoutine.COMPONENT_NAME, immediate = true, provide = WindowServiceLifecycleHook.class)
public class WebLinkExportRoutine implements WindowServiceLifecycleHook {
    private static final Logger logger = LoggerFactory.getLogger(WebLinkExportRoutine.class);
    public static final String COMPONENT_NAME = "WebLinkExportRoutine";
    private WebLinkExporter exporter;
    public WebLinkExportRoutine() {
    }
    @Override
    public void stop() {
        if (exporter != null) {
            exporter.exportUserWebLinks();
        }
    }
    @Override
    public void start() {
    }
    @Reference
    public void setWebLinkUtils(WebLinkExporter exporter) {
        this.exporter = exporter;
    }
}

...