My company maintains a software of one of our customers that is using Adobe LiveCycle to render HTML/PDF forms. Our customer got a support contract with us and with Adobe so that we will keep the software running on the new LiveCycle versions. This meant that we were updating our software recently to use ES4. The update went pretty smooth except for a single fact: Paging would no longer work to any page after the second page.
The paging itself was implemented using the simple server-side-script “xfa.host.pageDown()”. Paging from the first to the second page worked fine and paging back as well. Just paging from page 2 to page 3 would just bring us back to page 2. So we started to research that. We came up with a testcase that worked and simplified our production code and added complexity to the testcase until there were almost no differences in the requests sent to the LiveCycle webserivce. The only remaining difference was how the XDP file was sent to the server. In both cases we just provided an URL. In our testcase we were using a simple Apache httpd hosted web directory, in our production code we were hosting it using a custom Java Servlet from a database. We dumped the traffic between the LiveCycle server and the file server hosting the XDP and finally found a tiny but important difference. The webserver hosted file was using “Last-Modified” and “If-Modifed-Since”, which seems to be the default for Apache httpd. The traffic looked like this:
- the initial GET request came in from the LiceCycle server, containing a “Last-Modified: 1970-01-01”, Apache httpd return HTTP status code 200 with data and a modification timestamp of the file
- following GET requests from the LiceCycle server contained a “Last-Modified” with the timestamp of the file, and Apache httpd returned HTTP status code 304 Not modified
Our servlet wasn’t using the Last-Modified header and was returning every request with HTTP status 200 and the data. This tiny little difference caused LiveCycle not to jump to the third page. So what do we learn from this experience: Use HTTP status codes properly and evaluate Last-Modified header manually (if your framework doesn’t do this for you). And make sure that your application logic return status code 304 on consecutive requests by LiveCycle if the content didn’t change.