Page tree

Versions Compared

Key

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

...

You must have a basic understanding of maven and Java syntax. See Maven in five minutes for a quick introduction to maven.

About

...

Web Links

When users right-click an annotation, they see a context menu that contains one or more 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

...

Web Links module hooks into IGB

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

...

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 Modified

...

Project configuration file - pom.xml

...

Code Block
languagexml
<parent>
   <groupId>com.affymetrix</groupId>
   <artifactId>igb-project</artifactId>
   <version>8.46.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 specifies compatibility with IGB (version 8.6.0 is supported), identifies the project and artifact, and identifies the parent POM using a relative path. 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.

...

Code Block
languagexml
<packaging>bundle</packaging>

 

You may have noticed we We are using a non traditional packaging type of "bundle" which takes to take 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 the jar file into a module that can be managed in the IGB OSGi runtime.  

Dependencies Tag

...

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 . These selections are represented by the data model object types defined in the genometry module.  

...

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.

...

com.lorainelab:context-menu-api

Code Block
languagexml
<dependency>
   <groupId>com.lorainelab</groupId>
   <artifactId>context-menu-api</artifactId>
   <scope>provided</scope>
</dependency>

This module defines the interfaces and methods Web Links must implement in order to add items to the annotation context (right-click) menu.

 

Build and plugins section

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 the 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 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.  @Component annotation.

Code Block
languagejava
titleExample of Service Access Using DS
linenumberstrue
@Component(name = LinkControl.COMPONENT_NAME, immediate = true)
public class LinkControl implements ContextualPopupListenerAnnotationContextMenuProvider {

    publicprivate static final String COMPONENTSEARCH_WEB_NAMEICONPATH = "LinkControlsearchweb.png";
    private static final String searchWebIconPathorg.slf4j.Logger logger = "16x16/actions/searchweb.png";LoggerFactory.getLogger(MenuIcon.class);    
    private IgbService igbService;

    public LinkControl() {
    }
    @Activate
    private void activate() {
        igbService.getSeqMapView().addPopupListener(this);
    }
    @Reference
    public void setIgbService(IgbService igbService) {
        this.igbService = igbService;
    }
...

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 

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   

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.

...