<< July 2010 | Home | September 2010 >>

Maintaining a Lotus Connections environment? Well then you MUST see this!

Today a new article on Lotus Connections was posted on developerWorks and it shows you how to install an administration interface for Lotus Connections into Websphere ISC (Integrated Solutions Console). The interface provides easier access to Lotus Connections configuration files and looks like a real killer plugin for ISC. I have got to try and install it tomorrow and see for myself as this is something that has been sorely lacking.

The article is called Introducing the IBM Lotus Connections administration web interface and below is a snippet from the article introduction.

"The administration console utilizes a series of Jython and Jacl script files to allow administrators to work with Lotus Connections. These files provide automated ways to access the Lotus Connections MBeans that change back-end settings in databases and configuration files that service a deployment. Working with these Jython and Jacl script files requires some programming and scripting knowledge; the ability to import packages in the terminal, assign and use variables, and other basic programming concepts, all in the Jython or Jacl languages, are required. These languages, while not inherently hard languages to use, are relatively specialized and might be unfamiliar to the average Lotus Connections administrator. Removing control of Lotus Connections from the administration console and putting it into a web-based solution alleviate the need for specialized skills, providing a cost of ownership reduction to Lotus Connections customers."

Redbook: So we are writing this Redbook on plugin development - what do you wanna know?

As posted the other day my nomination to ITSO was accepted and I'm now on the team for writing a Redbook wiki on plugin (or component if you will) development for Lotus Notes, Lotus Sametime and Lotus Symphony. We had our first call yesterday and we're currently putting together the table of contents and discussing what to include.

For products versions we chose to target Lotus Notes 8.5.2, Lotus Sametime 8.0.2 and Lotus Symphony 3 beta 4. Of course we will try and make the samples work in prior versions but that's the versions we're aiming for. Any objections?

On the first call we also discussed the target audience for the wiki and defined who we're writing for. Here's what we came up with:

"We're writing for Java developers with some experience in the language that is they know the syntax. We will aim to give them a high level introduction to the plugin model and give them the material to dive deeper and make sure the appropriate Eclipse resources are linked in. The specific topic sections should readable to those who want to dangle their feet but also deep enough to allow a Java developer that know about plugins to actually start building stuff to make production quality plugins. "

How does that sound?

I would be very interested in hearing what you (yes you!!) the Notes developer wants to know about plugin development and maybe what's holding you back from getting started. Is it Java? Is it extension point documentation? Or is it something else? Please share and I'll do my best to make sure it's covered or at least written about here on the blog.

Eclipse Fall Training Series

"The Eclipse Foundation and Eclipse member companies are pleased to announce the fall 2010 training class series. The training is an excellent opportunity for software developers and architects to learn more about Eclipse Rich Client Platform (RCP), BIRT and Modeling technologies. Eclipse experts will lead the sessions, providing practical experience through classroom instruction and hands-on labs. Virtual and on-site classes have been scheduled in several countries from September 20 to November 5, 2010. "

Eclipse Fall Training Series

Use Wireless Hosted Networking to Share An Internet Connection Wirelessly

Apparently there's a hidden feature in Windows 7 that allows you to share a wi-fi connection to other users using a single wi-fi card. This means that you can buy one access token on for-pay-networks and share that to others. Very cool.

Windows 7 Tip of the Week - Use Wireless Hosted Networking to Share An Internet Connection Wirelessly

Updated! Introduction to Java programming

A lot of people ask me how to get started with Java programming so when I saw the below entry in the developerWorks newsletter I thought it should be communicated as far and wide as possible.

"developerWorks Java contributor Steve Perry took on the Herculean task of updating the "Introduction to Java programming" tutorials. This two-part series introduces the structure, syntax, and programming paradigm of the Java language and platform."

Get started with Java technology

Redbook residency nomination accepted!

Yahooo! Got word that my nomination for the virtual Redbook residency for "LO-0W01-R01 Developing Customized Components for Lotus Notes, Sametime, and Symphony" was accepted and that I'm on the team. How sweet is that?! First call is on Monday and I'm really looking forward to this. It will be good to do some more writing.

IBM Software Day 2010

Again this year IBM will be hosting their annual IBM Software Day in Øksnehallen in Copenhagen on 12 October 2010. You may now sign up for the event and if you're in Copenhagen on 12 October and you're working with IBM software you really should sign up. If nothing else there's normally a great lunch buffet... :-)

NLLUG 2010: Planning webapp for your smart phone

If you went to Lotusphere 2010 you probably used our web application for managing your Lotusphere schedule on your iPhone or Android device. I know a lot of people did!! With the Dutch user group just over 2 weeks away we've done it again and made a version of the web application for NLLUG 2010 available. If you're going simply head over to lug2010.nl/agenda to browse it and put together your schedule.

But what's an user group application without a prize?! The application also gives you the option of entering into our drawing for an Apple iPad!! So what are you waiting for? Go, go, go!

If you're looking for more screenshots before you decide to try it out I suggest your read my post from Lotusphere 2010 (Lotusphere 2010: Check out this killer Lotusphere planning web app!!).

Tags :

How to extend Notes 8: New version of the demo application

I just posted an update to the demo application for my Extending Notes 8 series of posts. The demo application is discussed in more detail in my previous post (How to extend Notes 8: LiveText demo application). The issue was that I had a button to create a demo e-mail in the UI which made the plugin depend on the Notes Java UI API which was added in Notes 8.5.1 and hence meant that the demo application wasn't installable on previous Notes versions... :-(

To remedy that I built an new version where the button using the offending API is added from an Eclipse plugin fragment and using a custom extension point (if you're running Notes 8.5.1+). More on that approach at a later date. For now you may install the new version using the updated widget descriptor (extension.xml) (simply drag the link to your MyWidgets sidebar plugin).

If you do an update - which there's absolutely no reason to if it already works for you - the only way to tell is by verifying that the version number at the bottom of the sidebar application is changed to 1.0.1.

That's all for this post. All the posts in the series may be found under the extending_notes8 tag.

Configure Eclipse 3.5 for Notes 8.5.2

Just updated my instructions on how to configure Eclipse 3.5 for Notes 8.5.2 with correct install_id and rcp.base_version as Notes 8.5.2 is now GOLD!! :-)

While I was out...

Just back from vacation I'm plowing through my feed reader and e-mail and found lots of cool stuff. I thought I would highlight some of it that caught my scanning eye... Julian writes about Custom SWT Buttons, Bob writes about Why BrowserFunction is so cool, Chris writes about Lotus Connections Profiles DB Purging and finally Stuart says: "Wow, a Lotus Notes book for end users".

Google Wave discontinued - what will that mean for Project Concord?

In a post the day before yesterday on the Google Blog Urs Holzle, Senior Vice President, Operations & Google Fellow, provides an Update on Google Wave. As it stands now Google will stop development on the Google Wave platform and provide tools to liberate the data from Google Wave. This decision has been made due to users not adopting Google Wave to the extent they would have wanted. Urs Holzle emphasizes that many of the protocols and technologies have already been made open source and that they hope that developers will continue to innovate on top of the technology.

I find this very interesting. First of all there was no end to the amazement and hype that was built around Google Wave when it was first announced. Second of all it looked like very cool technology though a lot of discussion was being had on the applicability to business and how it would fit in. Would it be the next killer application and what e-mail would become down the road? Sadly the technology never stuck and we will never know.

The announcement is however also interesting from a Lotus perspective.

As you might remember IBM unveiled Project Concord at Lotusphere 2010. Project Concord is IBM Lotus' next generation web collaboration environment which also featured live character-by-character typing etc. Many of us thought of Project Concord as being a clear response to Google Wave and a way to compete with Google in that (new) space. Now that Google is halting development of Google Wave what will happen to Project Concord? Will it be left for dead as well as the technology has been proved inadequate or "not wanted" or will it provide a clear opening for IBM Lotus to pursue? Does IBM Lotus have some "other stuff" up its Project Concord sleeve that will prove it to be the killer platform that will replace e-mail as we know it. I guess only time can tell.

R.I.P. Google Wave - we loved you although we never really got to know you...

How to extend Notes 8: LiveText demo application

The day before yesterday I posted the first summary post in my Extending Notes 8 series with a complete end-to-end approach to dynamically adding LiveTex recognizers. As part of that post I uploaded a demo application (plugin) but I didn't add a screenshot so I thought I'd remedy that.

As you can see the plugin has a small welcome text and two buttons. You'll also see a textbox to hold any exception (not that I'm expecting any) that might be raised as part of adding the recognizer and content type. You may use the two buttons to easily create a demo e-mail for use with the added LiveText stuff. The left button creates the e-mail in the UI (using the new handy Java UI classes) and the right one simply sends the e-mail to you in the backend. The latter is very handy for testing as the e-mail needs to be in read mode for the LiveText sub-system to kick in.

I've put a compiled version of the plugin on my update site and tthe plugin may be installed by dragging this extension.xml file to your MyWidgets sidebar panel (policy permitting).

That's all for this post. All the posts in the series may be found under the extending_notes8 tag.

How to extend Notes 8: case insensitive LiveText patterns

When you start to do a lot of LiveText recognizers you find yourself wanting to do more advanced stuff with your regular expressions. For instance you might want to do case insensitive patterns or use some of the others regular expression modifiers. This post will show you how to do this.

By default the regular expressions you specify for your recognizers are case sensitive. This is normally fine unless you really want it to be case insensitive. Since the LiveText engine is in Java you may use the supported Java modifiers for your regular expressions. Normally the modifiers are specified when you "compile the pattern" in Java (java.util.regex.Pattern.compile(pattern, modifiers)) but as you don't have access to this process you can't do that.

There is however another way...

You can embed some modifiers in the pattern such as Pattern.MULTILINE, Pattern.UNICODE_CASE, Pattern.DOTALL and most of all Pattern.CASE_INSENSITIVE! You embed the modifier in the start of the pattern. So instead of doing a case insensitive pattern like this (to recognizer "lotus" and "Lotus"):

[Ll]otus
you do
(?i)lotus
Cool isn't it?

The following modifiers are supported in Java though not all makes sense for LiveText:

  • Pattern.CASE_INSENSITIVE = (?i)
  • Pattern.MULTILINE = (?m)
  • Pattern.DOTALL = (?s)
  • Pattern.UNICODE_CASE = (?u)
Please bear in mind that it probably only makes sense to use DOTALL and CASE_INSENSITIVE.

That's all for this post. All the posts in the series may be found under the extending_notes8 tag.

Lotus Connections 3 coming to greenhouse.lotus.com this weekend

Just got word today from the team at greenhouse.lotus.com that a beta of the next release of Lotus Connections, which is now called 3.0, is being put on greenhouse.lotus.com on the this weekend. Very nice. Below is a snippet from the newsletter.

"Starting Friday August 6th we will begin our upgrade and migration of Lotus Connections 2.5 to Lotus Connections 3.0. The Lotus Connections services will not be available from Friday August 6th at 8:00 AM until it comes back online Tuesday August 10th."

How to extend Notes 8: dynamic LiveText recognizers using Java

As I briefly described in my last post ("How to extend Notes 8: dynamic extensions using Java") it's possible to create new extensions to Lotus Notes using Java and hence inject functionality into the client dynamically. It's very cool functionality and it allows you to inject anything from content types and recognizers to sidebar panels.

In this post I'll build on three previous posts and show you how to use dynamic extensions in Lotus Notes in combination with a Java action that uses multiple capture groups for an end-to-end solution that may be deployed as a single Java extension (aka plugin). The result is a plugin that may be deployed to a client workstations which allows you to act on text recognized by the LiveText sub-system but where you have the power of Java for processing.

All the posts in the series may be found under the extending_notes8 tag.

We need three pieces of information:

  1. The code to dynamically inject our custom recognizer and content type into Lotus Notes without the need for an extension.xml file. This is what the LiveText sub-system uses to highlight the text for us.
  2. The Java action to act on the LiveText selection.
  3. The plugin.xml file to bind it all together.

The first piece is the code that injects the custom recognizer and content type under a known id. This code may be run in lots of ways but to make it easy for this example I choose a sidebar panel. Below is the createPartControl-method from that class.

public void createPartControl(final Composite parent) {
  try {
    // define XML
    final String extensionXml = ...;
    
    // get extension registry and load extension 
    // into registry
    final IExtensionRegistry reg = Platform.getExtensionRegistry();
    InputStream ins = new ByteArrayInputStream(extensionXml.getBytes());
    Bundle bundle = Activator.getDefault().getBundle();
    IContributor contr = ContributorFactoryOSGi.createContributor(bundle);
    reg.addContribution(ins, contr, false, null, null, null);
    
  } catch (Throwable t) {
    t.printStackTrace();
  }
}
The above code injects the recognizer and content type with an id of DCCT.ExampleContentType.1234567890 into the client.

The next part we need is the action class (again implementing org.eclipse.ui.IObjectActionDelegate) to act on the LiveText selection. Most of the code you've seen before in a previous post but again it goes and get the text from the underlying document as document properties.

public void selectionChanged(IAction action, ISelection selection) {
   IDocumentContent doc = null;
   
   // cast/adapt selection
   if (selection instanceof StructuredSelection) {
      Object sel = ((StructuredSelection)selection).getFirstElement();
      if (sel instanceof IDocumentContent) {
         doc = (IDocumentContent)sel;
      }
   } else if (selection instanceof IDocumentContent) {
      doc = (IDocumentContent)selection;
   } else {
      // try and adapt
      IAdapterManager amgr = Platform.getAdapterManager();
      doc = (IDocumentContent)amgr.getAdapter(selection, 
          IDocumentContent.class);
   }
   if (null == doc) {
      this.contents = null;
      this.prodFamily = null;
      this.partNumber = null;
      return;
   }
   
   // get data from document property
   this.contents = doc.getProperties().getProperty("contents");
   this.prodFamily = doc.getProperties().getProperty("pf");
   this.partNumber = doc.getProperties().getProperty("pn");
}

The last piece is the plugin.xml to put it all together using the org.eclipse.ui.popupMenus extension point. Notice how we use the content type id we know (bold text below) from our dynamically deployed content type.

<extension
  point="org.eclipse.ui.popupMenus">
  <objectContribution
    id="com.lekkimworld.extnotes8.dynext.objCtr1"
    objectClass="com.ibm.rcp.content.IDocumentContent">
    <visibility>
      <and>
        <objectState
          name="content.type"
          value="DCCT.ExampleContentType.1234567890">
        </objectState>
        <objectState
          name="contents"
          value="*">
        </objectState>
      </and>
    </visibility>
    <action
      class="com.lekkimworld.extnotes8.dynext.MyAction"
      enablesFor="*"
      id="com.lekkimworld.extnotes8.dynext.action1"
      label="Do me!">
    </action>
  </objectContribution>
</extension>

The result when deployed to a Lotus Notes client is something like the screenshot below where you get a Java action to act on a LiveText recognition. Only change this time is that all the functionality is provided from your plugin. No separate extension.xml is necessary for the recognizer or the content type.

That's how it's done. I've uploaded an Eclipse project to the blog so you can download it and install it in your Eclipse as a demo. You can download the project here.

How to extend Notes 8: dynamic extensions using Java

I get so many question on how to extend Notes 8 that I finally decided to create a series of blog posts on how to do it. All the posts in the series may be found under the extending_notes8 tag. In all of the examples I assume a working knowledge of Eclipse and Java programming and how to work with extension points.

As I briefly mentioned in my last post ("How to extend Notes 8: capture group LiveText recognizers with a Java action") it's possible to create new extensions to Lotus Notes using Java and hence inject functionality into the client dynamically. It's very cool functionality and it allows you to inject anything from content types and recognizers to sidebar panels. I've used this a lot previously and also demoed it in my "How dynamic are your Notes sidebar plugins?" demo. Watch the Flash video and see how you can make sidebar panels come and go on demand.

Now on to the code...

The trick to dynamic extensions is to inject extensions into the Extension Registry at runtime. The Extension Registry is where Eclipse reads the plugin contributions from plugin.xml files into at startup. If we inject an extension, and the receiving plugins are set up to handle dynamically adding extensions you are golden. Let me show you have to use the Extension Registry.

final String extensionXml = ...;
final IExtensionRegistry reg = Platform.getExtensionRegistry();
InputStream ins = new ByteArrayInputStream(extensionXml.getBytes());
Bundle bundle = Activator.getDefault().getBundle();
IContributor contr = ContributorFactoryOSGi.createContributor(bundle);
reg.addContribution(ins, contr, false, null, null, null);
The code does the following:
  1. Defines the extension XML to add (more on this later).
  2. Gets the extension registry from the platform.
  3. Reads the extension XML into an input stream.
  4. Retrieves the bundle.
  5. Creates a new contributor that is the object that makes the contribution to the extension registry.
  6. Adds the contribution to the registry.

So what is the extension XML mentioned above?

The extension XML is the XML that defines the extension you're adding. It's actually any piece of XML you would stick in your plugin.xml file either manually or using the UI editor. An example could be a custom recognizer and content type as shown below as a snippet from Java.

final String extensionXml = "<?xml version=\"1.0\" encoding=\"utf-8\" ?>" +
"<?eclipse version=\"3.2\"?>" +
"<plugin>" + 
"<extension id=\"DCR.ExampleRecognizer.%s\" 
   point=\"com.ibm.rcp.annotation.regex.regexTypes\">" + 
"<regexTypes contentTypeId=\"DCCT.ExampleContentType.%s\" 
   id=\"DCR.ExampleRecognizer.%s\" match=\"([A-Z]{4})-(\\d{4})\" 
   name=\"Example Recognizer\">" + 
"<group contentTypePropertyId=\"pn\" number=\"2\"/>" + 
"<group contentTypePropertyId=\"pf\" number=\"1\"/>" + 
"<group contentTypePropertyId=\"contents\" number=\"0\"/>" + 
"</regexTypes>" + 
"</extension>" +  
"<extension id=\"DCCT.ExampleContentType.%s\" 
   point=\"com.ibm.rcp.content.contentTypes\">" + 
"<contentSet>" + 
"<type category=\"Recognized Content\" 
   id=\"DCCT.ExampleContentType.%s\" 
   name=\"Example Content Type\">" + 
"<property description=\"Entire Contents\" id=\"contents\"/>" + 
"<property description=\"Product Family\" id=\"pf\"/>" + 
"<property description=\"Part Number\" id=\"pn\"/>" + 
"</type>" + 
"</contentSet>" + 
"</extension>" + 
"</plugin>";

That's how you do it. Tomorrow I'll show how to combine it with our custom recognizer and content type to inject it dynamically into the LiveText system in Lotus Notes. Stay tuned...

How to extend Notes 8: capture group LiveText recognizers with a Java action

I get so many question on how to extend Notes 8 that I finally decided to create a series of blog posts on how to do it. All the posts in the series may be found under the extending_notes8 tag. In all of the examples I assume a working knowledge of Eclipse and Java programming and how to work with extension points.

For this post I'll build on the "How to extend Notes 8: coupling LiveText to a Java action" and "How to extend Notes 8: using LiveText with capture groups" posts and show how to act on your own custom recognizer from a Java action when you have multiple capture groups.

Please note: I'll assume that you read the "How to extend Notes 8: using LiveText with capture groups" post and have it working as we'll build on that example in this post. Unfortunately as we act on the content type id you need to find the id of the content type on your system. I'll show you how.

Enough with preparations - now on to the code!

So far we have our custom recognizer and our custom content type but instead of a web widget we really want to use our Java action as the recipient of the LiveText selection. We couple the Java action to the content type using an extension point in plugin.xml based on the content type id. Let me show you how to find the content type id.

  1. Start by opening the management UI for widgets, content types and recognizers. You do this by choosing "Manage Widgets, Content and Recognizers" from the part menu in the My Widgets sidebar panel as show below.
  2. Now switch to the "Content Types" panel and make a note of the ID for the "Demo Product Number" content type. Here the id is "DemoProductNumber.1410710777" as highlighted below.
  3. Now comes the trick. Notes adds "DCCT." in front of the id shown so the real id is "DCCT.DemoProductNumber.1410710777". Make a note of your own id and read on...

As previously the first piece of the puzzle is the extension point. Add an org.eclipse.ui.popupMenus extension as previous and specify the id you noted above as the content type id. Mine is shown below - notice how I use the id prefixed with "DCCT.".

<?xml version="1.0" encoding="UTF-8"?>
<?eclipse version="3.4"?>
<plugin>
   <extension  point="org.eclipse.ui.popupMenus">
      <objectContribution id="com.lekkimworld.livetxt.objectContr1" 
         objectClass="com.ibm.rcp.content.IDocumentContent">
         <visibility>
            <and>
               <objectState name="content.type" 
               value="DCCT.DemoProductNumber.1410710777"/>
               <objectState name="contents" value="" />
            </and>
         </visibility>
         <action class="com.lekkimworld.livetext.MyAction"
            enablesFor="*" 
            id="com.lekkimworld.livetxt.action1" 
            label="Do stuff!" />
      </objectContribution>   
   </extension>
</plugin>

Now create your Java action class - again implemening org.eclipse.ui.IObjectActionDelegate - and specify the correct class name in the extension point.

Again when it comes to grabbing the contents of the recognized LiveText it comes down to you selectionChanged-method of your Java action. As our recognizer uses capture groups we have a few choices for the properties we can grasp from the document. As always the entire recognized product number will be in the "contents" property but we also have "pf" and a "pn" property available that holds the product family and the part number. The example code below shows how to get at these.

public void selectionChanged(IAction action, ISelection selection) {
   IDocumentContent doc = null;
   
   // cast/adapt selection
   if (selection instanceof StructuredSelection) {
      Object sel = ((StructuredSelection)selection).getFirstElement();
      if (sel instanceof IDocumentContent) {
         doc = (IDocumentContent)sel;
      }
   } else if (selection instanceof IDocumentContent) {
      doc = (IDocumentContent)selection;
   } else {
      // try and adapt
      IAdapterManager amgr = Platform.getAdapterManager();
      doc = (IDocumentContent)amgr.getAdapter(selection, 
          IDocumentContent.class);
   }
   if (null == doc) {
      this.selection = null;
      return;
   }
   
   // get all recognized content
   this.prodNumber = doc.getProperties().getProperty("contents");
   this.prodFamily = doc.getProperties().getProperty("pf");
   this.partNumber = doc.getProperties().getProperty("pn");
}

Now when you install the extension and hence put the pieces together you should see two actions for the product number LiveText recognition as shown below. The top one is our Java action and the bottom one is our web widget from previously.

That's what is required to act on custom recognizers. As you can probably gather from the above it doesn't work letting users do their own recognizers and then wanting to act on them from Java due to two reasons - 1) never trust a user to give it the right name as instructed :-) and 2) the id of the content type will change from machine as it is generated when the user creates the content type. It is possible however if you create the content type and the recognizer for users and install then using an extension.xml file as the extension.xml sets the id's. That's probably also the way you'd want it.

There is however an even better solution... Dynamically add the content type and recognizer to the client from Java for a single, combined solution. Stay tuned...