Make Java code for XAgents easy to test
One of the popular entries in this blog is my introduction into XAgents together with related considerations and practial applications. There are a few patterns, that make XAgents easier to develop and debug.
Despite outstanding tool contribution debugging in XPages is still wanting, so any code that you can incorporate pre-debugged is a bonus. Here is what I do:
As usual: YMMV
Despite outstanding tool contribution debugging in XPages is still wanting, so any code that you can incorporate pre-debugged is a bonus. Here is what I do:
- I try to write my logic in Java. I use the SSJS only to fetch the values I need to call my Java function
- The functions of the Java class take always the OutputStream (or the ResponseWriter) as a parameter. This is where the output goes
- For rendering XML or HTML output I use SAX with a little helper (Making one of these for JSON would be an interesting exercise)
- I try to avoid using XPages specific (e.g. variable resolver) in my class containing the logic, but rather rely on Dependency Injection to ease testing
- I debug and test the Java parts outside of XPages
// The external context and the response object
var exCon = facesContext. getExternalContext ( ) ;
var response = exCon. getResponse ( ) ;
// Deliver uncached PDF
response. setContentType ( "application/pdf" ) ;
response. setHeader ( "Cache-Control" , "no-cache" ) ;
// Force file name and save dialog
response. setHeader ( "Content-Disposition" , "attachment; filename=invoice.pdf" ) ;
// The Output Stream for Binary Output
var out =response. getOutputStream ( ) ;
var pdfProcessor = new com. notessensei. tools. PDFFormatter ( ) ;
// Here the call where "document" is a Notes document
pdfProcessor. renderInvoice (out , document ) ;
// Done
facesContext. responseComplete ( ) ;
out. close ( ) ;
Not really rocket science. The beauty of this approach: I can have a standalone Java application to test my PDFFormatter class. I use Eclipse for that. In Eclipse I have configured the Notes client's JVM as the runtime for the project. This way all Notes Java classes are found. Most likely you need the Notes program directory on your system path (but you know that). A simple testing class can look like this:
var exCon = facesContext. getExternalContext ( ) ;
var response = exCon. getResponse ( ) ;
// Deliver uncached PDF
response. setContentType ( "application/pdf" ) ;
response. setHeader ( "Cache-Control" , "no-cache" ) ;
// Force file name and save dialog
response. setHeader ( "Content-Disposition" , "attachment; filename=invoice.pdf" ) ;
// The Output Stream for Binary Output
var out =response. getOutputStream ( ) ;
var pdfProcessor = new com. notessensei. tools. PDFFormatter ( ) ;
// Here the call where "document" is a Notes document
pdfProcessor. renderInvoice (out , document ) ;
// Done
facesContext. responseComplete ( ) ;
out. close ( ) ;
public class Tester {
public static String theURL = "Notes:///8525744100531C7D/F4B82FBB75E942A6852566AC0037F284/034DAEE1CEEE2FB58525744000719185" ;
public static void main ( String [ ] args ) throws Exception {
NotesThread. sinitThread ( ) ;
Session s = NotesFactory. createSession ( ) ;
Document document = ( Document )session. resolve (theURL ) ;
PDFFormatter pdfProcessor = new com. notessensei. tools. PDFFormatter ( ) ;
FileOutputStream out = new FileOutputStream ( new File ( "invoice.pdf" ) ) ;
pdfProcessor. renderInvoice (out, document ) ;
out. close ( ) ;
NotesThread. stermThread ( ) ;
}
}
Of course that approach works too when you plan to use JUnit or a similar framework. Finally all can be glued together with ANT for a full automated environment, but that's a story for another time.
public static String theURL = "Notes:///8525744100531C7D/F4B82FBB75E942A6852566AC0037F284/034DAEE1CEEE2FB58525744000719185" ;
public static void main ( String [ ] args ) throws Exception {
NotesThread. sinitThread ( ) ;
Session s = NotesFactory. createSession ( ) ;
Document document = ( Document )session. resolve (theURL ) ;
PDFFormatter pdfProcessor = new com. notessensei. tools. PDFFormatter ( ) ;
FileOutputStream out = new FileOutputStream ( new File ( "invoice.pdf" ) ) ;
pdfProcessor. renderInvoice (out, document ) ;
out. close ( ) ;
NotesThread. stermThread ( ) ;
}
}
As usual: YMMV
Posted by Stephan H Wissel on 21 March 2012 | Comments (6) | categories: XPages