Mindoo Blog - Cutting edge technologies - About Java, Lotus Notes and iPhone

  • Customer project: Dojo 1.8 based portal on top of XPages and Domino 8.5.3

    Karsten Lehmann  18 September 2012 00:13:00
    The last months have been incredibly busy for us at Mindoo and I could not find much time for blogging. Tweeting about my findings on the web is just so much easier than to write a complete blog article.

    We spent most of our time working on web applications for desktop browsers and the iPad (including Retina support), based on our favorite web toolkits Ext.JS from Sencha as well as the Dojo toolkit.
    Since we like cutting edge development, we prefer to use the latest versions of toolkits. For Sencha Touch, this means 2.0.x, Ext.JS is available in version 4.1.x and for Dojo it's the brand new version 1.8 that we already used for a portal framework development during the past 3 weeks.

    Portal framework


    This portal framework is a customer project, so there is not much code I can share (I will try to write blog entries about specific technologies).
    But I can describe the basic ideas in this blog post and provide some links to useful toolkits that helped us building the app.

    The portal leverages Dojo's dojox.layout.GridContainer (click here for a portal sample app) to build the portal UI. Portlets can have two different render modes: IFrame and inline rendering. In IFrame rendering mode, the portlet content is completely independent from the parent page; in inline rendering mode, the portlet code can directly render its content into the container node of a dojox.widget.Portlet within the portal page.

    The portal page acts as a communication mediator between the portlets (both with IFrame and inline rendering). Portlets can send JSON based messages to the portal, which - depending on the message content - can send a response to the portlet (e.g. to return loaded portlet state information), forward the message to another portlet (to update another portlets state) or send out a broadcast message to all portlets in the page (e.g. to publish selection changes in a Dojo grid).

    More or less, the portal acts like a Composite Application on steroids. :-)
     
    Cross-domain security


    While sending messages between portlets with inline rendering is quite easy, we needed to find a way to cross the IFrame boundaries in order to send data from IFrame content to the main page back and forth.
    This is not that easy, because browsers prevent this kind of communication to avoid cross-domain security issues.

    Fortunately, there is easyxdm, a Javascript library that contains several solutions for cross-domain communication and automatically picks the right one for the current browser.

    Portlet content rendering


    Loading the portlet content for IFrame rendering mode is quite easy. All you need to do is create an IFRAME node with JavaScript and set its src attribute to the remote content URL.
    This way, portlet content can get generated in external databases or even on different servers (including servers that are not Domino based).

    This works quite well on desktop browsers. They have a good internet connection and plenty of RAM, so it's not a problem to load newer or older Dojo versions or other toolkits as part of the IFrame content.
    Scrolling content that is larger than the portlet viewport is quite easy as well. This is all handled automatically by the desktop browser.

    Unfortunately, this approach did not work well on mobile devices. Scrolling content with a Swipe gesture did not work at all and we noticed rendering issues: in many cases, the IFrame content did not render properly.
    That lead us to the development of inline rendering mode: The whole portal content is stored in one DOM tree and shares the portal's Dojo 1.8 framework.
    This is good and bad at the same time: Page load is faster, but portlets needs to be developed in a way that they don't interfere with each other and only load required resources once (like JavaScript code or CSS files).

    In addition to adding the inline rendering mode, additional tweaks had to be applied to the portal rendering in order to support drag&drop of portlets on the iPad (Dojo's GridContainer layout is pretty hardcoded to mouse events) and change the portal column width with a pinch gesture.
    To drag&drop portlets, we implemented a special edit mode, comparable to the "jiggle mode" in the springboard on iOS devices: Portlets in edit mode get a CSS based jiggle animation to illustrate that they can get moved with a swipe gesture (tap on the portlet and drag it to the target location).

    Dynamic classloading

    To implement the inline rendering mode of portlets in a clean way, we built the whole portal framework on top of Dojo's new AMD classloader architecture. This lets us define classes, implement class inheritance and lazily load portlet code so that it gets loaded when it is required for the first time, speeding up overall page load.
    By following a tutorial on the Dojo website, we could also load specific classes from different locations than the portal page itself. This enables us to separate the portal code from the actual portlet code, making the application reusable and easy to extend.

    In addition, we used the Ensure library to coordinate the loading of resources that are required for the portlet rendering process: Portlets send a JSON message to the portal with a list of required HTML, JS and CSS files and the portal only loads files that have not been fetched for other portlets before.
    When all resources are loaded, Ensure calls our callback function which then notifies the portlet that all resources have been loaded and content rendering can start.

    Modality


    Portlets can be configured to be modal. A modal portlet gets displayed in a Dojo dialog on desktop browsers (including dialog-in-dialog) and gets opened in a separate dojox.mobile.View with transition effect on the iPad in order to use all the real estate on the iPad screen. Since portlets can exchange data via the portal page mediator, this can be used to provide special settings portlets to configure one portlet from another one.
    Our first 'real life' portlets use this modality feature to display a list of documents in a document library database. A click on a list entry displays detail information of the entry in a separate dialog / mobile view including the full document richtext with inline images and attachments (leveraging a nice hidden url syntax of Domino).
    Both the list and detail portlet use Dojo's powerful Django template language to generate the HTML content.

    Backend


    The portal and portlet code and data are stored in a Lotus Domino 8.5.3 server.

    As you might know, Lotus Domino 8.5.3 contains Dojo version 1.6.x as part of the XPages runtime environment. That version is already pretty outdated and not sufficient for our portal framework usecase (e.g. no dojox.mobile.ScrollablePane).
    There is some hope that 8.5.4 will contain Dojo 1.8, but we could not wait until Q1/2013 for the 8.5.4 release (the world out there does not wait for IBM dev).
    Replacing the existing Dojo version of the server with a newer one is more or less a hack and not supported as well, so we decided to render the whole portal UI in our own code and develop a set of REST services to communicate between frontend and backend code.

    Content rendering is done in an XAgent style XPage. The page loads one or more files from the database design (added in the Java perspective of Domino Designer), parses placeholders in the text content with a regular expression (e.g. to include other files or insert paths and multilingual text phrases coming from property files in the database design) and sends the output to the browser.

    We've got REST services to load/store information about all the portlets on the portal page. Each portlet has a state and appearance information as a JSON object (the latter e.g. to store in which column of the portal a portlet should be displayed).
    The REST services are implemented with a Java control similar to IBM's rest service in the Extension Library (using the XPages extensibility API), but we removed the SSJS functionality from the control and directly call Java code (that's much cleaner than writing SSJS code that then calls our Java classes).

    For each portlet instance, we create a Notes document in the database. There is a document to store the overall state of the portal page itself and there are configuration documents in the database to configure which portlets can be added to the page by the current user.
    By replacing the backend storage code, portlet data can optionally be stored temporarily in the user session (sessionScope, viewScope). And since the whole framework is developed in a modular way, the portal UI can also be replaced by something else, e.g. to display new tabs instead of portlets. Actually, we don't use the terms "portal" and "portlet" in the framework. They are called "WorkbenchPage" and "ViewPart", similar to Eclipse terminology and displaying them in a portal layout is just a single use case.  

    Summary

    Developing this application was really fun, especially the iPad and CSS animation part.
    The only thing that was a real PITA was to get the whole stuff working on Internet Explorer 7 (fortunately, only the desktop part, not iPad mode).

    Hopefully, some of the concepts and links in this article are helpful for others as well, although there is not a single line of code in it. :-)