<< Previous | Home

IBM Connections application development state of the union - part 6

Part 5 was about extensions/apps on-premises and this - probably final post - will be about extensions for IBM Connections Cloud. There are different ways to extend IBM Connections Cloud - one is to add links to the app menu and another is to add actual UI extensions to the applications within IBM Connections. This post is about the latter (although the observations about the administration UI applies to both). To get it out of the way from the beginning I might as well say it flat out. IBM has really missed the mark here. The extensibility mechanism for IBM Connections in Cloud is close to unusable from my point of view. Let me explain...

Basically the extension mechanism for cloud is an iframe and you may only extend Communities which is so wrong to begin with. As mentioned previously IBM Connections is a piece of social software that focus on people and not being able to extend Profiles is baffling to me. Using a clumsy UI in the administration portal you can upload a JSON file describing the extension which in turn will make the extension show up in the main UI. The smallest file I could make work is 34 lines of JSON but basically I could do away with 3 lines. Almost all of the JSON I upload is simply cruft that seems to carry over from the on-premises widget container and as I really cannot change it why should I specify it? In essence I can only change the following 3 parameters:

  • defId - seems to be an ID of the widget
  • url - the URL to set into the iframe
  • height - the height of the iframe
Part of the JSON I upload is the widget ID. I have to specify the ID of the widget (defId) but there is no check whether it's used. Using an already used ID is allowed but only one of the widgets with the same ID shows up which is an issue as this is an obvious copy/paste error on the users part. Also the widget is added to the community page using the defId as the title but shown in the administration UI using a "name" parameter from JSON which is pretty confusing. Part of the JSON I upload is also the actual iWidget that creates and builds the iframe. I can specify my own iWidget description and the only thing that makes it not work is the ajaxProxy rejecting it making the UI fail when users load the community page. There is no upload time check. Often times an invalid JSON file only makes the UI do nothing - there is no response as to what might be wrong.

Sigh...

Once the JSON is uploaded I get an iframe of a static height with a URL set into it. The height is one thing that makes this extension mechanism hard to work with for production apps. Often times the height of the content cannot be decided at deployment time but is only known at runtime and unfortunately there is no way to change the iframe height at runtime. At least nothing which is obvious and/or documented. But now we have an iframe set the URL specified in the application JSON. The iframe is sandboxed with the following policy: "allow-same-origin allow-scripts allow-popups allow-forms". This restricts the extension and basically it may only do the following:

  • Run JavaScript
  • Make xhr requests to the server it was loaded from (same origin)
  • Open a new window/tab in the browser
There is no way for the widget to even talk to IBM Connections itself - not even the IBM Connections API. The widget may basically show static / server side generated HTML and run JavaScript. The JavaScript may make xhr requests to the server it was loaded from. That's it.

When the widget loads it may ask the surrounding page for a widget context by registering a message listener and posting a message to the parent page (parent.postMessage). The context looks like this:

{
   "source": {
      "resourceId": "ff7dd8b4-95d6-4fb4-f094-edb52e5d8eee",
      "resourceName": "Some Community Title",
      "resourceType": "community",
      "orgId": "12345678"
   },
   "user": {
      "userId": "87654321",
      "orgId": "12345678",
      "displayName": "John Doe",
      "email": "jdoe@example.com"
   },
   "extraContent": {
      "canContribute": "true",
      "canPersonalize": "true"
   }
}
From the context the widget can figure out who the user is and what community the user is in. The problem is however that the user information is unusable as there is no way my application server can trust this user information. As the context is not verifiable in any way there is no way for my server to trust the information it receives from the extension. The only way to convey user identity to my server is by using SAML and assume that a SAML assertion dance is performed when the iframe contents is loaded so the user has a session cookie relationship with my server. But this is doable - I now know the user identity based on the SAML dance.

Next thing is to make sure the user is actually a member of the community he/she is sending to my server - but oh - there is no way to decide this. My server side code cannot make requests on behalf of the user back to IBM Connections without the user having already performed an OAuth dance and authorized my application to IBM Connections. I could tell the user that we might not have tokens for him/her but it yields a crappy user experience. Plus any authorization granted expires from time to time (at least every 90 days). Also there is no organization wide OAuth authorization capabilities in IBM Connections Cloud like is the case for Google or Microsoft plus there is no super-user for IBM Connections so we're pretty stuck here.

Now this is pretty bad and combining these things basically makes it impossible to create any kind of customer or ISV solution with a decent user experience. At least if the context is important and the contents is not static.

So what do we do about it? Well IMHO the solution is pretty easy and simple which makes it even worse that IBM decided to ship this capability. Let me suggest the following points:

  • Administration UI
    Fix the administration UI including the widget JSON I have to upload. Only ask for the stuff that actually matter and induce the rest if not specified. If the uploaded file doesn't validate tell me - maybe even provide a clue as to what's missing...
  • Make the context verifiable
    When I register a widget add an option to indicate that my server needs to verify the information in the context (the JSON blob above). If I check the box generate a set of asymmetric keys and provide me one of the keys. Now the JSON context could be signed with the IBM Connections part of the key making my server capable of verifying that the information indeed came from IBM Connections. And since it's asymmetric there is no way for my server to impersonate IBM Connections. Oh and this would make the information in the context trustable even if the customer is not using SAML.
  • Making calls back to IBM Connections possible
    When I register a widget add an option for me to indicate that my server needs to make calls back to IBM Connections on behalf of the user. For additional credits allow me to specify which parts of the IBM Connections API my server may use. In combination with the asymmetric key pair above this option would include an encrypted opaque token in the JSON context blob. This token could be used by my server to authenticate my server and the request back to IBM Connections. It could be a set of automatically generated OAuth tokens but doesn't need to be. This is a secure solution as we already have a key pair in place so the token could be encrypted using the IBM Connections part of the key pair so that the widget code in the browser cannot use it. Only the server with the matching key may decrypt the token and use it for the IBM Connections API.
Now I'm no security expert but this should be secure and pretty easy to implement. With a single sweep it would make widgets in IBM Connections Cloud way more powerful than widgets on-premises and would make them much easier to develop. Only thing left then is making it possible to adjust the height at runtime but I'll let that slip for now as a basic oversight in the design of the extensibility mechanism and assume this capability will be available soon anyway.

</rant >

I have a small IBM Connections Cloud community apo on Github if you would like to see a minimal example: IBM Connections Cloud Community App Example

IBM Connections application development state of the union - part 5

Part 1 was about API's and SPI's, part 2 about Mobile, part 3 about security and "coherent-ness". This part will be about apps/extensions this time moving to on-premises.

For on-premises the extension model for IBM Connections is iWidgets and OpenSocial gadgets. You can extend Profiles, Communities and Homepage. OpenSocial is only supported in Homepage. IMO the former two (Profiles and Communities) are probably the ones mostly extended using widgets. Unfortunately these also use the oldest extension mechanism but also the most capable one. I have presented numerous times on iWidgets (e.g. see Easy as Pie - Creating Widgets for IBM Connections).

In essence an iWidget consists of:

  • A widget descriptor - an XML document describing the widget and which is pointed to in the IBM Connections on-prem setup (widgets-config.xml). The widget descriptor may also contain static HTML for the widget e.g. a "Loading..." text.
  • A JavaScript "class" having methods for various parts of the widget lifecycle such as onLoad, onView, onEdit etc.
  • Zero or more resources loaded by the widget descriptor before control is passed to the JavaScript. This can be JavaScript files, CSS files etc.
Besides being the worstly formatted document I've even seen the iWidget specification is pretty easy to follow. The specification allows for pretty powerful extensions to IBM Connections but has major drawbacks the worst being:
  • Creating a simple dynamic widget is pretty involved failing the "fast HelloWorld test". Also something simple as setting a nice widget title takes i18n files and editing LotusConnections-config.xml as well.
  • IBM proprietary - at some point IBM Mashup Server used iWidgets as well but I think the product has been discontinued with IBM Connections being the only container using iWidgets now
  • No development environment available. Only way to develop is to either use a full IBM Connections instance with the caching-hell that ensues or write an iWidget wrapper/emulator. I prefer the latter and it's not hard but really shouldn't be necessary.
  • The widgets all run as part of the page so there is no containment from a CSS perspective (a "rouge" CSS class will mess up the entire page), from a JavaScript perspective (a "rouge" piece of JavaScript both stop the entire page from loading and/or read data from the entire page).
These are pretty bad but as a developer you can learn to live with them and work around them. The worst is the last item where a failing widget makes the entire page fail to load something that seems to even affect the IBM supplied widgets.

This being said you can develop almost anything using iWidgets. You may talk to any HTTP based API using XHR whether the same source as where the widget code was loaded from or not. Worst case is that you use the built-in AJAX proxy to tunnel requests that work to work around same-origin-policy issues or if the API supports CORS you can go nuts and load data to your heart's content. The only real issue is that to convey user identity from the IBM Connections WebSphere Application Server (WAS) to a proprietary - or non IBM server (without support for LtpaToken cookies) - is tricky. Developing a simply app deployed on WAS or Domino to created an encrypted assertion of the user identity is not hard but could - and should - be part of the platform and not something I as a developer should have to worry about. It's a situation that is pretty easy to imagine would happen and IBM should have addressed it.

All things considered the iWidgets approach is proven works for most ISV/product situations or customer engagements I've been involved in. I'm just happy we and/or no customer has asked us to extend areas other than Profiles and Communities yet...

IBM Connections application development state of the union - part 4

While previous posts in this series has been about specific parts of the IBM Connections platform this is a bit more generic setting the stage for the next two ports. The next two posts are about extensions/apps for IBM Connections on-premises and in the cloud. Setting the stage for this is talking about the difference scenarios for extensions and what they would like to to and what capabilities they would need from the platform (IBM Connections).

In my mind when you provide a platform that allows for extensions - such as the extensions/apps in IBM Connections - you really need to think about not just what you want and need to provide but also what the consumer would want to do with it. What is the usage scenario of the customer / ISV? What would they want / need to do? Is the user identity important? If the context (e.g. current profile / current community ID) important? Providing an extension mechanism that doesn't allow a customer or ISV to do what they would like is almost even worse than providing nothing at all. If nothing else it leads to more frustration anyway.

Looking at the various things a customer / ISV would want to do you can list them like below. Of course there might be a different number of areas of interest but these are at the core. I note observations for both on-premises and cloud.

  • Extend required areas e.g. Homepage, Profiles, Communities, Files etc.
    • On-premises: No. Or to some extent. You can extend Homepage, Profiles and Communities. It's pretty hard to control from a policy perspecitive but it's doable. There is no support for extending other features (besides the rich text editor) which is pretty bad if you provide a service for Files or Wikis.
    • Cloud: No. Extension only available for Communities. This is really bad for a piece of social software that focus on people...
  • Access to widget context
    • On-premises: Yes. iContext provide the community / profile ID of the active community or profile.
    • Cloud: Yes. Extension can receive a context object describing the active community.
  • Ability of called REST API to obtain user identity
    • On-premises: Yes. If using IBM server using LtpaToken otherwise you need to develop custom code.
    • Cloud: No. Not without additional technology. Context provides access to the user identity but it cannot be trusted as it's not signed or authenticated in any way. Using SAML is an option but is an add-on and require interaction with IBM Support.
  • Ability to communicate with custom API (anything other than IBM Connections)
    • On-premises: Yes. You may do anything but may need to use provided AJAX proxy
    • Cloud: No. May only communicate with the same origin as the widget was loaded from. Cannot even communicate with the IBM Connections API.
  • Ability to communicate with the IBM Connections API
    • On-premises: Yes. Possible as user is most likely already logged into IBM Connections. Most likely as Profiles doesn't require authentication by default. It is however possible to configure the widget to require the user to be authentication and hence not show up for unauthenticated users.
    • Cloud: No. Widget may only communicate with the same origin as the code was loaded from.
  • Ability of an API to communicate with the IBM Connections API on behalf of the user
    • On-premises: Yes. Possible if the API runs on an IBM based server supporting LtpaToken and the API runs on the same domain as IBM Connections as the API may grab the cookie and use it when calling back to IBM Connections. Not pretty but it works.
    • Cloud: No. The API a widget would call never runs on the same domain nor is there any traditional cookie based SSO available.

As is pretty clear from the above I'm not a great fan of the extensibility model of IBM Connections Cloud and it fails in almost all areas. It's severely and utterly broken from an ISV standpoint and fails on all accounts making it unusable IMHO. I go more into details about why not in a post specific to extensions for IBM Connections Cloud. The on-premises model is okay but is cumbersome to develop for and is outdated. Also it doesn't work for cloud making us having to develop the same functionality twice. The on-premises capabilities work however and mostly allows ISV's and customers to develop the extensions they need. Again there will be a separate posts on extensions for on-premises.

IBM Connections application development state of the union - part 3

While part 2 was about IBM Connections Mobile this post will be about security and the "coherent-ness" of the platform.

IBM Connections runs/builds on IBM WebSphere Application Server (WAS) and much of the functionality is delegated to the underlying application server. Delegated responsibility is topics ranging from messaging to SMTP transport to database access and security. WAS also handles the clustering and fault tolerance and does it very well. Being built on WAS is a good thing for stability and security but it also has its drawbacks when it comes to manageability and how coherent the application feels.

But lets face it - when I buy IBM Connections I buy just that and not the underlying WAS platform. WAS only adds to the complexity. But since it's built on WAS many features are leveraged from there many features feels clunky and like they are not part of the application which I guess is right as it technically isn't. This becomes even more apparent from a security and manageability perspective.

WAS Integrated Solutions Console (ISC) provides a graphical environment to managing certificate trust, configuring directories for authentication and mapping users and groups to Java Enterprise Edition (EE) roles. But Java EE was never really meant to make sense across multiple applications. Everything in Java EE centers around the monolith application where as IBM Connections - the application - is really made up of many many Java EE applications. In v. 1.0.3 I think there was just one per feature (ie. 5 or so) where as v. 5.5 has 24 applications. 24! This means that all role configuration and access management is split over 24 applications. To makes matter worse it means there are 24 places to make sure administration privileges and the connectionsAdmin user is configured correctly. This configuration breaking in one Java EE application makes the entire thing come crashing down unless is a JMS or database access credential - then it's part of WAS. Confused!? Join the club.

Where I do manage feature A or feature B - well ISC is your Swiss army knife - it's pretty good but was never meant to manage 24 applications running and functioning the concert. That's the job of a specialized mangement UI which sadly is still missing from the product.

We still lacking a built in way of discovering profiles with problems, file library issues, orphan files, communities with no active owner and the like. Vendors such as Panagenda, Time to Act and Domain Patrol Social does a nice job of plugging the hole but seriously this kind of functionality should be provided by the platform. If a platform is core to any business there should be management tools and a dashboard to gauge the health of the application. No not separate places to check search indexes, seedlists and so on. One place.

Another place where WAS provides strong support but doesn't really help the overall perception is with security. Security is core to the IBM Connections API's but since it is delegated to WAS it makes the configuration process cumbersome and hard to troubleshoot. Since access control (authentication and authorization) is delegated from IBM Connections to WAS it's extremely hard to diagnose since the issue could be in different layers and when there are layers the real cause of the issue might got lost in the reporting chain. Is the user who cannot login due to a WAS issue (login i.e. authentication (usernname/password, SPNEGO, certificates, TAI), roles ie. authorization, directory connectivity) or due to an IBM Connections issue (no user profile matching WAS security name, missing inter-app loginname sync)? Oh and can I trace a login? Well not really as login spans across layers and it could even be different based on which IBM Connections feature I access first. Oh and difference db schemes and ID's across features makes it even worse.

My head hurts from just thinking about troubleshooting sessions like this.

In IBM Connections API access can be controlled using form based authentication, basic authentication or OAuth (and basically any way security can be managed in WAS e.g. TAI's). Now from a WAS perspective OAuth is just another supporting technology but for IBM Connections it's core to its functionality and API's. Configuration is done using command line wsadmin and requires you to be in a terminal on the Deployment Manager ("the server"). Now there nothing wrong with command line but managing API credentials for an application (IBM Connections) should be part of the app and tied to the app. It should also be possible to provide scoped access to OAuth applications - today it's all or nothing whereas granting access to just Profiles or Files would make total sense. And to makes matters worse this kind of limitation carry over to the cloud version as the core and API's are shared.

Security wise we also lack a "root" user with access to all content. Time and time again I hear it as a base requirement for many organizations evaluating IBM Connections. It's also key to customers and/or ISV's building custom applications. Without root level access you cannot provide applications that work with application data without requiring a specific user account. Try writing and app that extracts data from or populates communities across the organisation without having a user account specific to that community. Good luck. Only was is to make specific (licensed) user accounts being member of the various communities. And managing username/password/credentials just like any other user. It's really an issue that should be addressed.

There is definitely room for improvement. Now I didn't mean for this post to be such a rant but a great platform is being tarnished by really lousy "coherent-ness". The platform is starting to show its age with all the new features being added and still clearly stinks from originally being disparate apps being glued together. Painting the walls and putting in a new bathroom doesn't fix the foundation.

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.

IBM Connections application development state of the union - part 2

Part 1 was about API's and SPI's - this part will be about widgets or apps as IBM likes to call them now. There are big differences between how widgets / apps works for on-premises, cloud and on Mobile. Let us starts with Mobile as it's the quickest one to address but also the most depressing...

Besides adding menu items to the IBM Connections mobile app menu (the one that slides in from the left) and having the content load in an embedded browser control there is no support for widgets / apps on Mobile. None. Zero. Given that IBM Connections always has been marketed as social software that focus on the individual and where all content and data is tied to the user it has always been surprising to me how little focus IBM has put on Mobile from the ISV perspective in this regard. From my perspective as an ISV it would be obvious that ISV's would want to pivot of a profile, a file, a community etc. and launch into a custom app supplying that context.

I have always been a big advocate for adding widgets / apps / actions to IBM Connections Mobile. And yes I know that adding custom content to an iOS or Android app is hard and there are security implications but there are ways around it. Simply supporting declarative actions using URL token replacements would go a long way (on-premises they could be loaded from mobile-config.xml). Allow me add an action specifying the feature it should go into (Profiles, Communities, Files etc.) and allow me to add a URL pattern to it. The URL pattern should be able to take URL token replacements so my URL could be something like https://myapp.example.com/people/%uid% or https://myapp.example.com/people/%email% or https://myapp.example.com/files/%fileid%. Once activated the app could grab til touch action, replace the tokens in the URL based on the current record and load it in the browser control it uses for those aforementioned left menu shortcuts.

Obviously I'm always way too optimistic but how hard could that be? And I think it would add a ton of options to customers and ISV's for pivoting off content in IBM Connections and go into custom apps.

Thinking further about it - what if a native app for the data was present on the device and a registered URL scheme was used it would probably automatically launch into that app carrying the context along. Maybe even sending along some credentials to make this app switch transparent to the user - how cool would that be. But even it that wasn't the case (I know iOS added restrictions as to what and how many URL schemes an app could query) and I would end up in a web app it would still be a great improvement.

IBM Connections application development state of the union - part 1

IBM Connections has been on the market for a lot of time now and has always been a real strong player when it comes to application development. I thought it was time to review where we are application development wise over what will probably be a couple of posts. First off is API's...

IBM Connections is and has always been strong from the point of API's - there is an API for almost all areas of the product and always has. I think IBM Connections was the first product (maybe still the only one) that was built by IBM Collaboration Solutions using an API first approach or at least with a strong emphasis on API's.

The API's are extensive and are pretty straight forward to use. The main caveat about the IBM Connections API's is that they were designed a looooong time ago and hasn't been updated since. I went to the documentation to check and the majority of the API's hasn't changed one bit since v. 2.5. This means they are still using the once cool Atom publishing protocol using lots of XML and lots of namespaces. Stability is very nice but an XML based API is really appdev unfriendly these days and the use of namespaces makes it even worse and difficult to handle - you either handle the complexity or you simply choose the parse without namespaces. Extracting data is either done using XPath or string parsing none of which is easy or performs well and again the namespaces makes XPath notoriously difficult.

This being said there is one exception to the XML based nature of the API's. When Activity Streams were added in IBM Connections 4.5 it was brought to market with a JSON based API and is still the only component in the IBM Connections suite using JSON based API's. Due to its roots in OpenSocial the API was however hard to grasp and I don't think it got much traction despite my best efforts to make it approachable. My presentation on how to use the Activity Stream remains one of my most popular presentations at conferences.

When this is said and done I think that the most important thing IBM could do for IBM Connections API wise would be to update the API's. In todays world a JSON based API is really expected and is the defacto way of accessing data. Do away with XML and namespaces and adopt a standards based JSON approach to messages being sent to the server and returned from the server. Of course the legacy Atom based API should be left in but it should really be augmented with a JSON ditto as soon as possible.

Besides the API's there is also a set of SPI's (Service Provider Interfaces) for stuff like hooking into the event subsystem, discovering features etc. The event SPI is pretty well designed and is very useful. However it seems that it was never really polished, completed and designed for customer / partner consumption as much of the functionality is reserved for IBM widgets and never documented or supported. Other pieces of the SPI's can only run within the same JVM as IBM Connections which really makes it unusable from a partner perspective.

The worst thing about the API or SPI is however what is not there...

There is no support for programmatic user registration or user deletion / deactivation. There is no support for feature discovery from outside the JVM. There is no support for getting a complete member lists for a community based on a (LDAP) directory groups. Using the community membership API will return a list of members some of which may be groups. If that's the case good luck. Your best / only option there would be to use WIM (WebSphere Identity Manager) to resolve the group and then manually combine that result with the direct community members. Of course if you are using IBM Domino as the LDAP server start by figuring out how IBM mangled the group UID before resolving it in WIM. That's really a can of worms of its own and maybe worth a blog post of its own. There is no support for a super-user that can access data on all users behalf. There is no support for easily reusing the IBM Connections header bar if using IBM Connections on-premises.

I don't want to finish this post being too pessimistic but there is really room for improvement from the API / integration standpoint. IBM needs to step up to the plate and update the platform and make it current from an API perspective. Oh and while you are at it document the API's, create up to date examples and actually make the documentation discoverable using Google...