Page tree

Versions Compared

Key

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

...

To see the directory structure for your project in NetBeans, select the Files tab (next to the Projects tab).

Info

Many Apps will include image files and other content. To include these, create a directory named "resources" at the same level as the pom.xml file, as seen in the image above. is this accurate???

 

HelloWorld pom.xml

***Need explanation of what the app's pom.xml file is for***

...

Code Block
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <parent>
        <groupId>com.affymetrix</groupId>
        <artifactId>igb-project</artifactId>
        <version>9.0.0</version>
    </parent>
    <groupId>org.lorainelab.igb</groupId>
    <artifactId>org.lorainelab.igb.menu.api.example</artifactId>
    <version>1.0.0</version>
    <packaging>bundle</packaging>

    <name>IGB Menubar Extension</name>
    
    <dependencies>
        <dependency>
            <groupId>biz.aQute.bnd</groupId>
            <artifactId>bndlib</artifactId>
            <scope>provided</scope>
        </dependency>
          <dependency>
            <groupId>org.lorainelab.igb</groupId>
            <artifactId>org.lorainelab.igb.menu.api</artifactId>
            <scope>provided</scope>
        </dependency>
    </dependencies>

    <build>
        <plugins>
            <plugin>
                <groupId>org.apache.felix</groupId>
                <artifactId>maven-bundle-plugin</artifactId>
                <extensions>true</extensions>
                <executions>
                    <execution>
                        <id>build plugin repository</id>
                        <goals>
                            <goal>
                                index
                            </goal>                       
                        </goals>
                        <phase>package</phase>
                        <configuration>
                            <obrRepository>${project.build.directory}</obrRepository>    
                            <mavenRepository>${project.build.directory}</mavenRepository>                      
                        </configuration>
                    </execution>
                </executions>
                <configuration>
                    <instructions>
                       <Bundle-SymbolicName>${project.artifactId}</Bundle-SymbolicName>
                        <Import-Package>*</Import-Package>
                        <Export-Package/>
                        <Service-Component>*</Service-Component>
                    </instructions>
                </configuration>
            </plugin>     
        </plugins>
    </build>
</project>



 

parent tag

The parent tag specifies which version of IGB your new App is compatible with. It also enables your project to inherit configurations from the parent pom.xml file, which will save you time and effort.
The version found in the parent tag of the App's pom.xml should match the version tag found in the IGB pom.xml at the top level of your cloned IGB project.
For example, if the IGB pom.xml contains version tag equal to 9.0.0, then the parent tag of the App's pom.xml should match the tag below.

 

Code Block
languagexml
<parent>
     <groupId>com.affymetrix</groupId>
     <artifactId>igb-project</artifactId>
     <version>8<version>9.60.0</version>
</parent>


In the image below, you can see that the IGB version in IGB project of 9.0.0 is seen in the app's pom.xml:.


packaging tag

This tag specifies packaging type - e.g., war or jar. In IGB, we use an OSGi-specific packaging structure called a "bundle," which is a jar file with additional metadata. This additional metadata transforms an ordinary jar file into a plug-able module in the OSGi runtime. The IGB project uses the Apache Felix Maven Bundle plugin (BND) to generate this metadata. The BND bundle defines the packaging type "bundle."

...

Code Block
languagexml
titlepom.xml
<name>Hello<name>IGB Menubar World<Extension</name>

dependency tags (parent tag "dependencies")

...

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

...

com.

...

affymetrix:

...

igb-

...

services

This module is an API module that contains most of the service interfaces which provide access (hooks) to functions in the IGB platform, such as identifying the currently selected feature or tracks.  

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

com.affymetrix:

...

igbSwingExt

This module is an API module that contains most of the service interfaces which provide access (hooks) to functions in the IGB platform, such as identifying the currently selected feature or tracks.  contains custom Swing components used in the IGB graphical user interface. 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, such as the concept of "weights" for menu items to ensure that newly added menu options appear in the correct order. 

 

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

com.affymetrix:igbSwingExt

This module contains custom Swing components used in the IGB graphical user interface. 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, such as the concept of "weights" for menu items to ensure that newly added menu options appear in the correct order. 

 

...

languagexml

...

 

build, plugins, and plugin tag

maven-bundle-plugin

This is the most important plugin to be aware of as an IGB module developer.  This plugin is known as the "Swiss army knife of OSGi" and is a wrapper around the BND project described in the previous section.

Code Block
languagexml
	<build>
        <plugins>
            <plugin>
                <groupId>org.apache.felix</groupId>
                <artifactId>maven-bundle-plugin</artifactId>
     <scope>provided</scope>
</dependency> 

 

build, plugins, and plugin tag

maven-bundle-plugin

This is the most important plugin to be aware of as an IGB module developer.  This plugin is known as the "Swiss army knife of OSGi" and is a wrapper around the BND project described in the previous section.

Code Block
languagexml
           <build><extensions>true</extensions>
        <plugins>
        <executions>
    <plugin>
                <groupId>org.apache.felix</groupId><execution>
                <artifactId>maven-bundle-plugin</artifactId>
          <id>build plugin     <extensions>true</extensions>repository</id>
                <executions>
        <goals>
            <execution>
                <goal>
        <id>build plugin repository</id>
                        <goals>index
                            <goal>
         </goal>                       index
                            </goal>goals>
                        <phase>package</phase>
                        </goals><configuration>
                          <phase>package</phase>
                        <configuration>
                            <obrRepository>${project.build.directory}</obrRepository>     
                            <mavenRepository>${project.build.directory}</mavenRepository>                       
                        </configuration>
                    </execution>
                </executions>
                <configuration>
                    <instructions>
                        <Bundle-SymbolicName>${project.artifactId}</Bundle-SymbolicName>
                        <Import-Package>*</Import-Package>
                        <Export-Package/>
                        <Service-Component>*</Service-Component>
                    </instructions>
                </configuration>
            </plugin>         
        </plugins>
    </build>


There are several important things to understand about the above configuration.

...

 

This deployment mode will allow you to install and un-install your App bundle without having to restart IGB. This means you can make changes to your IGB App, recompile it, and then simply re-install it without restarting IGB. This is why we now call IGB a programming "platform" - it functions like a development environment. Like any good development tool, you don't have to restart it to run new code. 

...

Adding a new item to the IGB Tools menu 

To demonstrate how an IGB plugin could hook into and expand the IGB toolbar, you will can write a new class that implements the IgbMenuItemProvider the MenuBarEntryProvider interface.

This interface is designed to allow App developers to add new menu items to the IGB application's top level menus.

IGB (as of this writing) has seven top-level menus, including:

 

 

The IgbMenuItemProvider The MenuBarEntryProvider interface contains the following methods, shown below. To add a new menu item to IGB, you'll create a class that implements this interface. In other words, you'll create a class that provides an IGB menu item to the OSGi run-time, which will add it to IGB as soon as it becomes available.

 

Code Block
languagejava
titleIgbMenuItemProviderMenuBarEntryProvider
public interface IgbMenuItemProviderMenuBarEntryProvider {
    public IgbToolBarParentMenuOptional<List<MenuItem>> getParentMenugetMenuItems();
    	public JRPMenuItemMenuBarParentMenu getMenuItemgetMenuExtensionParent();
    public int getMenuItemWeight();
 }

 

Note that this interface will likely change in future releases of the IGB API. The getParentMenuName method will likely a custom enum type and not a String literal.  Additionally, we will add "weight" as an attribute to our custom JMenuItem class.  So it is likely this interface will ultimately contain one simple getMenuItem() method.  

Create  new Java class IgbToolbarExtension 

Within NetBeans, check that your "hello world" IGB Menubar Extension project is the currently selected project - the name of the currently opened project is shown on the NetBeans title bar. If it isn't, select File > Open Project to open it.

Next, create a new Java class named IgbToobarExtension:

  • Select File > New File
  • Under Choose File Type, select Java
  • Select Next
  • Enter class Name IgbToolbarExtension MenuBarExtensionExample
  • Select package comorg.lorainelab.pluginigb.menu.api.example
  • Select Finish

Edit your file to match the following code into your new Java class file.

Note that NetBeans has added the package and class declarations.

 


Code BlocklanguageYour newly created class should match the code sen below:

 

Code Block
languagejava
package comorg.lorainelab.plugin;

import aQute.bnd.annotation.component.Component;
import com.affymetrix.igb.swing.JRPMenuItem;
import com.lorainelab.igb.services.window.menus.IgbMenuItemProvider;
import com.lorainelab.igb.services.window.menus.IgbToolBarParentMenu;
import java.awt.event.ActionEvent;
import javax.swing.AbstractAction;
import static javax.swing.Action.MNEMONIC_KEY;
import static javax.swing.Action.SHORT_DESCRIPTION;
import javax.swing.ImageIcon;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

// annotations processed by BND tool
@Component(name = IgbToolbarExtension.COMPONENT_NAME, immediate = true, provide = IgbMenuItemProvider.class)
public class IgbToolbarExtension implements IgbMenuItemProvider {
    public static final String COMPONENT_NAME = "IgbToolbarExtension";
    private static final Logger logger = LoggerFactory.getLogger(IgbToolbarExtension.class);
    private static final int MENU_ITEM_INDEX = 4;
    private final JRPMenuItem exampleMenuItem;
    public IgbToolbarExtension() {
        exampleMenuItem = new JRPMenuItem("exampleIgbToolbarMenuItem", new LogEventAction(), MENU_ITEM_INDEX);
    }

    @Override
    public JRPMenuItem getMenuItem() {
        return exampleMenuItem;
    }
 
    @Override
    public IgbToolBarParentMenu getParentMenu() {
        return IgbToolBarParentMenu.TOOLS;
    }
    @Override
    public int getMenuItemWeight() {
        return MENU_ITEM_INDEX;
    }
    private class LogEventAction extends AbstractAction {
        public LogEventAction() {
            this("Hello IGB Toolbar", null, "", null);
        }
        public LogEventAction(String text, ImageIcon icon,
                String desc, Integer mnemonicmenu.api.example;
import aQute.bnd.annotation.component.Component;
import java.util.Arrays;
import java.util.List;
import java.util.Optional;
import javax.swing.JOptionPane;
import org.lorainelab.igb.menu.api.MenuBarEntryProvider;
import org.lorainelab.igb.menu.api.model.MenuBarParentMenu;
import org.lorainelab.igb.menu.api.model.MenuItem;
@Component(immediate = true)
public class MenuBarExtensionExample implements MenuBarEntryProvider {

    @Override
    public Optional<List<MenuItem>> getMenuItems() {
        MenuItem menuItem = new super(text, icon);MenuItem("Hello World App", (Void t) -> {
            putValue(SHORT_DESCRIPTION, descJOptionPane.showMessageDialog(null, "Hello IGB World!");
            putValue(MNEMONIC_KEY, mnemonic)return t;
        }});
        @OverridemenuItem.setWeight(1000000000);
        public void actionPerformed(ActionEvent e) {return Optional.ofNullable(Arrays.asList(menuItem));
    }

    @Override
    logger.info("Hello Igb Toolbar menu item clicked");
public MenuBarParentMenu getMenuExtensionParent() {
          }return MenuBarParentMenu.TOOLS;
    }
}
 
Info

Note that NetBeans adds the package and class declarations automatically.

About the implementation class

The @Component annotation 

Code Block
languagejava
@Component(name = IgbToolbarExtension.COMPONENT_NAME, immediate = true, provide = IgbMenuItemProvider.class)
public class IgbToolbarExtension implements IgbMenuItemProvider {...}

This annotation is processed by the felix maven-bundle-plugin (BND) and declares that the OSGi runtime will manage creation and destruction of any instances of this class. This is an important point to understand about how OSGi-based applicaitions function. Your code will not directly manage the life cycle of your class. Instead, you specify the behavior and lifecycle of your objects using annotations.

The immediate=true annotation attribute specifies to the OSGi runtime that this component should be instantiated immediately instead of lazily. 

See http://www.aqute.biz/Bnd/Components for more information about the annotation attributes.

The LogEventAction

When a user selects your new menu item, this action will execute. Note it prints a message to the IGB console. Note also that it uses the SLF4j API to log events to the IGB console.