Creating an IBM Lotus Notes 8.0 and later plug-in for IBM Multimedia Library

This article explains how to create an extension for IBM® Lotus Notes® 8.0 and later that allows you to open a preconfigured URL (for example, Lotus Notes Multimedia Library) in a newly opened browser window by selecting a menu entry in the Help menu.

Share:

Robert Schneider, IT-Specialist, IBM Software Services for Lotus, IBM Deutschland GmbH, IBM

Robert Schneider works as an IT-Specialist for the IBM Lotus software services department in Germany. He is a leading architect in several projects developing solutions based on Lotus Expeditor and Lotus Notes 8.0 and later at large industry customers in Germany. Robert has more than 20 years' experience in the computer business working for such companies as Digital Research and Novell. Since he joined Lotus in 1993, he has held different positions, all related to technical sales support. Recently he moved into the services organization, focusing on the new Java-based client platforms. You can reach him at Robert.Schneider@de.ibm.com.



29 June 2009 (First published 26 May 2009)

Also available in Chinese Spanish

Editor's note: Know a lot about this topic? Want to share your expertise? Participate in the IBM Lotus software wiki program today.

Introduction

The Lotus Notes 8.0 and later client has nice ways of linking its user interface to content pages; for example, it uses a bookmark residing in your favorites folder in the launcher bar. Sometimes, though, you want to make your content launcher display more "integrated" into the Lotus Notes client, for example, by linking it to a menu entry in the Lotus Notes menu bar. For the new Lotus Notes Multimedia Library, several customers expressed their wishes for such an integrated way of launching the plug-in directly from the Help menu of the Lotus Notes client.

The extension we use is a plug-in written to extend the IBM Lotus® Expeditor-based framework that is the base of the new Lotus Notes 8.0 and later client. The plug-in also makes use of the Managed Settings framework that lets you preconfigure the URL that opens and lock those preferences so that users cannot modify them later. The source code for the plug-in is provided with the article.

This article shows you how we developed a plug-in that lets you create a menu entry placed in the Lotus Notes Help menu that allows you to open a browser window, either in a tab or in a newly opened window, that shows some configurable content (the Lotus Notes Multimedia Library URL), which can be managed through IBM Lotus Domino® policies.

Several articles on developerWorks® have covered the basics of how to create plug-ins for IBM Lotus Expeditor, IBM Lotus Sametime® 8.0 and later, and Lotus Notes 8.0 and later, which all are Lotus Expeditor- and, hence, Eclipse-based. See the links in the Resourcs section of this article.

Instead of documenting each step required to implement the final plug-in, in this article we focus on the key steps only. The sources for the plug-in are included in the Downloads section of the article, in case you would like to reuse them rather than starting from scratch. The main steps we document are these:

  1. Provide a preference page that allows you to enter settings; foremost is the URL to be launched.
  2. Create an Eclipse user intereface (UI) command to provide a menu entry to call a command handler.
  3. Open a browser window, either as a new tab or as a newly opened window, to load the content of that URL.
  4. Provide a way to deploy the plug-in to your Lotus Notes users.

Prerequisites

For the development work, we used IBM Rational® Software Architect version 7.5.1 that had been equipped with the Lotus Expeditor 6.2 toolkit. Any Eclipse 3.4+ installation equipped with the Lotus Expeditor 6.2 toolkit will do as well. The plug-in was developed specifically to launch the Lotus Notes Multimedia Library; however, because any URL could be launched by it, we gave it a more neutral name: com.ibm.notes.webview.


Create a new plug-in project

To start the work, select File - New - Project and create a new Client Services Project with your favorite settings. Names and specifiers aren't that important. As one example, we called the project com.ibm.notes.webview, left everything else as the default values, and only cleared one option, the Create a plug-in using one of the templates option on the last page of the New Project wizard.


Preferences, the preference page, its initializer, and how to obey managed settings

The Lotus Notes Multimedia Library is something that customers usually make available to their Lotus Notes users on their internal servers, so using a preference page gives you the ability to edit this URL.

After the project had been created, we used the Eclipse extension point wizard, shown in figure 1, to create a preference page with its preferences initializer.

Figure 1. The Extension Point Selection window
The Extension Point Selection window

Figure 2 shows the sample preference page. Enter these values:

  • In the Java Package Name field, enter com.ibm.notes.webview.
  • In the Page Class Name field, enter PreferencePage.
  • In the Page Name field, enter Web View.
Figure 2. The Sample Preference Page window
The Sample Preference Page window

This wizard generates a PreferencePage class, which extends the FieldEditorPreferencePage class. Because we would like to have finer control of the elements on that page, we changed it to be a regular PreferencePage and created the required methods to fill the window with the controls we need.

Because customers might want to change the name of the preference page as it displays in the window, we later used the plug-in localization feature of Eclipse to outsource the text of that page into a properties file. You can now edit the name of the page in the plugin.properties file in the plug-in project.

[…]
prefpagename=Notes Multimedia Library
[…]

During createContents, we query the Managed Settings framework to determine whether the settings are locked by the administrator. If the settings are not locked, we enable the controls for them. Listing 1 is a code snippet that shows how that task can be accomplished.

Listing 1. Setting the enabled-flag of a managed setting
	[...]
	  private ManagedSettingsScope scope = null;
	[...]
	  scope = new ManagedSettingsScope();
	[...]
	  // check whether this is a locked managed setting and if so,
	  // disable the buttons to prevent user input
	  if (scope.isReadOnly(Activator.PLUGIN_ID,
	      PreferenceConstants.P_OPENMODE))
	  {
	    newTabButton.setEnabled(false);
	    newWindowButton.setEnabled(false);
	  }
	[...]

We implemented two settings for the plug-in:

  • A flag to indicate whether the user wants to open the content of the library in a new tab or in a newly opened window
  • The URL of the content that is supposed to display

If you use the code in the file provided in the Downloads section of this article, your preference page should look like the one shown in figure 3.

Figure 3. The preference page
The preference page

An Eclipse UI command

After we created the preferences functionality of our plug-in, we again went to the extensions page of our plugin.xml file and used another wizard, shown in figure 4, to implement everything we needed to have a menu item provide a way to call our code.

Figure 4. Extension Point Wizard
Extension Point Wizard

Figure 5 shows the sample command contribution page. Enter these values:

  • In the Java Package Name field, enter com.ibm.notes.webview.
  • In the Handler Class Name field, enter CommandHandler.
  • In the Message Box Text field, enter Hello, Eclipse world as a placeholder. You will probably remove that message box later.
Figure 5. The sample command contribution page
The sample command contribution page

After you click Finish, you find that several new extension points are filled for you. See figures 6 and 7 for details.

Figure 6. Comparing the wizard entries with the final entries: Extension points being automatically created by the wizard
Comparing the wizard entries with the final entries: Extension points being automatically created by the wizard
Figure 7. Comparing the wizard entries with the final entries: Extension points after we clean up what wasn't required for our plug-in
Comparing the wizard entries with the final entries: Extension points after we clean up what wasn't required for our plug-in

Eclipse has a careful way of defining such commands. In human words, the Eclipse process sounds something like this:

  • There is something I would like to carry out, and I call it do.it (org.eclipse.ui.commands/command).
  • This is the logic for do.it and the real code (org.eclipse.ui.handlers/handler).
  • I want do.it to be called on a certain keyboard shortcut (org.eclipse.ui.bindings/key).
  • I want do.it to be selectable in the UI (org.eclipse.ui.menus/menuContribution) at a certain position within the menu (org.eclipse.ui.menus/menu) and/or at a certain position within the toolbar (org.eclipse.ui.menus/toolbar).

As you can see, we have removed the toolbar entry and used only a menu entry for our command. We also changed the position where the menu-item displays. The wizard generated a menu-URL of menu:org.eclipse.ui.main.menu?after=additions. This menu-URL causes a new top-level menu to display before the Help menu containing one menu-item with our sample command. After we changed that command to menu:help?before=additions, the menu-item displayed in the Help menu below the Dynamic Help entry.

After all extension points have been properly defined, you need to focus on the code in the class CommandHandler in particular, in the body of the method execute(). Listing 2 shows the code as it was generated from the wizard in the extension points page shown in figure 4.

Listing 2. execute()-method of a org.eclipse.core.commands.AbstractHandler class
	/**
	 * the command has been executed, so extract the needed
	 * information from the application context.
	 */
	public Object execute(ExecutionEvent event) throws ExecutionException {
	  IWorkbenchWindow window = HandlerUtil.getActiveWorkbenchWindowChecked(event);
	  MessageDialog.openInformation(
	      window.getShell(),
	      "Webview Plug-in",
	      "Hello, Eclipse world");
	  return null;
	}

Opening a browser window to display the content of a URL

Let's recap: So far we have created a preference that holds the URL that we want to display to our users, and we have an action that is selectable in the UI and that causes a method of one of our classes to be executed. Next, we want to open a new tab or a new window and embed an instance of a browser that is pointed to our URL.

In Eclipse, we would create a view for our embedded browser instance, put it into a perspective, and call the platform to open this perspective. But there is a difference between Eclipse and Lotus Notes and Lotus Expeditor. A perspective is already open and all that we want to do is open a new tab in it. To accomplish this step, Lotus Expeditor provides a special API that allows us to do exactly this: the SwitcherService-API.

At this point, we need to widen the scope of our article to create some understanding about services, which can be provided through the OSGi framework of Eclipse. If you have functionality that you want to provide to others, you can create an extension point that another plug-in can link to by creating an extension to it. This approach is the best-known way extending the capabilities of Eclipse. Of course, there are other ways to do that; depending on your specific plan, those ways might have advantages over the extension point schema. One alternate way is the services framework of the OSGi platform. This framework offers a controlled way of providing instances of a certain class to others by recognizing that class-loaders within the platform are separated from one another.

Using the services part of the OSGi framework, you could characterize your plan this way: "I have something I can provide as a service, and it is implemented in a class called a.b.c.MyService." Users who want to consume that service can call another API and say, "I need a service of a.b.c.MyService, so go get me an instance of it."

That approach is the way that the Lotus Expeditor team implemented the SwitcherService, a service that allows you to open windows as new tabs, as grouped tabs, or as completely new windows. To get an overview of the features of that service, look at the Javadoc at for the com.ibm.rcp.ui.launcher package, in particular the interface SwitcherService and the class SwitcherParam.

To make use of the SwitcherService API, first you need to get an instance of the service. You can do that only if you have an instance of BundleContext that had been passed to the start()-method of your Activator class. As it is common practice to have the Activator class be a plug-in-internal service entity, we put a public method in our Activator that allows other classes of our plug-in to request an instance of that SwitcherService. Listing 3 shows the code for this particular method.

Listing 3. Code to retrieve an instance of the SwitcherService
	/**
	 * Obtain an instance of the SwitcherService from the Expeditor platform
	 * 
	 * @return the ss
	 */
	public SwitcherService getSwitcherService()
	{
	  if (ss == null)
	  {
	    ServiceTracker st;

	    // retrieve a SwitcherService instance through 
		// the ServiceTracker
	    st = new ServiceTracker(context,
	        "com.ibm.rcp.ui.launcher.SwitcherService",
 	        null);
	    st.open();
	    ss = (SwitcherService) st.getService();
	    st.close();
	  }
	  return ss;
	}

Note that this approach can go wrong in certain situations:

  • At an early stage of the platform initialization
  • If your plug-in was executed on Lotus Sametime instead of on a full version of Lotus Expeditor or Lotus Notes because Lotus Sametime does not provide a SwitcherService service

Be sure to check the result of that method and act accordingly if you detect a null return.

In the command handler class, you now have to do three things:

  1. Read your preferences to get the URL to open and the flag to show whether it's a new tab or a new window.
  2. Set up an embedded browser component with all your wanted settings including the initial URL.
  3. Open the window in the way that the user wanted us to open it.

This first step, reading the preferences, is shown in listing 4.

Listing 4. Code to retrieve settings from the preferences framework
	/**
	 * the command has been executed, so extract the needed information
	 * from the application context.
	 */
	public Object execute(ExecutionEvent event) throws ExecutionException
	{
	  logger.entering(getClass().getName(), "execute");

	  ManagedSettingsScope scope = new ManagedSettingsScope();
	  IEclipsePreferences prefs = scope.getNode(Activator.PLUGIN_ID);
		
	  String url = prefs.get(PreferenceConstants.P_URL, "about:blank"); //$NON-NLS-1$
	  boolean isOpenInNewWindow = (prefs.get(PreferenceConstants.P_OPENMODE,
	      null)
	      .compareToIgnoreCase(PreferenceConstants.P_OPENMODE_WINDOW) == 0) ? true
	      : false; //$NON-NLS-1$

The next step is to configure the embedded browser instance, as shown in listing 5. The names of the settings and their values should be self-explanatory. If you want to read about all possible settings for such a browser component, look up their names and settings in the Javadoc to the com.ibm.rcp.ui.browser.BrowserPreference-class (See this link.)

Listing 5. Setting the configuration of an embedded browser
	Map<String, String> configMap = new HashMap<String, String>();

	configMap.put(BrowserPreference.ID, Activator.PLUGIN_ID);

	configMap.put(BrowserPreference.INITIAL_URL, url);

	// TODO We could make all these settings configurable
	configMap.put(BrowserPreference.ENABLE_BOOKMARKS, "false"); //$NON-NLS-1$
	configMap.put(BrowserPreference.ENABLE_CONTEXT_MENU, "false"); //$NON-NLS-1$
	configMap.put(BrowserPreference.ENABLE_HELP, "false"); //$NON-NLS-1$
	configMap.put(BrowserPreference.SHOW_BOOKMARK, "false"); //$NON-NLS-1$
	configMap.put(BrowserPreference.SHOW_HISTORY, "false"); //$NON-NLS-1$
	configMap.put(BrowserPreference.SHOW_HOME, "false"); //$NON-NLS-1$
	configMap.put(BrowserPreference.SHOW_PAGE_CONTROL, "false"); //$NON-NLS-1$
	configMap.put(BrowserPreference.SHOW_PRINT, "false"); //$NON-NLS-1$
	configMap.put(BrowserPreference.SHOW_TOOL_BAR, "false"); //$NON-NLS-1$
	configMap.put(BrowserPreference.SHOW_URL_ENTRY, "false"); //$NON-NLS-1$
	BrowserFactory.setBrowserConfigMap(Activator.PLUGIN_ID, configMap);

Last, you need to direct Lotus Expeditor or Lotus Notes to open the window. See the code in listing 6.

Listing 6. Main code to open a view in a new perspective
	try
	{
	  SwitcherParam param;
	  SwitcherResult result;
	  IWorkbenchWindow currentWindow = HandlerUtil
	          getActiveWorkbenchWindowChecked(event);

	    switcherService = Activator.getDefault().getSwitcherService();

	    if (switcherService == null)
	    {
	      logger
	          .severe("Cannot obtain an instance of the SwitcherService!");
	      return null;
	    }

	    logger.fine("About to open URL " + url + " in new "
		      + ((isOpenInNewWindow) ? "window" : "tab"));

	    // if you set twoCalls to true, the newly opened window will
	    // receive a tab. If you set it to false, the newly opened window
	    // will NOT have a tab.
	    boolean twoCalls = false;
	    if (twoCalls)
	    {
	      if (isOpenInNewWindow)
	      {
	        param = new SwitcherParam(null);
	        param.setMode(SwitcherParam.NEW_WINDOW);
	        param.setTitle(Messages.WindowTitle);
	        result = switcherService.show(param);
			currentWindow = result.getWindow();
	      }
			param = new SwitcherParam(currentWindow);
			param.setViewId(Activator.VIEW_ID);
			param.setSecondaryId(Activator.PLUGIN_ID);
			param.setTitle(Messages.WindowTitle);
			result = switcherService.show(param);
	      } else
	    {
	      param = new SwitcherParam(currentWindow);
	      if (isOpenInNewWindow)
	      {
		      param.setMode(SwitcherParam.NEW_WINDOW);
	      }
	      param.setViewId(Activator.VIEW_ID);
	      param.setSecondaryId(Activator.PLUGIN_ID);
	      param.setTitle(Messages.WindowTitle);
	      result = switcherService.show(param);
	    }
	  } catch (WorkbenchException e)
	  {
	    logger
	        .log(
	            Level.SEVERE,
	            "Error when trying to open the web view window in command handler",
	            e);
	  }

	  return null;
	}

As you can see, there are two ways of opening a window. You can use one call to open the window and its content, and you can use another call where one call is used to open the window and another call to display the content. Each method does different tasks, and their functionality is undocumented. Figures 8, 9, and 10 illustrate their differences.

Figure 8. Comparing the different modes to open a view: In a tab
Comparing the different modes to open a view: In a tab
Figure 9. Comparing the different modes to open a view: In a new window (one call)
Comparing the different modes to open a view: In a new window (one call)
Figure 10. Comparing the different modes to open a view: In a new window (two calls)
Comparing the different modes to open a view: In a new window (two calls)

Deploying the plug-in to a group of Lotus Notes users

So far, you have created the vital parts of your plug-in, and you should be ready to roll it out to users. There are many ways to distribute and deploy such a plug-in to different communities. The most basic way is to create an update site with a feature containing your plug-in and asking the user to install that feature from the update site. Such an update site can either be a remote sytem, where users access the features and plug-ins using HTTP, or a compressed archive containing everything in one file that can be installed locally from a USB drive, for example.

Lotus Notes users have even more comfortable way to deploy such a feature; they can use the widgets framework of the Lotus Notes client, which is available in Lotus Notes 8.0.1 and later. This approach requires that you provide your feature on an update site, but that site could be an NSF-based update site. To trigger the installation of a feature through the widgets framework, you can either send your users an XML file that they drag into the My Widgets sidebar or assign them default categories of widgets in the widget catalog that get automatically installed into the Lotus Notes clients through Lotus Notes and Lotus Domino policies. You would need to set up a widget catalog on one of your Lotus Domino servers.

In this case, we provide a little XML file, shown in listing 7, that you can send to your users. All they have to do is drag the file onto their My Widgets sidebar.

Listing 7. XML-Data for a widget deployment manifest
<?xml version="1.0" encoding="UTF-8"?>
<webcontextConfiguration version="1.1">
	<palleteItem contributeToSideshelfOnStartup="false" 
	id=" lotus.multimedia.library" imageUrl="" 
    modified="false" providerId="com.ibm.rcp.toolbox.prov.provider.ToolboxProvisioning" 
    title=" IBM Lotus Notes Multimedia Library" 
    url="http://www.yourhost.com/some/folder/com.ibm.notes.webview.
    updatesite/site.xml">
    <preferences/>
    <data>
      <installManifest>
      <![CDATA[
        <install version="1.0.0">
          <installfeature default="true" id="com.ibm.notes.webview.feature" 
            name="notes.webview" required="false" show="true" version="1.0.0">
           <requirements>
              <feature download-size="1000" id="com.ibm.notes.webview.feature" 
                match="perfect" shared="true" size="1000" 
                url="http://www.yourhost.com/some/folder/com.ibm.notes.webview.
                updatesite/site.xml" 
                version="1.0.0"/> 
            </requirements>
          </installfeature>
        </install>
      ]]>
      </installManifest>
    </data>
  </palleteItem>
</webcontextConfiguration>

Place the code in listing 7 into an XML file and mail it to your users. If they drag it to their My Widgets sidebar, the installation of your feature from your update site is automatically triggered. After a restart of the Lotus Notes client, your menu should be in place, as shown in figure 11.

Figure 11. Appearance of the new menu item
Appearance of the new menu item

The source code of the plug-in, its features, and an update site are provided in the Downloads section of this article. If you want to rename your preference page and menu entry, all you have to do is change two lines in the plug-in’s plugin.properties file.

This plug-in is meant to handle only one menu entry and one URL to be displayed. Should you have the need to provide two or more entries to open two or more different URLs, you can add entries to the org.eclipse.ui.commands, org.eclipse.ui.bindings, and org.eclipse.ui.menus extension points. You can work with one command handler; you just have to check on the command ID that is passed into the command handler and act accordingly. For another URL to be edited in the preference page, you can duplicate the lines that produce the edit control for the URL and see where the values are read and written, then duplicate that code with new IDs.


Conclusion

As you can see, it’s not a lot of work to write code that integrates content natively into the Lotus Notes client. Knowing how to use the genuine extension-point framework of the underlying Eclipse and Lotus Expeditor framework is probably the most important part. The code of this plug-in can help you understand some of those features, allowing you to start doing greater things with the new Lotus Notes client.


Downloads

DescriptionNameSize
Code samplecom.ibm.notes.webview.updatesite.zip14KB
Code samplecom.ibm.notes.webview.zip30KB

Resources

Learn

Get products and technologies

Discuss

Comments

developerWorks: Sign in

Required fields are indicated with an asterisk (*).


Need an IBM ID?
Forgot your IBM ID?


Forgot your password?
Change your password

By clicking Submit, you agree to the developerWorks terms of use.

 


The first time you sign into developerWorks, a profile is created for you. Information in your profile (your name, country/region, and company name) is displayed to the public and will accompany any content you post, unless you opt to hide your company name. You may update your IBM account at any time.

All information submitted is secure.

Choose your display name



The first time you sign in to developerWorks, a profile is created for you, so you need to choose a display name. Your display name accompanies the content you post on developerWorks.

Please choose a display name between 3-31 characters. Your display name must be unique in the developerWorks community and should not be your email address for privacy reasons.

Required fields are indicated with an asterisk (*).

(Must be between 3 – 31 characters.)

By clicking Submit, you agree to the developerWorks terms of use.

 


All information submitted is secure.

Dig deeper into IBM collaboration and social software on developerWorks


static.content.url=http://www.ibm.com/developerworks/js/artrating/
SITE_ID=1
Zone=Lotus
ArticleID=391886
ArticleTitle=Creating an IBM Lotus Notes 8.0 and later plug-in for IBM Multimedia Library
publish-date=06292009