The following post walks you through creating a LiveCycle process within Workbench that generates a PDF document using LiveCycle Output 8.2. First a request is received via SOAP, then we look up configuration parameters in a properties file, then we retrieve records and data from a database, then we merge this data with a form template, and finally we write the file out to disk.
Prerequisites:
- A database and tables to query with a valid datasource (named DEMO_DS below).
- LC Turnkey Install 8.2
- LC Workbench
- An XDP template to merge with the data.
Overview
Here is a screen shot of what the whole process looks like: View image
The name and location of the XDP template and the data to merge is kept in the database so I can use this as an example of pulling from a database. When the process starts, the user will have to enter a formId and a customerId. The formId is used to look up the form name and location form a table and the customerId is used to look up the customer specific data from the database.
Here are two screen shots of my basic tables that you will have to copy unless you want to hard code a bunch of things.
View image
View image
Steps
- Create the following global variables:
- customerData as xml
- customerId as String (Input & Required)
- formId as String (Input & Required)
- formLocation as String
- formName as String
- pdfOutput as Document
View image - We need to extract the form name a location from the database. This next step is what you need to do to extract a single result from a database.
- Insert the component "Foundation | JDBC | Query Single Row" as your start component.
- Under "Input | Datasource Name" enter a "literal value" of your datasource name. I called mine "java:DEMO_DS".
- Under "SQL Statement", click on the "..." button and enter a query that will extract the form location. Mine happens to be "SELECT formLocation, formName FROM demo.tblforms WHERE formId = ?".
- Check the box, "Use Parameterized Query".
- Enter the variable that you want to substitute for the question mark, which in my example is formId.
View image - Click "OK".
- Under "Data Mapping" click on the "..." button to map the results to useable variables.
- Since our query stated that we want "formLocation" and "formName" we need to map the result to variables. Map "formLocation" to your "formLocation" global variable and do the same for formName (as per screen shot).
View image - Click "OK" and now you have the XDP name and location from a table. You could hard code the name and value if need be.
- Now you need to extract the customer data that will be merged with the XDP template form.
- Insert the component "Foundation | JDBC | Query for Multiple Rows as XML" and attach to the last component.
- Under "Input | Datasource Name" enter a "literal value" of your datasource name. I called mine "java:DEMO_DS".
- Under "SQL Statement", click on the "..." button and enter a query that will extract the customer data. Mine happens to be "SELECT * FROM demo.tblcustomerdata WHERE customerId = ?
- Check the box, "Use Parameterized Query".
- Enter the variable that you want to substitute for the question mark, which in my example is customerId.
View image - Finish by clicking "OK" and now you have a query that will obtain the XDP name and location from a table. You could hard code the name and value if need be.
- Under "XML information" click on the "..." button to map the results to an xml structure.
- The next dialog is a module used for creating XML from your query. The XML that you define here should match the schema that you created in the XDP form. This module can only create very basic and flat XML structure. Follow my screenshot below to create your basic XML structure that will be merged to the template.
View image
What you will end up with is an XML document with a root node called "main", a repeating node called "customer" and 9 customer related fields in the repeating node that is bound to the XDP template once we merge. - Click "OK" to close the "XML Document Info Editor" dialog.
- Under "Output | XML document" select the XML "variable" that you created called "customerData".
- Now you have all the data from the customer that we will merge into the form.
- Next I added a default logger just to verify all my information.
- Add the "Foundation | Variable Logger | log" component and attach it to the last component.
- Next we need to create the PDF with the "Output" component that is only available if you installed "Output" with LiveCycle.
- Drop the "Output | Output | generatePDFOutput" component and attach it to the last component.
- Under "Input | Tranformation Format" select a "literal value" of PDF.
- Under "Form" select the "variable" that you filled earlier called "formName".
- In the "Context Root" select the "variable" that you filled earlier called "formLocation".
- In the "Input Data" select the "variable" that you filled earlier called "customerData".
View image - In the "Output | PDF Output" section select the "variable" called "pdfOutput". This will put the resulting PDF into this variable.
- Now you have everything you need in memory but you need to see the resulting PDF so we'll save it to disk so we can view it.
- Drop the component "Foundation | File Utilities | Write Document" and attach it to the last component.
- Under "Input | Pathname Pattern" enter a "literal value" of the file location where you want to save the PDF. In my case I used "C:\\BlogDemo\\HeyThere.pdf".
- Under "Document" select the "variable" that you want to save to disk, "pdfOutput".
- Select "Make Unique" so that you don't overwrite anything and you can see your results every time the process is run. It will create a new file every time.
View image -
You're done! Run the process by right clicking on the process map (after you Activate it) and enter the two input parameters that correspond to the values that you're looking up in the database. In my example I would do:
View image - And then I would have a PDF in my folder "C:\BlogDemo\HeyThere.pdf".
I had a problem when I tried to implement this example.
I don't know what I have to put in the "Input | Datasource Name" field. I don't know my datasource name.
I have tried lots of things, but when test it on the SQL statement it says that my DatasourceName is not bound.
What do I have to do?
Have you created your datasource? In my "Prerequisites" I mention you need: " A database and tables to query with a valid datasource (named DEMO_DS below).". Basically a datasource is a pointer to your database with all the necessary connection information. If you're using JBoss, datasources will reside in your "deploy" folder with a "-ds.xml" extension. Inside that file will be an xml node with the name of your datasource.
Here is a JBoss link I found on the subject: http://docs.jboss.org/jbossas/getting_started/v4/html/db.html
Do you have the customerForm1.xdp form you can send me? This article is GREAT... but the orchestration for me fails when trying to output the pdf.
should formLocation have two slashes after the word "repository" ?
Thanks for a great tut.
Elaine
I placed a link at the bottom of the blog with a sample. I couldn't find the original sample but this one should work. It could be a number of problems including the settings you have in your form. If you look at my form you can see that it's as simple as they come. I also embedded a schema inside the form if you wanted to see what the data should look like. Good luck.
hi... Brad...
Its a great article and gives good insight for Processes in LiveCycle.
I have a query regarding xml definition in 2nd operation. Refernce point 8 in this article,
"The next dialog is a module used for creating XML from your query. The XML that you define here should match the schema that you created in the XDP form. This module can only create very basic and flat XML structure. Follow my screenshot below to create your basic XML structure that will be merged to the template."
It seems like process will get dependent on the form schema. What if I am giving a form-id whose schema is different from what is mentioned here?
Please, help me in this case or correct me if I am understanding something wrong.
Thanks and Regards,
Ambika
The portion of the orchestration that you are referring to is a component that creates XML data from an SQL query. The component only creates a very flat structured XML document. You can very easily map the columns that are retrieved from your SQL query to any user-defined node name in the XML but you can't map the query to an existing schema definition in this step.
To accomplish what it is I think you're asking for you would have to create 2 XML variables. XMLVar1 would match or be bound to your schema and XMLVar2 would be created as per the instructions in this post. Then add a SetValue component to map from one XMLVar2 to XMLVar1 after you perform your SQL query.