At ILUG I attended Paul Calhoun’s excellent session “Using XML and RDBMS Data Sources in XPages”. The XML element of the session built upon articles Paul had contributed to The XPages Blog and the Lotus Notes and Domino Application Development Wiki.

Over the last few days I’ve been experimenting with various methods of using XML for reporting in XPages. My particular focus has been testing performance because in my current project I’m working with a large amount of data. Firstly I tried using an XML file generated by an overnight agent and stored on the Domino server (the agent takes some time to run). Then I tried Paul’s suggested approach of using a Java agent called from the XPage. Both took quite a long time to run with large amounts of data, during which the nhttp process on the server was hitting a high CPU usage and my development server was also stuck at 100% CPU usage. Another problem I encountered was that even though the user accessing the XPage was authenticated and even though the Java agent was called via SSJS and was in the same database, the Java parser was running as Anonymous. This exhibits itself with the rather unhelpful message “White spaces are required between publicId and systemId.” (as a comment on the LNaDAD wiki article shows). Basically, if I understand it correctly, because the parser cannot access the agent, the content returned by the request is not readable as XML, so cannot be parsed. However, when as a developer you enter the URL of the agent into a browser, you’re authenticated and you get the XML you’re expecting, leaving you baffled. The solution I used was to give Anonymous “Read public documents” privilege and save the agent with a tick in “Allow public access users to view and run this agent” on the Security tab.

Returning to my alternative of using ?ReadViewEntries on a view, giving Anonymous access to the database and view resolved the same error message of “White spaces are required between publicId and systemId.”. ReadViewEntries performed better for one simple reason. By default, ReadViewEntries only returns 30 entries from the view, although it is possible to override this by adding “&Count=x” where x is the number of entries you wish to return. It may be that with the same number of entries ReadViewEntries performs slightly better than a Java agent, I have not tested.

But with both of these I wanted to find a better solution than allowing Anonymous access to the data. As shown by Paul Calhoun’s solution, one of the benefits of XPages and SSJS is that you can use all the Java packages that come with the Domino server. After some searching on the web I came across some Java code that, with a bit of manipulation, enabled me to parse XML from a url with the relevant authentication. My knowledge and experience of Java is extremely limited, so most of this code is just converted from Java to SSJS with a limited understanding of what’s actually happening. The code is:

  1. //Create the XML Document
  2. var parsedxml:org.w3c.dom.Document = null;
  3. //Create the Parser Factory and document builder
  4. var domfactory:javax.xml.parsers.DocumentBuilderFactory =  javax.xml.parsers.DocumentBuilderFactory.newInstance();
  5. var xmldocument:javax.xml.parsers.DocumentBuilder = domfactory.newDocumentBuilder();
  6. //Read the XML from the Domino Agent
  7. var url:java.net.URL = new java.net.URL(“http://myServer/myDatabase/myView?ReadViewEntries”);
  8. var conn:java.net.URLConnection = url.openConnection();
  9. var uConn:java.net.HttpURLConnection = conn;
  10. uConn.setRequestMethod(“GET”);
  11. uConn.setAllowUserInteraction(false);
  12. uConn.setDefaultUseCaches(false);
  13. uConn.setDoInput(true);
  14. uConn.setDoOutput(false);
  15. uConn.setInstanceFollowRedirects(true);
  16. uConn.setUseCaches(false);
  17. var auth=”username:password”;
  18. uConn.setRequestProperty(“Authorization”,”Basic ” + new sun.misc.BASE64Encoder().encode(auth.getBytes()));
  19. uConn.connect();
  20. var is:org.xml.sax.InputSource = new org.xml.sax.InputSource(uConn.getInputStream());
  21. var parsedxml = xmldocument.parse(is);
  22. //Store the parsed XML to a session scope variable.
  23. sessionScope.put(“viewEntries”,parsedxml);

If you’ve read Paul Calhoun’s articles lines 1-7 and 23-24 will be familiar, so I will skip over the explanation of what’s happening there. Lines 8-10 create a new java.net.URL object (pass the relevant URL you wish to call), open it and cast the open java.net.URLConnection into a java.net.HttpURLConnection object. It looks like that has additional methods and properties that allow authentication to occur. Some properties and methods are called in lines 11-17 to determine how the java.net.HttpURLConnection behaves. The properties for authentication are set in lines 18-19. Line 18 creates a string comprising the relevant username and password with which to authenticate. Line 19 then sets the Authorization property with Basic + a Base64 encoded version of the auth string. Line 20 launches the URL with the authentication, line 21 passes it to an org.xml.sax.InputSource object and line 22 parses the XML.

Two points to note with this example. Firstly, here the username/password pair are passed directly to the string, but in practice that is unlikely to be the case. Secondly, there is no standard Java method for encoding and decoding data. The sun.misc.BASE64Encoder().encode method is unsupported so should be used with caution. Other proprietary Java classes are available for base 64 encoding, but you would need to install the relevant jar files and include them yourself.

As I have said, my Java knowledge is limited and I am sure more seasoned Java developers could improve upon this crude but effective solution. Yet after having spent quite some time getting this far, hopefully this code will help others.

2 thoughts on “Using Security-Restricted XML as an XPages Data Source”

  1. Paul,

    good example (you might want to use { Link } for code – looks nicer 🙂

    I would change 2 things:

    a) use the Apache HTTP client. It supports more authentication methods

    b) Move that code to a JavaBean (so you could use some caching in future) which makes data binding even simpler.

    Steal some code to get started: { Link }

  2. @Stephan Thanks for links. I’m sure someone (probably you) pointed me to quickhighlighter.com before. I just need to remember to use it!

    Thanks for the code for using Apache HTTP client, its very useful. Looks like I’ll be reviewing Jeremy Hodge’s JavaBean tutorials on NotesIn9.

Leave a Comment

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.