<< February 2009 | Home | April 2009 >>

On plug-ins, features, update sites and extension.xml files...

I'm receiving quite a few e-mails asking questions about features, plug-ins, update sites and extension.xml files and how they relate so I thought I would try and clarify things.

TermDescription
Plug-in The smallest unit of code you use to create functionality for an Eclipse based client. This is where the actual Java code is.
Feature Used to package and bundle plug-ins together. Features are thin wrappers for plug-ins and is basically a single file called feature.xml. You can bundle multiple plug-ins into a single feature. When installing code into Notes you actually install the features which in turn point to the plug-ins to copy to the client. You can only manage features through the Notes "code UI" (File/Application/Application Management) though you can install code into the platform by simply copying the plug-ins into the appropriate directories in the file system. This is not recommended... :-)
Update site Update sites are used to deploy features to clients. An update site is simply a directory containing a
  • "plugins"-directory containing a jar-file per plug-in
  • "features"-directory containing jar-file per feature
  • site.xml file describing which features and plug-ins (and in what versions) are available on that particular update site
When an Eclipse based client contacts an update site it reads and parses the site.xml file to discover what's available there.
Update Sites may be remote or local. A local update site is a directory on a local hard drive or LAN drive with the above structure or a zip-file with the above structure. An update site may also be remote and may be read using HTTP (any server will do) or it may be read using NRPC if you're using a Notes 8+ client. When using NRPC you use the Update Site Notes database template.
extension.xml These files are used when installing code using the MyWidgets sidebar plug-in and is a shorthand for manually installing code. There is no magic at work here. When you drop an extension.xml file onto the sidebar panel the following steps are performed:
  1. The extension.xml file is parsed and verified to be a valid XML file
  2. The features to be installed are located and a dependency graph is assembled so any required features are identified
  3. The update site address specified in the extension.xml file is contacted and each missing feature in the dependency grapg is attempted installed "bottom up"
  4. The client is restarted

http://aws.amazon.com/eclipse/

Now there is an Eclipse plug-in for interacting with Amazon EC2 services - very cool.

"We want to make the process of building, testing, and deploying applications on Amazon EC2 as simple and efficient as possible. Modern web applications typically run in clustered environments comprised of one or more servers. Unfortunately, setting up a cluster can involve locating, connecting, configuring and maintaining a significant amount of hardware. Once this has been done, keeping the operating system, middleware, and application code current and consistent across each server can add inefficiency and tedium to the development process. In recent years, Amazon Web Services has helped to ease much of this burden, trivializing the process of acquiring, customizing, and running server instances on demand."

Tags : ,

IBM / SAP Alloy dissected

After the announcement of the general availability of IBM/SAP Alloy the other day I downloaded the package to find out which components it is made up of. Below are some tidbits that may or may not be of interest to you.

Download packages

  • Client package == plugin
  • Domino Server package
  • SAP Server package
  • Documentation package
Parts
  • Plug-in to Notes 8.0.2 or newer
  • Domino Server component
    • Notes database with a web service
    • This database is used to configure the available applications and hostname for the SAP server
  • Updates to the user mail database
    • Description: "The Alloy by IBM and SAP Mail Template Update Tool adds additional and required design elements to the master IBM Lotus Notes and IBM Lotus Domino mail template. This is required to enable integrated Alloy functionality in user's mail and calendar views. The additional design elements are supplied in the NDERPmail.ntf template, which is typically resident in the Domino\data directory on the Alloy server. "
SAP applications
  • Leave management
  • Travel management
  • Reports
  • Customized decision workflow applications
More info
IBM/SAP Alloy InfoCenter

It appears that the Notes plug-in reads the webservice address from the plugin_customization.ini file (com.ibm.nderp.client/NDERPMDWS_URL=http://hostname/nderpws.nsf/MetaDataService?openwebservice) or from the notes.ini file (NDERPMDWS_URL)

If you're wondering why your widget catalog deployment doesn't work...

...then make sure your widget catalog is in the root of the server. This will be fixed in Notes 8.5.1 and a SPR has been generated (SPR #DMDD7Q4MWT) for Notes 8.5 FP1 so open an PMR and vote for it if this is important enough for you. For the record the way that this works is by the Notes client having a replication event listener for the widget catalog database.

How to deploy widgets and/or plugins in your organization

Deploying widgets and/or plug-ins in your organization is very easy and there's a number of options for doing it.

  1. Desktop policies
  2. Widget catalog via MyWidgets
  3. Drag'n'drop of widgets to the MyWidgets sidebar plug-in
Using a desktop policy is just a administration shorthand for using the widget catalog via MyWidgets.

The first thing you really should do, if not simply using publishing widgets created through the MyWidgets functionality, is to read up on and understand the Lotus Expeditor provisioning manifest syntax. The manifest is used to specify where the update site server is and which features and in which version to install. The manifest looks weird at first but it's actaully easy enough. Unfortunately there isn't a nice UI for creating these provisioning manifests but I head rumors in the Meet the Developers lab at Lotusphere that a UI is coming. Soon... :-)

And now for the time and frustration saver...

Absolutely make sure that you put the widget catalog in the root of the Domino server to make sure it ends up in the root of the Notes client. If you do not do this and you specify a widget catalog in the preferences the Notes client wont apply updates to the widgets when new versions are available. This is a bug at least in Notes 8.5 GOLD.

Resources:

The technique for building a better Notes Java API

This is a followup post to yesterdays post titled Want to join me in building a better Notes Java API? and here I'll show just how easy it was to build the wrapper API.

Below is the code from the implementation of the getView(String) method of the lotus.domino.Database interface. As you can see the central element is to get the current thread the method is called on and the thread used for Notes data access. If we're not on the Notes thread execute a blocking request and return the result. If we're on the Notes thread simply go ahead and do the operation. Simple right?

The most difficult part of all this was that I had to write my own Notes thread handler (equivalent of NotesPlatform) as there isn't a method for doing a blocking request on the Notes thread in NotesPlatform class supplied by Lotus.

public View getView(final String name) throws NotesException {
  // get threads
  Thread curThread = Thread.currentThread();
  Thread notesThread = NotesPlatform.getInstance().getThread();

  // decide if we're in the Notes thread or not
  if (curThread != notesThread) {
    // we're not on the Notes thread so wrap
    final Holder h = new Holder();
    
    NotesPlatform.getInstance().syncExec(new Runnable() {
      public void run() {
        try {
          h.value = DatabaseWrapper.this.db.getView(name);
          
        } catch (NotesException e) {
          h.throwable = e;
        }
      }
    });
    
    if (null != h.throwable) {
      throw (NotesException)h.throwable;
    } else {
      return new ViewWrapper((View)h.value);
    }
    
  } else {
    // we're on the thread so do request
    return new ViewWrapper(DatabaseWrapper.this.db.getView(name));
  }
}

TwitNotes 1.0.9 available and the book is now closed on v. 1.0.x :-)

So I've fixed the final small issues I really wanted to get fixed before focusing on the next release of TwitNotes in version 1.0.9. This release is primarily a bug fix that fixes the following:

  • Make sure the date/time of the post is represented in search results
  • Make sure the source application of the post is represented in search results
  • Make sure the Twitter tab is always the first tab and search is the second
  • Make sure TwitNotes is working perfectly on Ubuntu
  • Fix the version number in the about dialog

I've created a widget descriptor for TwitNotes v. 1.0.9 as well. To update or install simply drag the widget descriptor to the MyWidgets sidebar.

I know there are (small) things that could be done differently but all future work will be done on version 1.1 which has some new exciting features I think... :-)

Want to join me in building a better Notes Java API?

One of the things that are the hardest for Notes Java developers transitioning to developing plug-ins for Notes 8 is handling threading. All access to the Notes backend classes must occur on the Notes thread using NotesJob or a thread statically initialized using NotesThread.sinitThread. This is cumbersome and prone to runtime exceptions making the development process slow and agonizing. Also most interaction is started from the UI thread making the need for handling the Notes thread all too common.

A far better approach, IMHO, would be to not require the programmer to handle the threading all together as there are solutions for this readily available. The solution isn't hard to do.

In an effort to prove this point I sat down for an hour or so at Lotusphere (I know I'm behind in blogging this) and cooked up a wrapper API that wraps the Notes API and provides access to the Notes backend classes without the need to worry about threading. The Notes API is made up of interfaces which makes it even easier.

The whole concept with the wrapper is that the user can write code like this in an event handler

public void widgetSelected(SelectionEvent event) {
  try {
    // get value
    Session session = NotesPlatform.getInstance().getSession();
    Database db = session.getDatabase(null, "names.nsf");
    View v = db.getView("($People)");
    ViewEntryCollection vec = v.getAllEntries();
    
    // set value in label
    lblCount.setText("Found " + vec.getCount() + " contacts...");
    
    // return from event
    return;
    
  } catch (Exception e) {
    StringWriter sw = new StringWriter();
    e.printStackTrace(new PrintWriter(sw));
    txtException.setText(sw.toString());
  }
}
instead of doing stuff like this which includes two extra jobs and having to make sure that no Notes API access is done from the UI thread:
public void widgetSelected(SelectionEvent event) {
  // kick of Notes job to get data
  new NotesJob("Some job") {
    public IStatus runInNotesThread(ProgressMonitor m) 
                               throws NotesException {
      // get value
      Session session = NotesPlatform.getInstance().getSession();
      Database db = session.getDatabase(null, "names.nsf");
      View v = db.getView("($People)");
      ViewEntryCollection vec = v.getAllEntries();
      
      // get count into final variable
      final int count = vec.getCount();
      
      // kick of new UI job to update UI
      new UIJob("Update UI") {
        public IStatus runInUIThread(IProgressMonitor monitor) {
          // set value in label
          lblCount.setText("Found " + count + " contacts...");
          return Status.OK_STATUS;
         }
      }.schedule();
      
      // return
      return Status.OK_STATUS;
    }
  }.schedule();
  
  // return
  return;
}

Besides being shorter code-wise the former code is also much easier to read and understand. The performance of the former is somewhat slower than the latter ("native" API) due to context switching but the fact that I could do this is 60 minutes proves that something can and should be done to make plug-in development easier. Imagine what could be done in more time. Tweaking for performance should be possible and easy enough. Also using this wrapper API could be a choice the developer makes - ease of use over performance... It could be a call I as a developer was willing to make.

This could actually be a good idea for a project on OpenNTF. If anyone is interested to join up on the project let me know - I'll be interested in joining forces with someone.

Tomorrow I'll blog about how this is done and just how easy it is.

TwitNotes - v. 1.0.7 is out

Just uploaded TwitNotes v. 1.0.7 to the update site. It's just a small bug fix release that fixes some minor things:

  • Easier searching by responding to pressing the Enter key on the Search tab
  • Make sure all profile images are scaled to 48x48px to handle too large images (looking at you @marybethraven)
  • Attempt to fix wordwrap issue on Ubuntu - still working on that

Thanks to Brian Leonard from IBM for providing a widget descriptor to make installation a lot easier. Simply drag the link to your MyWidgets sidebar plug-in to install.

Cool shortcuts for the Notes 8 client

Here's a list of some cool shortcuts for navigating the Notes 8 client using the keyboard.

Ctrl-Shift-LShortcut list for the client
Ctrl-Shift-TShow thumbnails of open tabs
Ctrl-F8Change perspective (tab)
Ctrl-0Close the sideshelf
Ctrl-3Minimize the sideshelf
Ctrl-4Expand the sideshelf

Tags : ,

Developing plug-ins for Notes 8.0.x, Notes 8.5, Sametime 8.0.x and Sametime 7.5.x

I received an e-mail from Dirk Jebing on my blog post on deploying TwitNotes in Sametime and how I was having deployment problems due to an exception being thrown. This is a long time ago but Dirk now found the solution which actually turned out to be a close cousin to my Cross compiling sidebar plugins for Notes 8.0.x and Notes 8.5 post.

Hi Mikkel,
at least for my plugin I could solve this! The two steps I did (perhaps it may help you): 1) I realized that I build my plugin with sametime 8.01 SDK. So I changed that (that did not help at all) 2) In the sametime logs my eye fell on an UnsupportedClassVersionError. So I changed the compiler compliance level (which stood on 5.0) to 1.4, as it has been with Sametime SDK 7.5.1. And now it works!

Cya, Dirk

So the lesson is to always watch for the JDK level of the client you're developing for...

SWT Widget Style Bits

In the Eclipsepedia there is a complete list of all built in widgets and which style bits they take. Enough said!! :-)

SWT Widget Style Bits!

Tags : , ,

Much better video for IBM press release on Lotus Sametime/virtual worlds

I guess all have seen the press release from IBM Lotus on IBM CREATES SOFTWARE FOR HOLDING FACE-TO-FACE MEETINGS IN VIRTUAL WORLDS but unfortunately the YouTube video linked in this press release is of very poor quality. I asked IBM and got a link to a video of much better quality you might want to check out.

Exciting stuff...

Tags : ,

My take on the LotusLive Contacts Sync plug-in and how to install it more easily

I read Chris Tooheys post on the LotusLive contact sync plug-in for Notes 8 (LotusLive Notes Contacts Sync on Lotus Notes 8.5... and why you should care!) with great interest and was very happy to see they didn't choose to make it a sidebar plug-in. Instead they chose a Tools-action which makes much more sense and which doesn't take up space in the sidebar. Now it just needs a hook (extension point) into the replication API to sync when I replication with my servers - that would be very nice.

I haven't really tested the plug-in thoroughly yet but I found it funny that I had to issue a cross certificate to a LotusLive certificate during the install ("CN=www.lotuslive.com/OU=Terms of use at www.verisign.com/rpa (c)05/OU=Lotus/O=INTERNATIONAL BUSINESS MACHINES CORPORATION/L=Phoenix/ST=Arizona/C=US/SerialNumber=DOC:19110616/XX=V1.0, Clause 5.(b)/XX=New York/XX=US"). This is the SSL certificate of the LotusLive.com site. I can actually install without cross-certifying but cannot restart the client until I create the cross-certificate. Maybe Lotus should choose a SSL certificate that is trusted by the Notes client by default.

To make it easier to install I created a LotusLive Contacts Sync widget descriptor which you can use to install the plug-in much more easily than doing the File/Application/Install dance.

To install from this either save the xml-file to your computer and drag it to the MyWidgets sidebar (or use a widget catalog) or drag the link directly to the sidebar.