Lotusphere 2009: AD215 – Practical DXL Magic

Just sat through Stephan Wissels session on DXL and it was great. Good slides, not too many of them, excellent demos and altogether a great session. Way to go!

Below are the cliff notes.

  • IResource in DDE returns DXL
  • DXL Studio by Stephan Wissel
  • DXL Explorer
  • Setting setForceNoteFormat=”true” makes export round trip safe but not usable for anything else than round tripping (== binary)
  • stream out has to be UTF-8
  • Switch of “Compile LotusScript” to avoid script related import options; you can always recompile later
  • Watch out for line break issues; improvements needed; work from DOM tree in memory
  • If export fails try exporting design elements one by one; issue is probably a race condition as an 88 millisecond wait between design elements makes it work
  • Get a decent XSLT/XPath editor – NO Notepad/vi
  • Approx. 156k lines of LotusScript in all IBM templates – thought it would be more (based on 69 templates
  • Cocomo tool for estimating how much time it takes to redo code
  • Cool demo showing how to transform a view to a XPage, some copy/pasting required but it works like a charm
  • Even cooler demo transforming a view to a XPage, again copy/pasting required but worked perfectly

I’m trying to create script libraries using DXL – possible?

I have spent a little time this weekend trying to create Java script libraries (that is script libraries with Java code and not “JavaScript” libraries) from scratch using DXL. Exporting the DXL of a script library with a jar-file imported into it yields some base64 in a <javaarchive /> tag. The base64 data is however not decodable as it’s not valid base64. Base on prior experiences with this kind of stuff I tried decoding the bytes but without success.

The header in base64 is (or at leas to a multiple of 4 characters) is “UEsDBBQACAAIAKyEATkAAAAAAAAAAAAAAAAUAAAA”. I guess the beginning is probably a CDFILEHEADER struct (based on prior help) but I’m unable to decode it… 😦

The struct should start with a DSIG struct (16 bit unsigned integer and a 32 bit unsigned integer) but I’m unable to get anything that makes sense. I end up with 20555 for the first WORD but that doesn’t “compute”. Bummer!

If you’ve done any work on this and is willing to share please drop me a comment. Thanks.

Exporting DXL for databases with Java web services

Today I needed to export a database application containing a web service written in Java as DXL. How stupid of me to think that I could do this with only Notes.jar on my build path… Doing such an export will make your code throw java.lang.ClassNotFoundExceptions unless you have the following libraries on your build path:

  • jvm/lib/ext/notes.jar (not much surprise there)
  • jvm/lib/ext/websvc.jar (due to missing lotus.domino.websvc.client.Service)
  • jvm/lib/ext/mail.jar (due to missing java.mail.Multipart from lotus.domino.ws.ServiceContext)
  • jvm/lib/ext/jsdk.jar (due to missing javax.servlet.http.HttpServlet)
  • jvm/lib/xml.jar (due to missing org.apache.xerces.parsers.SAXParser)

The above was found by diagnosing and reading ClassNotFoundExceptions in Eclipse at runtime since ClassNotFoundException is a runtime exception.

Now back to exporting…

Building XPath expression from XML node

When programmatically dealing with large XML (or DXL) documents it is often beneficial to be able to indicate, for logging or similar, which node the processing stopped at or where the “thing” you are logging was found. The simplest way to do this for XML is using XPath. The code below is from a library I wrote and constructs a XPath expression to the org.w3c.dom.Node supplied to the method.

Consider a XML document like the one below and the below table. The left column shows the title we supply to the method and the right column the returned XPath. Notice how the method will try to use “known” attributes to address the specific node (id/name attribute) to make the XPath more readable. If no “known” attribute is found we fall back to the sibling index.

Supplied node XPath
Title node of “Harry Potter and the Chamber of Secrets” bookstore/book[@id=’2′]/title[1]
Second tag node of “Harry Potter and the Prisoner of Azkaban” bookstore/book[@id=’3′]/tags[1]/tag[2]

If you combine this with a nice logging engine like log4j you have a robust solution for reproducing parsing issues.

Use to your heart’s content…

<?xml version="1.0" encoding="iso-8859-1" ?>
<bookstore>
  <book id="1">
    <title>Harry Potter and the Philosopher's Stone</title>
    <isbn>0747532745</isbn>
    <tags>
      <tag>children</tag>
      <tag>stone</tag>
    </tags>
  </book>
  <book id="2">
    <title>Harry Potter and the Chamber of Secrets</title>
    <isbn>0747538484</isbn>
    <tags>
      <tag>children</tag>
      <tag>secrets</tag>
    </tags>
  </book>
  <book id="3">
    <title>Harry Potter and the Prisoner of Azkaban</title>
    <isbn>0747546290</isbn>
    <tags>
      <tag>children</tag>
      <tag>prisoner</tag>
    </tags>
  </book>
</bookstore>
/* *********************************************************************
 *                    *** DISCLAIMER ***
 * This code is covered by the Creative Commons Attribution 2.5 License
 * (http://creativecommons.org/licenses/by/2.5/).
 *
 * You may use this code in any way you see fit as long as you realize
 * that the code is provided AS IS without any warrenties and confers
 * to rights what so ever! The author cannot be held accountable for
 * any loss, direct or indirect, afflicted by using the code.
 *
 * *********************************************************************
 */

import java.util.Stack;

import org.w3c.dom.Element;
import org.w3c.dom.Node;

/**
 * Utility class for dealing with XML DOM elements.
 *
 *
 * @author Mikkel Heisterberg, lekkim@lsdoc.org
 */
public class ElementUtil {

   /**
    * Constructs a XPath query to the supplied node.
    *
    * @param n
    * @return
    */
   public static String getXPath(Node n) {
      // abort early
      if (null == n) return null;

      // declarations
      Node parent = null;
      Stack hierarchy = new Stack();
      StringBuffer buffer = new StringBuffer();

      // push element on stack
      hierarchy.push(n);

      parent = n.getParentNode();
      while (null != parent && parent.getNodeType() != Node.DOCUMENT_NODE) {
         // push on stack
         hierarchy.push(parent);

         // get parent of parent
         parent = parent.getParentNode();
      }

      // construct xpath
      Object obj = null;
      while (!hierarchy.isEmpty() && null != (obj = hierarchy.pop())) {
         Node node = (Node) obj;
         boolean handled = false;

         // only consider elements
         if (node.getNodeType() == Node.ELEMENT_NODE) {
            Element e = (Element) node;

            // is this the root element?
            if (buffer.length() == 0) {
               // root element - simply append element name
               buffer.append(node.getLocalName());
            } else {
               // child element - append slash and element name
               buffer.append("/");
               buffer.append(node.getLocalName());

               if (node.hasAttributes()) {
                  // see if the element has a name or id attribute
                  if (e.hasAttribute("id")) {
                     // id attribute found - use that
                     buffer.append("[@id='" + e.getAttribute("id") + "']");
                     handled = true;
                  } else if (e.hasAttribute("name")) {
                     // name attribute found - use that
                     buffer.append("[@name='" + e.getAttribute("name") + "']");
                     handled = true;
                  }
               }

               if (!handled) {
                  // no known attribute we could use - get sibling index
                  int prev_siblings = 1;
                  Node prev_sibling = node.getPreviousSibling();
                  while (null != prev_sibling) {
                     if (prev_sibling.getNodeType() == node.getNodeType()) {
                        if (prev_sibling.getLocalName().equalsIgnoreCase(node.getLocalName())) {
                           prev_siblings++;
                        }
                     }
                     prev_sibling = prev_sibling.getPreviousSibling();
                  }
                  buffer.append("[" + prev_siblings + "]");
               }
            }
         }
      }

      // return buffer
      return buffer.toString();
   }
}

Lotusphere 2007: The power of DXL (AD503)


Apart from being told that the DXL implementation in Notes/Domino 8 will be able to surface the source code and WSDL from web services the session was below my expectations.

The fact that the source code of web services will be surfaced will make LotusScript.doc able to pick it up which is nice since I’ve had problems with this in the past (Domino 7 web services woes). I talked to the developers about this last year and it appears I’ve been heard. Thank you for that!

Mark Ambler: Using LotusScript to import an image resource

I just saw that Mark Ambler wrote some code to import an image resource into a Notes database using DXL. It complements the code I wrote some time back to export an image resource from a database using DXL (Helping out a fellow blogger getting the actual bytes of an image resource – a lesson in the intricacies of DXL representation).

See the post for the complete code: Using LotusScript to import an image resource