Developing plugins for IBM Notes on Mac

I’ve been developing plugins for IBM Notes on Mac for years now but never really got around to sharing the steps on the blog. The below steps – in very crude form – works with Java 8 on Mac OS El Capitan (v. 10.11) using IBM Notes 9.0.1. The below sections are additions to the regular steps on creating a target platform documented otherwise on this blog

Main-tab

Run a product: com.ibm.notes.branding.notes

Execution Envionment: JavaSE-1.6

Arguments-tab

Program arguments:

-personality com.ibm.rcp.platform.personality
-debug
-console
-ws cocoa

VM Arguments:

-Declipse.registry.nulltoken=true
-Djava.util.logging.config.class=com.ibm.rcp.core.internal.logger.boot.LoggerConfig
-Dcom.ibm.pvc.webcontainer.port=8080
-Declipse.pluginCustomization="/Applications/IBM Notes.app/Contents/MacOS/rcp/plugin_customization.ini"
-Djava.protocol.handler.pkgs=com.ibm.net.ssl.www.protocol
-Dosgi.hook.configurators.exclude=org.eclipse.core.runtime.internal.adaptor.EclipseLogHook
-Dosgi.framework.extensions=com.ibm.rcp.core.logger.frameworkhook
-Xbootclasspath/a:"/Applications/IBM Notes.app/Contents/MacOS/rcp/eclipse/plugins/com.ibm.rcp.base_${rcp.base_version}/rcpbootcp.jar"
-XstartOnFirstThread

Environment-tab

  • DYLD_LIBRARY_PATH=/Applications/IBM Notes.app/Contents/MacOS
  • NOTESBIN=/Applications/IBM Notes.app/Contents/MacOS

Developing code using IBM Notes in Eclipse on Mac OS

I’m cleaning out my drafts folder and stumbled unto this one I never posted. The steps has changed slightly after IBM Notes 9.0.1 for Mac was released as that release works fine with the never JVM’s for the Mac. Actually there are very few steps you need to do to make the code work. To complete a standard console app that prints the username from the current session to stdout do the following:

  1. Write the code – could be something like this:
    import lotus.domino.NotesFactory;
    import lotus.domino.Session;
    import lotus.notes.NotesThread;
    
    public class Main {
       public static void main(String[] args) throws Exception {
          NotesThread.sinitThread();
          Session session = NotesFactory.createSession();
          System.out.println(session.getUserName());
          NotesThread.stermThread();
       }
    }
    
  2. Run the code as a Java Application. This will fail as the JVM cannot load the required libraries.
  3. Edit the Run Configuration (click the dropdown next to the green run button and choose “Run Configurations…”)
  4. Switch to the “Environment”-tab
  5. Add an environment variable called DYLD_LIBRARY_PATH with a value of “/Applications/IBM Notes.app/Contents/MacOS” (without the quotes)
  6. Click Apply and Run

This was done in Eclipse neon on Mac OS El Capitan (10.11) using Java 8.

Test agents in Eclipse by extending AgentBase

I continuously get questions on how I do Java agent development and I’m happy to answer them as I hope that some of the answers I provide means that more and more Domino developers see Java as a strong alternative to LotusScript for background processing. Most times the approach I recommend is a mock object approach that I wrote about waaaaaay back in 2006 (did I really write that 10 years ago?!?!?).

If / when you want to read the posts please start from part no. 1. Here’s a link to all 5 parts:

The approach doesn’t handle importing the code back into Domino Designer but it does allow you to “mock” the Notes side of the API and allows you to write, test and debug your agents in Eclipse. Then when they’re completely done you can import it back into Notes without any changes. This is the approach I would choose and that I still use when writing Java agents here 10 years later.

Hope this helps but if it doesn’t please let me know.

IBM Connections Cloud (SmartCloud) FINALLY adds much awaited feature

We have had OnTime Group Calendar working with IBM Connections Cloud (SmartCloud) for a years so that customers could move all or part of their mail users to IBM Connections Cloud and host OnTime Group Calendar on-premises or (IBM SmartCloud Notes Hybrid). We have seen adoption and do have customers using it but the main obstacle to full adoption by customers has been the lack of mailfile ACL controls for the customers. Since we require access to the mail files (we do need to read data you know…) a PMR to change ACL’s and/or a custom mail template in IBM Connections Cloud was required to add on-premises Domino servers to the cloud mail file ACL’s. With the latest update of IBM Connections Cloud this capability has finally been added to the administration panel so that customers may control these capabilities themselves. Yay!!

Administrators can control access to mail files from administrator interface (available on or after August 17 2015)

Company administrators can now control access to mail files through the Users page of the IBM SmartCloud Notes administration interface. Previously, IBM services needed to review, and then apply the template to the users. Administrators can now make the ACL changes directly against the mail file, saving them time and money.

For more information refer to the info center (Administration: control access to mail files).

Eclipse target platform invalidated by IBM Notes 9.0.1FP4 on Mac

After installing IBM Notes 9.0.1FP4 I have been unable to launch Notes from my Eclipse workspace when doing RCP development (i.e. plugin development) for Notes. I finally decided to solve it. The stacktrace is like the one below:

2015/07/20 08:16:42.280 SEVERE CLPDN0016E: Error starting RCPApplication com.ibm.rcp.personality.framework.RCPApplication
::class.method=com.ibm.rcp.personality.framework.internal.RCPApplication.run() ::thread=Thread-1
::loggername=com.ibm.rcp.personality.framework.internal

java.lang.NoSuchFieldError: isWindows
   at com.ibm.rcp.platform.personality.DefaultWorkbenchWindowAdvisor.createLaunchChevron(DefaultWorkbenchWindowAdvisor.java:2229)
   at com.ibm.rcp.platform.personality.DefaultWorkbenchWindowAdvisor.createShortcutBarItems(DefaultWorkbenchWindowAdvisor.java:591)
   at com.ibm.rcp.platform.personality.DefaultWorkbenchWindowAdvisor.createWindowContents(DefaultWorkbenchWindowAdvisor.java:733)

The issue turned out to be due to duplicate similar named plugins from the target platform with different versions. For instance I had the com.ibm.common.services.icalendar plugin in both version 9.0.1.20131022-0932 and in version 9.0.1.20150610-1521. Manually running through the plugins included in the target platform and excluding the older versions solved the issue. There must have been a problem deleting the older versions when upgrading my Notes client but in any case it’s solved now.

List of OpenSocial fixes in 9.0.1?

As reported all over the Yellow-bubble we’ve now got a Domino 9.0.1 server and a Notes 9.0.1 client to install. All is good and the list of fixes reported by developerWorks is 267. The list however doesn’t mention OpenSocial at all. This is sad as this is one of the new features from 9.0 and getting an idea as to what have been fixed would have been nice (plus I know that lots have been fixed).

Hope that IBM will release more information as to what was fixed for OpenSocial.

Java in Notes/Domino Explained: On Java Security and how it relates to Notes/Domino


I get so many questions on Java security and how it all fits together that I finally decided to blog it instead of simply answering over and over again. So here goes…

Security was built into Java from its inception and everything in a Java Virtual Machine (JVM) runs under the control of a security manager. Now the security manager may be very lax or it may be very restrictive as the one for Java applets or Notes/Domino agents is. A security manager is installed into the JVM when it’s constructed meaning either from the command line or, in the case of Notes/Domino, when a JVM is created to run agents, XPages or the like. A security manager may decide that a certain operation (method call) is “powerful” and hence will require the code executing the operation to be allowed to do so.

The way this is done in Java is by the operation itself (the method you are calling e.g. “write file” or “do stuff with reflection”) asking the security manager whether the code calling it has a given permission that it supplies to the security manager. The security manager may either decide that it does and hence return quietly or it may decide that the calling code does not have the required permission. To signal the latter it will throw a java.security.AccessControlException which you’ve seen if you’re reading this.

So how do we grant these permissions?

In Java permissions are controlled in the java.policy file located in the file system under <notes>/jvm/lib/security or <domino>/jvm/lib/security. I will not go into detail on the syntax of this file as resources are readily available on the web but suffice to say that different locations (be those file based or network based) are granted different sets of permissions (for more info see http://docs.oracle.com/javase/6/docs/technotes/guides/security/PolicyFiles.html). By default jar-files in jvm/lib/ext, the XPages runtime, OSGi bundles etc. are granted all permissions possible (java.security.AllPermission) whereas other code is granted a limited set of permissions. So if you need to run code that requires a different set of permissions you edit this file and restart the server/client. Now often times simply editing this file is not an option. Either you do not control the server, you cannot edit it for all clients or your security guidelines tell you just can’t do it. In either case editing the file is seldom the entire solution. And you need to understand why. Before showing you some code let me explain the scenario I’m going to use below first.

The scenario is that Joe Notes Developer needs to use reflection (wikipedia) to change the accessibility of a method from private to public (yes it’s possible) to override the private restriction set on the generate() method of the Test class (see below). To do this he uses a method like the one below:

public void doAccessible(Object obj) throws Exception {
   Method[] methods = obj.getClass().getMethods();
   for (int i=0; i<methods.length; i++) {
      Method m = methods[i];
      m.setAccessible(true);
   }
}

The class he needs to affect is likewise simple (he needs to make the generate() method public):

private class Test {
   private String uuid = null;

   public Test() {
      this.generate();
   }

   public String getUUID() {
      return this.uuid;
   }

   private void generate() {
      this.uuid = UUID.randomUUID().toString();
   }
}

To start of Joe Notes Developer creates a Java agent in Domino Designer and sticks the below code in NotesMain of the agent:

Test t = new Test();
System.out.println(t.getUUID());
doAccessible (t);
t.generate();
System.out.println(t.getUUID());
System.out.println("Completed...");

But oh no!! Joe gets the dreaded AccessControlExeption as the code in the Java agent may not use reflection this way.

java.security.AccessControlException: Access denied (java.lang.reflect.ReflectPermission suppressAccessChecks)
   at java.security.AccessController.checkPermission(AccessController.java:132)
   at java.lang.SecurityManager.checkPermission(SecurityManager.java:544)
   at COM.ibm.JEmpower.applet.AppletSecurity.superDotCheckPermission(AppletSecurity.java:1449)
   at COM.ibm.JEmpower.applet.AppletSecurity.checkPermission(AppletSecurity.java:1617)
   at COM.ibm.JEmpower.applet.AppletSecurity.checkPermission(AppletSecurity.java:1464)
   at java.lang.reflect.AccessibleObject.setAccessible(AccessibleObject.java:118)
   at ReflectionUtil.doAccessible(Unknown Source)
   at JavaAgent.NotesMain(Unknown Source)
   at lotus.domino.AgentBase.runNotes(Unknown Source)
   at lotus.domino.NotesThread.run(Unknown Source)

Nothing is holding Joe back though so he puts the reflection code into a ReflectionUtil class which he puts in a jar-file in jvm/lib/ext as he has heard that this location allows for this kind of funky stuff. Using the ReflectionUtil instead of a class method from his agent is like this:

ReflectionUtil l = new ReflectionUtil();
Test t = new Test();
System.out.println(t.getUUID());
l.doAccessible(t);
t.generate();
System.out.println(t.getUUID());
System.out.println("Completed...");

Arrrghhhh no!! He still gets an AccessControlException. But how can this be?? He did put the code in the special jvm/lib/ext folder which is granted AllPermissions. Hmmm…

The reason is that security in Java is layered and it’s the layer or “context” in Java parlance initiating the call that decides which permissions are assigned. This is why simply making a call from a Java agent in Notes/Domino to a Java library in jvm/lib/ext that need permissions other than the default set doesn’t just work. It doesn’t work because it’s the context of the Java agent which is in effect. So wouldn’t it be great if you could change the context? Well you can… 🙂 This is done using the java.security.AccessController class (docs).
The AccessController class is a nifty little thing. It works by you supplying an instance of the java.security.PrivilegedAction interface which is an interface with a single method called run. Inside the run-method you put the code requiring special permissions. Below is an example of using the AccessController class:

AccessController.doPrivileged(new PrivilegedExceptionAction() {
   public Object run() throws Exception {
      ReflectionUtil l = new ReflectionUtil();
      Test t = new Test();
      l.doAccessible(t);
      System.out.println("Completed...");
      return null;
   }
});

But wouldn’t you know it – this also fails! Of course the reason is quite obvious – I think – we cnanot just have developers go ahead elevating their persmissions themselves. As Paul Mooney would say – developers mus be controlled and kept down. It needs to be the privileged code meaning the code in jvm/lib/etc that needs to elevate the permissions. To do this we move the AccessController call info the ReflectionUtil in a special “doAccessiblePrivileged” method as this code can then decide to elevate permissions as it runs from a location with a higher security context. The code in the agent is therefor now like this (change in bold):

ReflectionUtil l = new ReflectionUtil();
Test t = new Test();
System.out.println(t.getUUID());
l.doAccessiblePrivileged(t);
t.generate();
System.out.println(t.getUUID());
System.out.println("Completed...");

And the code in ReflectionUtil looks like this:

public void doAccessiblePrivileged(final Object obj) throws Exception {
   AccessController.doPrivileged(new PrivilegedExceptionAction() {
      @Override
      public Object run() throws Exception {
         ReflectionUtil.this.doAccessible(obj);
         return null;
      }
   });
}

Now the code runs just fine as Joe is using code that knows that it might need to elevate the permissions so it provides a call doing just that (doAccessiblePrivileged).

Of course this can make it very difficult to just use a standard library from the web in Notes as it may not provide a way to elevate the permissions as no one ever saw that as a use case. In this case a wrapper API that elevates the permissions in jvm/lib/ext may be necessary to make it work.

Hope this explains it… 🙂

The example code is available for download including the required jar-file to put in jvm/lib/ext.

New IBM Notes and Domino Certification Available – get 50% off until 25 June 2013

IBM has announced a nice new entry level certification for Notes and Domino and until 25 June 2013 you get 50% off the certification test so if it fits a suggest you go and get certified. The page I link to at the bottom has the promo code you need for the rebate.

“IBM Collaboration Solutions is pleased to announce a new associate level certification: IBM Certified Associate – Notes and Domino.
This credential requires successful completion of the test LOT-442: IBM Notes and Domino Fundamentals. This test covers IBM Notes and Domino material as it relates to competencies within the following areas:

  • Architecture
  • General Administration
  • Calendaring and Scheduling
  • Replication
  • Mail
  • Clientv
  • Security
  • XPages
  • Non-XPages Design
  • Troubleshooting

Read more: New IBM Notes and Domino Certification Available – IBM Certified Associate – Notes and Domino.

Configure Eclipse 4.2 (Juno) for Notes 9


Yesterday after publishing my updated article on configuring Eclipse 3.5 for Notes 9 I wondered why I was still using such an old Eclipse build. Now Lotus Expeditor and hence Notes is still based on Eclipse 3.4 but since we develop for what’s called a target platform that shouldn’t matter so I wanted to move to Eclipse 4. So I grabbed Eclipse 4.2 (Juno) from Eclipse.org and started configuring (of course capturing what I learned). The steps are actually remarkably similar to Eclipse 3.5 (with some slight changes) so now I’m using a new Eclipse build with all the functionality benefits (the New and Noteworty page outlines many nice features) it provides plus the updated look’n’feel.

I’ve captured the steps into a new page called Configure Eclipse 4.2 for Notes 9. The page also contains a video walkthrough now (rather rough) but it shows what’s involved. The video is about 5 minutes long.

Happy coding.