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

  • XPages series #9: How to debug an XPages application

    Karsten Lehmann  July 20 2010 09:49:53
    Are you tired of using System.out.println's to track what the code of your XPages application is actually doing and why it is not working as expected? Life as a developer would be so much easier if there was a way to debug an XPages app while it is running.
    Well, at least for code written in Java there is a solution.

    Before we start, let me summarize which other options you have as an XPages developer to get runtime information about an application:

    Writing log messages to the console or a log file/database

    Of course you can manually collect the necessary information about the application state and write it to a log.  For client-side JavaScript logging, Firebug and console.log are your friends.
    On the server-side, you can use System.out.println() in Java to write a message to the console. For server-side JavaScript, there is a command called _dump() that does the same. If you don't have your own private Domino server for development, you will then soon get a call from the administrator, because the server's log database is rapidly filled with funny log messages like "before method xyz", "after method xyz" or another popular syntax: "method xyz.1", "method xyz.2", "method xyz.3" to see whether specific lines in your code are executed or skipped for a certain set of input parameters (of course, we never do that! ;-) ).
    You should at least use some global debug switches to quickly enable/disable debugging. Otherwise, moving an application to production and removing all those debug prints when the app is ready for prime time can be a lot of work.

    To not stress the administrator too much, you should use more advanced variants of this technique that do not write to the console, but make use of a dedicated log database or send status messages via email to the developer.  The TaskJam template contains a SSJS library that generates log records for the popular OpenLog project of Julian Robichaux (Java classes to do the same are available as part of the project).
    Tommy Valand has written a helper function to send debug messages via email.

    Analyzing the XPages component tree

    For more advanced XPages applications, writing simple status messages to a log is often not enough. You need detailed information about how the XPage is stored in the server memory. For example, if your XPages contain dynamic elements like repeater controls that create part of the UI at runtime or - even more powerful - you generate the whole component tree on the fly in your code, it's very hard to find out why an application is behaving unexpectedly.
    The Medusa project of Nathan Freeman, Tim Tripcony and Colin Macdonald can help you in this case. In short, it provides a Firebug plugin that lets you examine the server-side component tree (see the screenshot section of the Medusa project page for more details), e.g. to check whether a link has any server-side event code attached at all.

    Debug library code outside of XPages/Lotus Notes

    When you write a lot of application code in Java, a smart approach is to make most of it work outside of an XPage or even outside of a Lotus Notes context. That way, you can easily debug your library code in Eclipse and you can even build test cases for test-driven development.
    Unfortunately, there is no easy approach for SSJS debugging. There might be a way to build your own runtime environment using a JavaScript engine like Rhino, but we haven't really invested much time in that area, because most of our SSJS code is just directly calling bean methods in Java.

    What is missing?

    Looks like we already have a lot of options for logging and debugging. We have more for logging than debugging though, and there is no way yet to watch Java code while it is being executed on the server. That's exactly what this article is about.

    Now why is this important? At first, you save a lot of time, because you don't have to blow up your code with dozens of println's to track a specific issue, and remove all of them again after the issue has been resolved.
    And if you need to know more about complex objects and data structures, it's pretty hard to serialize them and print all parts to the log. Finally, in case of memory profiling and searching for memory leaks, it's a lot easier to just set a breakpoint in the code and examine which Java objects are stored in the server memory than trying to dump all that information to a log, if possible at all.

    Requirements for debugging

    Well, to be able to debug Java code, the Java Virtual Machine that is running the code, must be running in debug mode. Pretty logic, isn't it? In addition, you need to have the source code of something that you would like to debug, on the one hand to define the breakpoint position and on the other hand, because the debugger has to show something to tell you what is being executed.

    The best solution

    Our first idea was: What if we could launch the Domino server as a target platform from Eclipse, just like we do with the Notes Client or Domino Designer (DDE)? Then we could bring the JVM in debug mode and it would stop when a breakpoint in the code is reached. That's a similar approach to working with the Eclipse EE development environment, where Eclipse launches an embedded Tomcat server with a servlet configuration.
    Unfortunately, we don't know (yet) how to do this, because the Domino server is a bit more than just a few Java classes.

    Our solution :-)

    But, as I said above, we do know how to launch the Notes Client from Eclipse (with installed Expeditor). And since the Lotus Notes Client is able to serve "XPages in the Client" since release 8.5.1, it should be possible to debug the executed Java code in an XPages app. And in fact, it really is.
    We tried it and it worked, but when you launch Notes from Expeditor, you have to choose between launching the Notes client or DDE. Both cannot run at the same time, which is bad if you want to make small adjustments to your XPages application.

    There is an even simpler solution that does not require installing the Expeditor toolkit: Eclipse Remote Debugging.

    Launching Lotus Notes with enabled Remote Debugging

    This technique was inspired by a blog article of Bob Balfe that he wrote back in 2008: Lotus Notes can be launched in a special mode that makes it possible to connect to a running Notes Client from Eclipse.
    You can find detailed setup instructions on Bob's blog. Unfortunately, the picture links are broken, but you should get the idea what you have to do make it work.

    The calling syntax for Lotus Notes from his blog entry has slightly changed since 2008. Here is the syntax that works for release 8.5.1 and (most probably) 8.5.2:

    C:\Program files\IBM\Lotus\Notes\framework\rcp\rcplauncher.exe -config notes -debug -console -vmargs -Xdbg:transport=dt_socket,suspend=n,server=y,address=8000 -Xss512k

    Please note how we specify the port (8000) at the end of the line. We need to use the same port when we now create a new debug configuration in Eclipse (we're using version 3.4.2):

    Image:XPages series #9: How to debug an XPages application
    Debug configuration for remote debugging of Lotus Notes

    While Lotus Notes is running in debug mode, we can now connect to its JVM from our Eclipse IDE.

    You should now add Java projects to Eclipse that contain the Java code that you execute in your XPages application and set a few breakpoints.
    When you add the Java projects, Eclipse might complain about unresolved dependencies to classes of Expeditor, Notes or DDE.
    Here is a collection of JARs that might be needed as part of the classpath (depending on your Notes configuration, you need to modify the version numbers).
    • C:\Program files\IBM\Lotus\Notes\jvm\lib\ext\Notes.jar
    • C:\Program files\IBM\Lotus\Notes\framework\shared\eclipse\plugins\com.ibm.designer.lib.jsf_8.5.1.20090926-0124\lib\jsf-api.jar
    • C:\Program files\IBM\Lotus\Notes\framework\shared\eclipse\plugins\com.ibm.xsp.core_8.5.0.20100318-1445\lwpd.xsp.core.jar
    • C:\Program files\IBM\Lotus\Notes\framework\shared\eclipse\plugins\com.ibm.xsp.designer_8.5.0.20090926-0124\lwpd.xsp.designer.jar
    • C:\Program files\IBM\Lotus\Notes\framework\shared\eclipse\plugins\com.ibm.xsp.domino_8.5.1.20100318-1445\lwpd.xsp.domino.jar
    • C:\Program files\IBM\Lotus\Notes\framework\shared\eclipse\plugins\com.ibm.xsp.extsn_8.5.1.20100318-1445\lwpd.xsp.extsn.jar

    Launching the XPages application
    To launch the application, you can either choose an XPage in the Notes launch settings of the database or create a Composite Application, e.g. with one component that either shows the XPage itself or a component created for the XPage. Regarding the latter: there is an article in this blog with a demo video from IBM how to do it.

    Image:XPages series #9: How to debug an XPages application
    Choosing an XPages as launch option

    Hijacking XPages
    For every XPage displayed in the Notes Client, the Client starts a new local HTTP server instance that will be running until you close the XPage tab. That server is running on a randomly chosen port number and the Notes client uses a unique ID in the URL to authenticate the browser:

    http://127.0.0.1:2711/xsp/path%5Cto%5Cdb.nsf/xpageName.xsp?SessionID=ID0-35c463d059feb800

    Ever read that URL from JavaScript (document.location.href) and tried to use it in the system browser? Works like a charm.

    So in case your XPages apps are not running well in the Notes Client, because its XPages viewer blocks popup dialogs or does not display things like rounded corners via CSS properly etc., you can also open that URL in any other browser. It will be served locally by the HTTP server instance of the running Lotus Notes client. The Notes Client acts like a Domino server (and you don't need to open up the ACL for anonymous access like you have to do for the XPages preview in DDE).

    To make the process of opening a running XPages application in the system's default browser a lot easier, we have developed a small helper Eclipse plugin that shows up as a new toolbar icon in the Notes Client:

    Image:XPages series #9: How to debug an XPages application
    Toolbar icon to launch an XPage in the system browser

    The code behind the toolbar action is actually very easy. It reads the currently displayed XPages url, strips a few query string parameters and calls an Eclipse method that opens the URL in the default browser.
    Here is a ZIP file with an update site and the source code:
    A word about security exceptions
    You might see ECL security exceptions, if you are using "restricted" operations in your Java code, for example such dangerous things like XML parsing. ;-). This issue is discussed in another block article.
    Remember that it's still the Notes Client that serves the XPages, although you are using them in the system browser.
    As a temporary workaround, this can be solved by appending the following code to the java policy file located in C:\Program files\IBM\Lotus\Notes\java.policy:

    grant {
          permission java.security.AllPermission;
    };


    This completely disables any security restriction that is active for XPages code (Eclipse plugins are not affected by the security manager anyway), so be careful with it!

    Summary
    The demonstrated approach is a workaround for debugging XPages backend Java code, for which there is no officially available solution from IBM yet. By launching the Lotus Notes client with enabled remote debugging, we were able to connect from an external Eclipse IDE and debug custom backend Java code of an XPages application.
    Hopefully, IBM will someday provide a better solution, for example by transforming the Domino server into a standard Eclipse target platform that can be directly launched from Eclipse.

    At Lotusphere 2010, IBM announced that XPages in the upcoming Lotus Notes release 8.5.2 can be extended with custom OSGi/Eclipse plugins, e.g .in order to split up the business logic of a large enterprise application into small extensible modules.
    With some slight modifications, the demonstrated approach should also work in that scenario, but running a Domino server directly from Eclipse would further speed up the process of developing, deploying and testing code.