Working with the DataExtractionAndUpdateDatabase ES2 Sample Application Part 1

I had a customer contact me for help in getting this sample application to work.
http://help.adobe.com/en_US/livecycle/9.0/samples/ServiceUsageSampleFormsDataExtractionAndUpdateDatabase.html

It’s a nice sample application that shows you how to extract data from a form, transform the XML using XSLT and then save it to a MySQL database table.

The directions don’t tell you how to create the MySQL database and this can be a challenge. You can find documentation on MySQL 5.1 (the version installed as part of an ES2 turnkey installation) here. To save you the trouble, I’ve summarized the steps you need to follow to make the process work.

Note: This assumes you are using a LiveCycle ES2 JBoss turnkey installation on Windows.

Note: There seems to be a problem with the Watched Folder end point configuration and I could only get this process to work by using the invoke command from Workbench. I’ll post a fix to the WatchedFolder configuration in another blog entry.

  1. Open a command prompt and navigate to the MySQL installation. This is {LiveCycle ROOT}\mysql\bin. So, in a turnkey installation with the default folders, you would need to go to C:\Adobe\Adobe LiveCycle ES2\mysql\bin
  2. The turnkey installation creates this MySQL database account. user = adobe, password=password. Login with the adobe user using the mysql command line tool. The command is:
    mysql -u adobe -p
    Enter “password” when prompted for the password.
    login-resized.png
  3. Now you can create a test database by entering the command:
    CREATE DATABASE test;
  4. Switch to this database by entering the command:
    use test
    Note: you do not need a semicolon (;) for this command
  5. Now you can create the table by entering the command:
    CREATE TABLE tb_DataExtractionAndUpdateDB(data BLOB);
    Your command line prompt should look like the screen shot below.
    create_db_and_table-resized.png

    Please leave the mysql prompt open so we can verify the process updates the table later on.
  6. Now the database and table are created. You should verify the configuration of the data source (test-ds.xml). This was part of the collateral/resources folder that you downloaded earlier.
    You only need to change the user from root to adobe, if you’re using the default MySQL user and password. If you’ve chosen a different user/password, make sure you update it here. Since I’m using the default adobe user, my configuration looks like this.
    test-ds-resized.png
    This file should be copied to your deploy directory. If you used the default installation settings, this would be:
    C:\Adobe\Adobe LiveCycle ES2\jboss\server\lc_turnkey\deploy
    Note:If you changed anything in this file, then you will need to restart the LiveCycle server (just JBoss, not Windows) for the change to take affect.

  7. Open the DataExtractionAndUpdateDatabase process in LC Workbench.
    process-resized.png
  8. Double-click on the properties for the SQL activity which has the caption “Persist data to Database”.
    process_properties.png
  9. Click on the button with a caption of “…” next to the SQL Statement property.
    sql_default-resized.png
  10. Click on the test button. In the “Test Result” box you should see “Number of rows affected: 1″. Let’s check this in the database. Go back to the mysql command prompt and type in
    select * from tb_DataExtractionAndUpdateDB;

    you should see this result:
    check_results_1.png
  11. We’ve now proven we can insert a null BLOB. Let’s test that one with data will work too. Change the SQL to as shown in the screenshot below and then test it. Don’t save the changes!
    sql_test-resized.png
  12. Now let’s go back to the mysql command prompt and run the query again. You should see this:
    check_results_2.png
  13. Congratulations! You’ve now proven that the sample application works in your turnkey environment.

Where to find more LiveCycle ES2 Sample Applications

I got a request from a customer asking me to help debug a problem they were having with a sample application. I’ll be posting about the solution to this soon.

After a lot of searching I discovered that this was not a sample that you get out of the box with ES2, but rather one you can download separately. To save you all this trouble and to give you some more interesting samples, I’m pasting the link below.

http://help.adobe.com/en_US/livecycle/9.0/samples/lc_sample_service.html

LC Designer: Single Web Service with Many Services

One side-effect of using Web Services in LC Designer is that you create a lot of data connections; in LC Designer and other IDEs consuming Web Services is not a big deal. For Form Desingers in particular, they seem to be consuming a lot more than the other development groups like: Java, AJAX, etc. And what amounts to is a tens of unique Web Services called within a single form. The problem is keeping up with all the WSDL and server changes. I’ve watched a developer change twenty forms because a single webservice was changed. I’ll show you a simple technique that can solve these problems.

What I do instead of creating many web services is that I create a single web service: invoke(Stirng in, String out)

This web service does nothing else but take a String as input parameter and write a String out as an output parameter. For the format of the String I use JSON. So the web service is more like: invoke(JSON in, JSON out).

Within the JSON in my object has the following:

jsonInputObject:{

       serviceID, //Says which service to invoke.

       messageObject:  {

              //Message specific stuff here

        }

}

I like JSON since its natively represented in JavaScript and I can represent what ever I want. Since most of the web service calls from LC Designer are stateless, I don’t worry about the overhead of using a stateful mechanism which adds bloat. 

Using a single web service that makes a call for you on the server side has the following advantages:

  • Don’t have to stub out a unique service call for every service
  • All services are available to you during design time.
  • Unit testing is easier because you can test your JavaScript on the form against a fixed JSON test object.
  • Adding an optional input parameter or adding a additional return parameters doesn’t require regeneration of your stubbed code.

So below is an example of what my LC Worflow process looks like:

 

ExampleService.png

In this implementation, there are only two services. One to retreive group information and other for office information. Instead of creating two web services, I just have one. For this project I’ll keep adding services to this process. I’ve had projects where are twenty service calls are represented with a single web service call.

 

LiveCycle Development Techniques

Whenever I start development on a LiveCycle project, which usually involves LC Forms, LC Reader Extensions, LC Output, and LC PDF Generator. I utilize Acrobat for most of my prototyping and debugging. I’ll list the frequently used techniques:

  1. LC Reader Extensions – For those beginning to build forms with LC Designer know their form will be Reader Extended before going into production. I’ve seen cases where they will modify a form, manually Reader Extend, and then test their change. To save time, get a copy of Acrobat installed on your machine and use that to test changes. The other way is just too
    masochistic.
  2. LC Forms – Most likely you will be exporting data from a PDF or importing data into a PDF. You need to test a form or a generated XML that binds to a form. A quick way is to open the pdf in Acrobat then to –
    • Export Data from a form: Acrobat menu -> Forms -> Manage Form Data -> Export Data
    • Import Data into a form:  Acrobat menu ->  Forms -> Manage Form Data -> Import Data
  3. LC PDF Generator – You run into a problem where LC PDF Generator gives you an error while converting a non-PDF file. Open the non-PDF file in its native application and print as a PDF. The most common error is permission not to export data or print.
  4. LC Output – Here I prefer to use a unit test case, in most cases flattening a PDF will work file in Acrobat but making an API call reveals more details.

Hope this helps.

Acrobat JavaScript Extensions – Hello World

When we think "adding a button to the Acrobat Toolbar or Menu Item" we think: C++ Plugin; There is a far easier and less known alternative via JavaScript. That’s what I’d like to write about today. I’ve finished a project using JavaScript extensions for Acrobat, the customer is very happy because he can and did modify the extension himself. The one caveat is that not all the C++ functions are available in JavaScript but nonetheless still powerful.

I like the traditional "Hello World" examples, that’s what I look for when ever I start coding in a new language, framework or library; so I’ll give the reader a "Hello World" example.

Check the JavaScript for Acrobat Documentation for the exact use of each library call.

So open up your favorite text editor and the following self-explanatory code to HelloWorld.js

function helloWorld()
{
     //Say Hello World
     app.alert("Hello World");
}

app.addToolButton({
       cName: "helloWorldBtn", // A name for your button
       cExec: "helloWorld()", //Function to Call
       cLabel: "Hello World", //The Text on the Button
       cTooltext: "Say Hello World" //The Help Text
});

Drop the HelloWorld.js to:

  • Mac – /Users/<user id>/Library/Application Support/Adobe/Acrobat/9.0_x86/ JavaScripts
  • Vista – C:\Users\<user id>\AppData\Roaming\Adobe\Acrobat\9.0\JavaScripts

Restart Acrobat and open-up any PDF and you should see the following button added to the tool-bar.

 

Clicking on the button you should see your Hello World alert.

 

Updating Hostname of WSDL Connections in XDP with LiveCycle Form Rendering Process

A lot of times form developers develop form designs locally on their machines or on development servers. When dealing with web services, they would use the local or development instances of the web services by creating data connections pointing to WSDL URLs on localhost or dev.server.com. This is perfectly fine until the forms need to be migrated to other systems such as system test, stating or productions. The form developers would need to revisit the forms and update the data connections to point to the appropriate URLs depending on which environment the forms are being migrated to.
This becomes a big time consuming issue on projects dealing with a vast amount of form designs. So recently what I have been recommending my customers is to use a form rendering process that updates the WSDL data connections in the form design automatically on the fly as the form is requested by a user.


How does this work? (Please also refer to the process map below.)

  • The process reads the requested form design resource from the LiveCycle repository.
  • It then copies the content of the form design as XML to process variable and counts the number of WSDL data connections in the form.
  • Then it loops through every WSDL connections and update the domain name including the port with a new domain name extracted from a process variable called targetURL. (This targetURL variable is passed in automatically when you set up your the Render Service setting in your form variable.)
  • It then updates the form design variable with the new XML that has new WSDL information.
  • Finally LiveCycle renders the form design into a PDF. 
wsdl-updating-form-rendering-process.png

Requirements

  • LiveCycle Forms ES server.
  • The form design has to be in an XDP format.
  • The XDP has to be in the LiveCycle repository (e.g. database, Documentum, FileNet, etc.).
  • All web services used in the XDP have to be on the same server as the LiveCycle instance.
  • The only difference between web services on various environments must be the domain name and port. (e.g. http://dev:8080/soap/services/Weather?wsdl and http://staging/soap/services/Weather?wsld – OK but http://dev:8080/soap/services/Weather?wsdl and http:/staging/soap/services/Weather2?wsdl – Not OK)
Download

Download wsdl-updating-form-rendering-process.xml
and import the XML into LiveCycle Workbench as a process.

Further thoughts
  • If you need to reader extend your forms, add a Reader Extensions action at the end of the process map.
  • If your form design is in PDF, you could modify the process map to read the PDF resource from the repository and convert it to XDP.
  • What if you only deploy PDFs to your production system and don’t want to render them only the fly? You could render XDPs to PDFs as a batch process by creating a watched folder endpoint that invokes this form rendering proess.

Dynamically creating a table with data in LiveCycle form using JavaScript

Stefan Cameron wrote an article on scripting table columns a while back. Taking that idea, how would you dynamically create a table based on some data? Well, there are a couple of ways and this blog post will show you one way of achieving it.

Continue reading…

Generating JavaScript Documentation for Script Objects

One of the things many developers often fail to do is to document their code. Code and documentation comments are not only useful to yourself but also to other developers who may have to contribute to your work or use your work as part of their work. They help increase maintainability, code readability and ease of use. As previously posted, you can create script objects in Adobe LiveCycle Designer to extend standard JavaScript classes with prototype functions and properties. Your script objects can then be distributed among teams for reuse. However, if your script objects contain a large number of functions and properties, your end users may request for documentation.

Continue reading…

Using JSON to Exchange Data with Web Services in XFA Forms

Continuing from my previous post on extending the JavaScript prototype property, another most under-utilized technique is the use of JavaScript Object Notation (JSON) as a data exchange format between a form and web services. Did you ever think of using JSON in form development? No? Me neither. I never thought of it until one of my customers suggested the possibility. It was an elegant solution, as our web services were getting more complex, we were wrestling on reading the data versus implementing solutions. JSON gave us a way to reduce hassle of working with complex objects.

Continue reading…

Extending JavaScript with Prototypes in XFA Forms

Do you sometimes wish you had functions that standard JavaScript does not provide? For instance, a trim or strip function that removes leading and trailing white spaces from a string object. In LiveCycle Designer, the traditional way is to create a script object and a function. Then to use it, you would have a function call similar to the following statement:

var newString = ScriptObject.trim(oldString);

These function calls can become lengthy in situations where the script object is located on a different page than your method call. For example:

var newString = form1.page1.subform1.ScriptObject.trim(oldString);

Continue reading…