Monday, November 18, 2013

Really Strange Behavior with the REST Service Control in Xpages

Today I encountered some really strange behavior when trying to add a new column to a view that is used by a REST service.  I couldn't find anything out there on this, so I decided to write a short blog post detailing what happened and how I fixed it.

I was wanting to add a new column to the underlining view that the REST service uses.   The column is going to store raw HTML that I am going to use in an ExtJs RowExpander plugin.   I create the new column and add it my ExtJs and nothing happens.  After figuring out it wasn't my code, I checked the REST service and the column was not there.

I verified everything and even restarted Notes.  To prove that the view was being read, I tried deleting a column and refreshing my browser page and sure enough the column disappeared.  To test the REST service I used the URL to see the raw JSON data.  (This is done by adding '/restData' after the Xpage URL, or whatever you entered for pathInfo).

You can see here that I am reading all columns
Here is where it gets weird.  If I enter any quotes string in the column value then nothing shows up.   If the string is the result of most any formula it works.   Note:  @Text("test123") did not work.  For clarity, the value "$91" is the programmatic name of the column "confirm91".

This doesn't work

Column value contains only text

This works

The column result is the same, but the column is now read.

Obviously the formula is fake, but for whatever reason the REST service now sees it.   Now that the REST service is pulling the column, I can use it in a grid of my choosing.  

Thursday, November 14, 2013

Creating a PDF dynamically from an XPage - Part 2

In my first post on the subject of creating PDF's dynamically from an Xpage, I went over the research that needs to be done prior to starting.   In this post I will first give an overflow of the workflow and then go into two specific problems I encountered while trying to get a working proof of concept.

Like I said in my last post, this process is fairly complicated.  I drew up this chart to show the workflow process.   To see a better workflow chart (not drawn in windows paint) see this one from Stephan Wissel.


Step 1:  User presses button, the code behind the button simply sets a sessionScope variable and the calls an xAgent Xpage.

Step 2:   The xAgent code first gets the XML from the backend data by calling a method of an utility class I wrote.  The method uses the generateXML() method of the 'Document' class.   The method will also gather XML from the line items documents as well, and merge them into a single XML document (I haven't wrote this part yet).

Step 3:  The xAgent calls a Java class which uses Apache FOB to transform XML into PDF.   It passes it the XML String and a URI to the location of the XSL stylesheet.

Step 4:  The transformation happens on the server and then presents the user with a dialog box to open or save the PDF.

Problem #1:   Can't get a Writer while an OutputStream is already in use Exception.  

This Exception is caused whenever you have any type of error in the SSJS of your xAgent.    In my case, I was modifying code written by Paul Calhoun.   I missed that there was an package statement that hadn't been changed.   I went ahead and put a Stack Overflow before figuring out what happened.   On my SO question, Tim Tripcony gave me an excellent answer on why that exception was happening and how to avoid it.   Even if you have no interest in creating PDF's you will be smarter for having read it.

Even after figuring this out, I did several things that caused the same exception.   In this context I would translate the exception to mean "Something is wrong with the code in your xAgent"  The best thing to do here it undo what you just did and figure out why the server is choking on your code.  Consider this a generic exception that can be caused by any number of issues.

Problem #2:  Getting a "WrappedRuntimeException" when trying to pass the XML to the Transformer

This problem really confused me until I turned to Stack Overflow and got a great answer from who else but Stephan Wissel.  Looking back, I should have seen this as it was obvious after the fact.  The Transformer class was expecting a URI String that points to the XML to transform.   I was passing it the actual String XML.   This was what caused the exception.  I had to modify the Transformer class slightly to convert the String XML to a StreamSource object that it was expecting.  (If I was using the same Transformer class for views, I would have changed it prior to passing it, I still should probably do this.)

Next Post

In the next post, I will explain how to created the XSL stylesheet, and my challenges with that.  I will also tell how XPath fits into all this.

Monday, November 11, 2013

Creating a PDF dynamically from an XPage - Part 1

In my Purchase Order project, one of the features I promised to the users would be a professional looking document instead of a printed web page.   Of course this was very well received by the users.  I felt comfortable suggesting this feature because I have previously watched videos showing that it could be done.

The demos that I had watched had one thing in common, they all showed how to create a PDF from a view. In my case, I need to create a single Purchase Order from the contents of an Xpage.  The Xpage that is the PO, actually shows header items stored in one document, and line items which are each stored in separate backend documents. There is an indeterminate number of line items associated with any given PO.   I quickly discovered that this piece of the project will not be easy, and in fact will be time consuming and difficult.  

In this post, the first of a series, I will document the steps to prepare to create PDF's from an Xpage.  The first step you will need to decide is which method to go about this.  The second step is to do your homework and understand the technique you decided to use.

Step 1: Deciding which technique to use.  

There are three distinct technologies available for creating PDF's.  The first is using an FDF file.  My friend Mark Roden was kind enough to give me an overview of this technique.   It seems like it is the easiest solution to create a PDF, but it does have some limitations.   You would use Acrobat (paid version) to create a form and then create a FDF file from your application to tell which data to be placed in which field on the acrobat form.   The format of the FDF is structured file that is neither XML or JSON, but seems pretty easy to pick up.

The limitation is that you would have to know that the number of fields that you need prior to creating the PDF.   In my case, a PO can have any number of line items, so I felt like using this technique would be too limiting.  If you can, I would recommend using this technique for how easy it is.  The techniques below are very different and more time consuming.

The second technique is to use iText.  I watched an older Notes in 9 video on using iText by Brian Moore. The video was very well done, and is a much watch if considering using iText.   I decided to forgo using iText because most of the more recent demonstrations that I found used Apache FOP instead of iText.  

This brings me to the third technique on creating PDFs, XSL-FO using Apache FOP.   My research led me to know that this was my best path to accomplishing my goal.  


Step 2:  Understanding how to use the XSL-FO and Apache FOP

The two resident experts in the Xpages world on using XSL-FO are Stephan Wissel and Paul Calhoun. Stephan has produced a series on his blog on how to use XSL-FO, it is must reading.    Paul has created an Notes in 9 that in 15 minutes or so shows you how to create a PDF from a view.   Paul also includes links to his demo on his site for all to use. 

The other useful site that I helped me was good ole w3schools.com.   They have whole sections dedicated to XSLT, XSL-FO and XPATH.  You will need to understand these 'languages' to create PDF's.   You will find yourself learning far more about XML than you ever cared to know.  Best to start brewing a fresh pot of coffee before diving in.

Next Post

In Part 2 of this series, I will document the pitfalls I encountered while trying to get a working proof of concept.  I also want to add that I am still plowing through all this, and I welcome in the comments any corrections if I say anything wrong.