" /> LiveCycle Product Blog: January 2008 Archives

« December 2007 | Main | February 2008 »

January 30, 2008

Which Version of Reader?

In some cases you may want to ensure that the users filling in and submitting your forms are using the version of Reader that you designed your forms to function with. In most cases if you have developed your form with functionality that requires Reader 8.1.1 for example, and the user opens the form in Reader 7.0.9, Reader will attempt to "degrade gracefully" providing as much functionality as possible to the user. They will be notified that the form may not work as designed and that they should upgrade but they may still be able to complete and submit the form.

You can control your form programmatically by looking at the host "version".

var vCurrentVersion = 0;
vCurrentVersion = xfa.host.version;

vCurrentVersion will be equal to the version of Reader currently used. In my case, the numeric value is 8.101.

If you're curious as to whether or not Reader or Acrobat has been used to complete the form, that can also be detected.

var vApplicationName = "";
vApplicationName = xfa.host.appType;

vApplicationName will result in either 'Exchange-Pro" for Acrobat or "Reader" for Reader.

To tie the version and the logic together you'd be looking at something like this:

if(xfa.host.version >= 8.101)
{
resultText.rawValue = "Good.";
}
else
{
resultText.rawValue = "Bad.";
}

In the case of "Bad" you may want to protect the form fields or disable the submit button to ensure version compliance of your users.

January 23, 2008

LiveCycle Clustering - Folder Configuration Checklist

When deploying LiveCycle ES to a J2EE application server cluster for load balancing and/or High Availability, there are a few filesystem folders that need to be in place to ensure that the cluster functions properly. The locations of these are configurable during the install-config phase, or afterwards through the LiveCycle Admin Console. Just navigate to Home->Settings->Core System Settings->Configurations.

Global Document Storage Root Folder
This is the most important folder as far as LiveCycle clustering is concerned. There should only be one per cluster. All members of the cluster should have read-write access to this folder. In the case of a horizontal cluster with multiple physical nodes, the Global Storage Folder should be on a network share. The folder should be hosted on a reliable, High-Availability storage device (SAN, NAS) or file server. Networking to this folder should be fast and reliable.

This folder should also be regularly backed up as part of your disaster recovery strategy. The backups should be exactly in synch with your LiveCycle database backups. In the rare event of a complete disaster, the DB backup and the Global Storage Folder backup should be restored in conjunction with each other. If separate IT groups are responsible for the backup of the appserver filesystem and the DB, procedures should be put in place so that these backups are co-ordinated to happen during the same time window.

Temporary Folder
This folder should be created on exactly the same location on all members of a cluster. Each cluster member should have its own LiveCycle Temporary Folder.

Adobe Server Fonts Folder
This folder should be created on exactly the same location on all members of a cluster. Each horizontal cluster member should have its own LiveCycle Fonts Folder. Vertical cluster members can share this folder. The contents should be the same on all cluster members. This folder is always created wherever LiveCycle is installed (/opt/adobe/livecycle8/fonts/ or C:\Adobe\LiveCycle8\fonts\). Make sure that this folder's contents are copied to all of the horizontal cluster members.

Customer Fonts Folder
This folder is usually empty unless your documents or forms require special fonts.
This folder should be created on exactly the same location on all members of a cluster. Each horizontal cluster member should have its own LiveCycle Customer Fonts folder. Vertical cluster members (those on the same server) can share this folder.

System Fonts Folder
Ensure that this folder (whose location is usually predictable for all LiveCycle-supported Operating Systems) is in the same location for all members of a horizontal cluster. In Windows, this is usually C:\Windows\Fonts\. On AIX, this is usually /usr/lpp/X11/lib/X11/fonts/

AppServer Transaction Log Folder (WebSphere)
WebSphere 6.1 lets appserver instances recover one another's transaction logs (peer recovery). For this to work, define a common network share for all members of a cluster. You can find the setting using the WebSphere Admin Console as a property of the Transaction Service (Container Services). An understanding of lease-based file locking might be useful in configuring this. Windows 2003 Server's CIFS as well as v4 of NFS support this. More details are available in two excellent IBM WebSphere Developer Technical Journal articles:
- Transactional high availability and deployment considerations in WebSphere Application Server
- Automate peer recovery for transactions and messages in WebSphere Application Server

January 17, 2008

2D Barcode Capacity

There's no simple magic formula for the calculation of the Barcode size required on a form as the type and quantity of data changes from form to form (character types, case, special character use, etc.) but this sample will allow you to enter or generate sample data and test the results against a number of different barcodes. Bring this form into Designer and you’ll be able to manipulate the sizes of the Barcodes to test the capacity of different configurations.

January 16, 2008

Changing Script at Runtime

If you would like to experiment with Script within your PDF document, this sample shows how you can change and execute script at run-time without having to return to Designer to make the modifications. You can enter code into the script box, click the execute button, and the code will be run. Any errors will be displayed in the text box below. Quite useful when debugging different code techniques.

January 14, 2008

LiveCycle - Leveraging Windows PowerShell

PowerShell is Microsoft's new scripting environment for Windows, formerly code-named Monad. It will be native to the upcoming Windows Server 2008. Microsoft has let it be known that this will be the system administration environment for Microsoft products going forward.

It is based on the .NET framework. It is a shell as well as a scripting language. It is object-based and extensible. It comes with about 100 so-called commandlets whose output can be piped into other commandlets. For current Windows versions, you can download PowerShell 1.0

PowerShell can be used to gather process information. Here is the PowerShell command to display all running processes that are consuming more than 100 MB of RAM (WS=Working Set)
Get-Process | where { $_.WS -gt 100MB }

Here is the command to list all Windows services, sorted by their status, and then by the display name:
Get-Service | Sort-Object status, displayname

Command to list all Windows services that has the term "Adobe" in the Display Name:
Get-Service | Where-Object {$_.displayname -like "*Adobe*"}

The following sequence of PowerShell commands lets you query your remote SQL Server 2005 LiveCycle database to get a list of all User Manager domains, provided you have the SQLServer client installed:
$SqlConnection = New-Object System.Data.SqlClient.SqlConnection
$SqlConnection.ConnectionString = "Server=192.150.23.6;Database=lc_es;user=sa;password=mypassword"
$SqlCmd = New-Object System.Data.SqlClient.SqlCommand
$SqlCmd.CommandText = "SELECT id, commonname, domainname, syncstate FROM lc_db_usr.EDCPRINCIPALDOMAINENTITY ORDER BY domainname"
$SqlCmd.Connection = $SqlConnection
$SqlAdapter = New-Object System.Data.SqlClient.SqlDataAdapter
$SqlAdapter.SelectCommand = $SqlCmd
$DataSet = New-Object System.Data.DataSet

Return the number of returned records
$SqlAdapter.Fill($DataSet)
Display the returned records
$DataSet.Tables[0]
If the id is only partially displayed, get the full value by passing the record number
$DataSet.Tables[0].rows[2].item("id")

These have been tested to work in Windows Vista 32-bit.

PowerShell blog
Microsoft TechNet Script Center

January 10, 2008

LiveCycle and IBM DB2 - Bootstrapping to the Right Tablespace

"Bootstrapping" is the term commonly used for the creation of tables, indexes, views and sequences by LiveCycle in the database. For DB2, getting these to get created in the designated tablespace has been a struggle. This has mainly been because unlike WebSphere's JMS Message Store which asks the configurator for the name of the database schema to use, LiveCycle does not. As a result, tables, indexes, views and sequences all end up in the USERSPACE1 tablespace or the bootstrapping will fail.

Minimum required storage is 300 MB, 500 MB is better.

Here are steps you can take to ensure that LiveCycle bootstraps to the tablespace you want it to.

CREATE NEW BUFFERPOOL WITH 16 KB PAGESIZE
- Using the DB2 Control Center or the Command Line Processor (CLP), create a bufferpool (called LC_AIX for example) with a 16 KB pagesize. For a 300 MB bufferpool of 16 KB page size, you can create a size of 18,750 pages.

CREATE NEW SYSTEM TEMPORARY TABLESPACE WITH 16 KB PAGESIZE
- Create a "system temporary" tablespace called LC_SYSTEMP and configure it to use the newly created bufferpool

CREATE NEW REGULAR TABLESPACE WITH 16 KB PAGESIZE
- Create a new "regular" tablespace called LIVECYCLE, also configured it to use the newly created bufferpool. You could create another 16 KB bufferpool for this, it's up to you based on your corporate IT policy. Also, if possible, delete the USERSPACE1 tablespace that is created by default whenever a new database is created in DB2. It only has a 4 KB pagesize which is insufficient for LiveCycle.

CREATE NEW SCHEMA and DB USER
- Create a new schema called LC_USR. Depending on your IT policy, you would also have to create an OS user. For example, if DB2 is running on Windows, create a Windows user named LC_USR first and assign the user to the DB2USERS Windows user group. Then create the schema with this user. Creation of the schema will also create a DB2 DB user. If you used DB2 Control Center to do this, you wouldn't see the new user until you log out and then log back in!

GRANT ADDITIONAL AUTHORITIES TO DB USER
- Using DB2 Control Center or CLP, change the user LC_USR giving it two authorities, namely 'Connect to database' and 'Create tables'.

SET DEFAULT TABLESPACE FOR DB USER
- Also set this user's default tablespace as LIVECYCLE, with GRANT if your IT policy permits
- Make sure the schema is set as LC_USR

CONFIGURE WEBSPHERE
- If your appserver is WebSphere, make sure that the schema for the JMS message store is LC_USR
- Also for WebSphere, ensure that the J2C Authentication Alias for LiveCycle uses the same user credentials

START WEBSPHERE MESSAGING ENGINE
- Start the WebSphere appserver instance(s) hosting the JMS messaging engine(s).
- Check the tablespace, you should see eight tables with names starting with SIB... SIB is IBM's WebSphere Service Integration Bus.

START WEBSPHERE INSTANCE HOSTING LIVECYCLE, DEPLOY LIVECYCLE EARs
BOOTSTRAP LIVECYCLE
- Bootstrap LiveCycle using LiveCycle Configuration Manager (LCM).

VERIFY
- Check DB2. Tables, indexes, views and sequences belonging to LiveCycle (many but not all have names that start with EDC...) should now be created in the designated tablespace.
- Verify by logging in to the LiveCycle Admin Console and navigating to Home ->Services ->Archive Administration->Service Management. About 140 services should get listed, depending on the LiveCycle components you have licensed.

UPDATE DB STATS
- Run update statistics so that queries run faster - CLP command is REORGCHK UPDATE STATISTICS ON TABLE ALL

RUN CONFIGURATION ADVISOR
- Run DB2 Configuration Advisor on the database configuring it for "a mixed" workload, fewer than 10 (short transactions), faster transaction performance, 100 average number of connected remote applications, and "cursor stability" isolation level.

January 09, 2008

LiveCycle - LDAP Directory Synch Verification

One of the questions that consistently come up during LiveCycle ES installations is how one would go about verifying LiveCycle's synchronization with the corporate LDAP directory. If you have access to a database querying tool such as Aquafold AquaDataStudio, Microsoft Visual Studio, Oracle SQL Developer or Quest TOAD, you can run some queries against the LiveCycle database. Of these tools, AquaDataStudio supports all of the database platforms LiveCycle supports, runs on Windows, Linux and Solaris, and supports JDBC.

- run the following query against table EDCPRINCIPALDOMAINENTITY to determine the id of the LiveCycle User Manager domain you have created for your LDAP directory (replace lc_db_usr with your schema name):
SELECT id, commonname, domainname, syncstate
FROM lc_db_usr.EDCPRINCIPALDOMAINENTITY
ORDER BY domainname

The id will look something like this:
E69D93E4-C969-F1A7-105D-41C786157625

- Using that id, run the following query against table EDCPRINCIPALENTITY to determine the number of users that have been synched (replace lc_db_usr with your schema name):
SELECT COUNT(*) AS Expr1
FROM lc_db_usr.EDCPRINCIPALENTITY
WHERE (refdomainid = 'id_from_first_query') AND (principaltype = 'USER')

- for more details on the users, run this (replace lc_db_usr with your schema name):
SELECT canonicalname, commonname, description, email, originalname, status
FROM lc_db_usr.EDCPRINCIPALENTITY
WHERE (refdomainid = 'id_from_first_query') AND (principaltype = 'USER')
ORDER BY canonicalname

- run the following query against table EDCPRINCIPALENTITY to determine the number of groups that have been synched (replace lc_db_usr with your schema name):
SELECT COUNT(*) AS Expr1
FROM lc_db_usr.EDCPRINCIPALENTITY
WHERE (refdomainid = 'id_from_first_query') AND (principaltype = 'GROUP')

- for more details on the groups, run this (replace lc_db_usr with your schema name):
SELECT canonicalname, commonname, description, email, originalname, status
FROM lc_db_usr.EDCPRINCIPALENTITY
WHERE (refdomainid = 'id_from_first_query') AND (principaltype = 'GROUP')
ORDER BY canonicalname

These queries have been tested against SQL Server 2005 from Microsoft Visual Studio 2005.

January 04, 2008

Invoke LiveCycle with Visual Basic .NET 2005/2008

LiveCycle services can be invoked via SOAP from a Windows dektop application built with Visual Basic .NET

The basic steps are (for both Visual Studio 2005 and 2008):
1) Create a "Windows Application"
2) Create a "Web Reference" and point it to the WSDL file of the LiveCycle service you are interested in. The Forms service WSDL is at http://ip_address:web_container_port/soap/services/FormsService?wsdl. Examples are:
- JBoss : http://jboss_server:8080/soap/services/FormsService?wsdl
- WebSphere : http://was_server:9080/soap/services/FormsService?wsdl
- WebLogic : http://wl_server:7002/soap/services/FormsService?wsdl
3) Use this web reference to start coding

Sample code (Visual Studio solution) invoking the RenderPDFForm and ProcessFormSubmission methods of the Forms service is attached. It contains one form with two buttons.

The click event on the first button:
- reads an XML data file from a Windows desktop client's local disk
- calls Adobe LiveCycle ES Forms using SOAP over HTTP to render an XDP form template on the server filesystem with this XML data
- retrieves the rendered interactive PDF form
- invokes Microsoft Internet Explorer and displays it

The click event on the second button:
- reads a saved interactive PDF form file from a Windows desktop client's local disk
- calls the ProcessFormSubmission method of Adobe LiveCycle ES Forms using SOAP over HTTP with the PDF file
- retrieves the extracted XML data
- invokes Microsoft Internet Explorer and displays it

The code has been tested on Windows Vista clients against:
- LiveCycle ES running on IBM WebSphere ND 6.1.0.9 on AIX 5.3/Oracle 10g
- LiveCycle ES running on JBoss 4.0.3SP1/Windows 2003 Server/SQL Server 2005

To make it work in your environment, you would need to change the values of the constants at the beginning and re-build the solution. The input document for the ProcessFormSubmission is actually the output PDF of the RenderPDFForm, saved to the local disk.

The solution was built using Visual Studio 2005. If you open it in Visual Studio 2008, an import will be required. However, the code has been tested to work in Visual Studio 2008.