So you've decided to use the Live Forms Data Java client library to have a deeper integration between your application and Live Forms. Our aim with this tutorial is to quickly get you started in using the Java client library by guiding you through the implementation of a simple application.

We will first help you configure your development environment and then jump straight into the Java code. This tutorial assumes that you have already installed a recent version of the Java JDK (5.0 or 6.0) and that you have already downloaded Live Forms Tomcat bundle from LiveForms web site. The Tomcat bundle contains all the required Java Client jars.

On this page:

What are we going to build?

We are going to build a simple contacts application using Live Forms and the Data API Java Client Library.

This application will be composed on a single contact form that will be used to add new contacts, view and edit existing ones. For the sake of simplicity and the focus on the APIs, the application will be provided as an interactive command-line executable and contacts will be stored in Live Forms's internal submission repository. The command-line executable will automatically open forms using the system's browser (e.g. when editing, viewing or creating a new contact).

This tutorial will help demonstrate how to:

Login/logout and session management

Upload a sample application into Live Forms

List the existing submissions for a sample form

Create a new submission

View a submission

Edit a submission

Query submissions & pagination

Delete a submission

Installing the Client Library and Dependencies

The Live Forms Java Client Library has the following dependencies:

com.frevvo.forms.java-4.1.1.jar

com.google.gdata.media-1.40.3.jar

com.google.gdata.core-1.40.3.jar

com.google.gdata.client.meta-1.40.3.jar

com.google.gdata.client-1.40.3.jar

commons-codec-1.2.jar

commons-httpclient-3.1.jar

commons-logging-1.0.4.jar

google-collections-1.0.jar

mail-1.4.1.jar

activation-1.1.jar

json-1.0.0.jar

For your convenience all these required jars can be found in the Tomcat bundle in the /frevvo/ext/client folder. Make sure you include all of them in your classpath when adding them to your application's classpath.

The actual jar versions may be different depending on the version of Live Forms being used.

Contacts application

We have created a simple Contacts command-line application and we'll use it to demonstrate some of the API features. The idea is so that the user will start the command-line Contacts application and issue interactive commands to perform the main functions mentioned earlier: create new contact, edit or view a contact, delete contact, list contacts, etc. At times, the Contacts application will need to render a form and will then launch a browser window so the user can see or fill in the Contact form.

The Contacts application described here is comprised of a single .jar file that contains all the required dependencies including the Contacts Live Forms application .zip (more details about this below).

Assuming that you have an installation of Live Forms up and running (e.g. http://localhost:8082) and a user account (e.g. admin) in a given tenant (e.g. tutorial), you can run the command-line app here:

For the curious among you, you can see the list of commands available by entering the ?list command. We will cover each one of them in the following sections.

But first, let's go over the Contact form and how to get it's API ID...

The Contact Form

Once you are logged in to Live Forms, create an application named Contacts and then create a Contact form with a set of contact controls such as first name, last name, address, zip code, etc.

If you have run the command line .jar as instructed above you will already have this and won't need to create them.

In the Contact form you just created, make sure that you also check the Save PDF in the form properties pane. This will make sure that a PDF snapshot will be automatically saved when the form is submitted (this will be used to show how to get the PDF snapshot using the API).

Also make sure that your configure Sey Fields. Searchable fields can be used for quick searches when using the API.

Click here for information about Searchable Fields

Searchable fields configured for a form or flow are the fields that may be used to filter submissions in the submissions view. By default, all your data is saved as an XML document. This is the most efficient way to store/access your data both in terms of speed as well as storage. However, if you prefer to view your data via the submissions user interface, you can choose which fields are available to the user as search criteria in addition to the XML data.

Considerations when deciding which types of fields to configure are listed below.

Searchable fields are indexed for easy search of form/flow Submissions. They can also be used when searching Tasks on a user's Task List. You will see columns for the controls in your form/flow designated as Searchable fields in the Submissions table. This is helpful when trying to locate a particular submission from a long list. Searchable Fields are downloaded into the Submissions Download to a CSV file along with the submission default columns.

Cloud customers can configure up to 20 Searchable Fields.

In-house customers can change change the default value by adding the frevvo.max.searchable.fields configuration parameter to the <frevvo-home>\tomcat\conf\Catalina\localhost\frevvo.xml file.

Saved fields do affect performance as they are independently stored in addition to XML data. This can significantly reduce performance, especially for large forms and require additional storage in the repository. Saved fields are not rendered in the submission table and cannot be used as search criteria for submissions. The only reason to configure Saved fields is if you want to use the Export to Excel feature which is available on the Legacy Submissions view

The Export of submissions to Excel feature has been replaced by the Download to CSV. If you have not used the Export to Excel feature in the past, we recommend that you become familiar with the Download to CSV.

You can still use the Export to Excel feature by accessing it from the Submissions Legacy view. However, the Legacy Submissions view and the Export to Excel may be removed in a future release.

Designers should carefully consider which fields to designate as Searchable fields. The selection of the correct fields as search criteria can be very helpful with submission and Task List searches.

Clicking on the Click to setup Searchable fields link displays the setup wizard. This link is on the form's properties as shown below. If you have navigated away from the form's properties and instead see a control properties panel, just click anywhere on the toolbarto return to the form's properties.

Searchable Field wizard

The wizard displays the fields from your form/flow. Only controls that are considered form data will be listed. For Example, the link, signature, image, upload, trigger, section, PageBreak, Message, Form Viewer and video controls will not show up in the Searchable field lists as there is no value to save or query against. Also, group controls (tabs, panels, repeats) will not show up on the list of Available Fields.

We do not recommend using columns from Tables or Repeats as Searchable fields. The data will be hard to interpret since there can be multiple data values for the same field.

Do not select a Textarea field as a Searchable Field if the amount of text stored in the field is greater than 32k.

Searching submissions using a Repeat control from schema is not supported.

If the value of a field contains the < sign, the data in the Submissions Table will be incomplete. For example, if the value = a<b only the "a" will show in the Submission Table.

Move the the fields listed in the Available Fields tab that you want to use as search criteria to the Searchable Fields tab. You can change the order of the fields when you move them into the Searchable Fields area. The order of the form fields will be reflected in the Submission Table and the export to a csv file once existing submissions are resubmitted or a new submission is created.

There are two ways to select/unselect or reorder Searchable fields :

Drag and Drop - You can drag the fields from the Available Fields list and drop them into the Searchable Fields list if you re using Firefox, Chrome or Safari browsers. Items may be dragged between lists and within the Searchable Fields list. Items may be dropped between existing items and before the top-most item and below the bottom item. Only a single item may be dragged. Currently, the drag and drop function will not work in the Internet Explorer browsers. This issue will be addressed in a future release.

Center arrow buttons

The > right arrow moves the selected field from the Available Fields list to the bottom of the Searchable Fields list.

The < left arrow moves the selected field from the Saved Fields list to the bottom of the Available Fields list.

The >> double right arrows move all the form fields in the Available Fields list to the Searchable Fields list.

The << double left arrow moves all the form fields in the Saved Fields list to the Available Fields list.

Click Finish to save. Selecting the X in the upper right corner cancels any changes. Remember to save your changes when you exit out of the designer.

Controls are listed in the Available and Searchable Lists using control labels. If you change the label of a control in your form that was previously added to the Searchable Fields list the control will remain in the list reflecting the new label. In a Live Forms flow, the label can be different for controls with the same name in different activities. Controls are listed using the control name. If the name changes, it will unset the Searchable field. The newly renamed control will now show on the Available list and the designer must move it to the Searchable List again.

Note the first five fields in the Searchable Fields list are marked with double asterisks. These 5 searchable fields will be the key fields for the submission in the legacy view.

Maximum Number of Searchable Fields

Cloud customers can configure up to 20 Searchable fields. In-house customers can change the maximum number of Searchable Fields with a configuration parameter.

When an attempt is made to add more than the maximum configured number of Searchable fields, an error message ("Maximum Number of Searchable Fields Exceeded!"). displays on the lower right of the screen and will disappear after a short time. Any fields in excess of the maximum configured number will not be allowed.

Adding/Removing Searchable Fields

If you make changes to Searchable Fields in a form or flow, the changes will take affect for new submissions. If you want to update existing submissions to reflect your changes, run the Refresh Searchable Fields process.

Searchable fields can be refreshed for:

All forms/flows in all tenants (in-house) or a specific tenant (Cloud or in-house) - must be initiated by the frevvo Cloud or customer in-house superuser administrator. Cloud customers must contact frevvo to request a refresh of Searchable fields for your entire tenant.

frevvo will run the Refresh process during a time when your users are NOT using Live Forms.

If refreshing production forms or flows, run the job during a time period when the forms or flows are not being used.

Saved Fields tab

You will see a Saved Fields tab in addition to the Searchable Fields tab. This tab displays only when the Legacy Submissions view is configured as it is in the Live Forms cloud. The only reason to configure Saved Fields for a form/flow is if you want to use the Export to Excel which is only available in the Legacy Submissions view. Remember, Saved Fields are stored in the database when the form/flow is completed. This can significantly reduce performance, especially for large forms and require additional storage in the repository.

The Export of submissions to Excel feature has been replaced by the Download to CSV. If you have not used the Export to Excel feature in the past, we recommend that you become familiar with the Download to CSV.

You can still use the Export to Excel feature by accessing it from the Submissions Legacy view. However, the Legacy Submissions view and the Export to Excel may be removed in a future release.

In-house customers can choose to hide the Legacy Submissions view with a configuration parameter. If the Legacy submission view is not visible, the Saved Fields tab is not displayed in the Form/Flow designers and the Export to Excel feature is not available.

In case you need to search across all controls in the form (not only the ones specified as Searchable fields) just keep in mind that searches across non-key fields are slower for larger data sets.

Now save your form.

Get the Contact Form API ID

When using the Data API, you can find this Contact Form you just created either by getting a list of existing forms and finding the right one by name. This approach works but is a bit error prone in case another form could be created with the same name. In addition, it is also slower than getting the form directly by id.

A better approach is to use the FormTypeEntry ID for the form in question. In integrations where forms can be dynamically created using the API, this is just a matter of saving the id found in FormTypeEntry.getId() and then using it to find the form (code shown below).

For this tutorial, though, the Contacts form is known before hand and so we can get it's id manually. This can be done in two ways:

Manually constructing the entry's ID, i.e. {formtypeid}!{applicationId}!{ownerId} - When designing the form in question you can get all these three ids by looking at the url in the browser's address bar. It will look like something: .../frevvo/web/tn/tutorial/user/admin/app_lJ8_ERH8EeCl2et9BuDRPg/form/_pkMVwBH8EeCl2et9BuDRPg?typeId=_pkMVwBH8EeCl2et9BuDRPg&locale= (in bold, respectively, ownerId, applicationId and formtypeId). The final ID would be _pkMVwBH8EeCl2et9BuDRPg!_lJ8_ERH8EeCl2et9BuDRPg!admin.

Searching for the entry id in the forms feed. Go to the browser and access the formtype feed .../frevvo/web/tn/tutorial/user/admin api/formtypes. View the page source and search for the entry named "Contact Form". Copy the value of the <id/> element. You should see something like the following feed:

Note that we plan to make this a bit more straightforward in future releases.

Download/Upload the Contacts application

Now that we have already created the Contact Form, we will manually download it from the UI, by going to the applications page and clicking the download button, and then use the application .zip to automatically upload it to aForms install the first time our command line app is executed. This simplifies the deployment since you only need to download command-line .jar and run it, i.e. no other configuration steps, and it also shows how you can use the API to upload an application (the same applies to forms, flows, schemas and themes) programmatically.

I will not get into the details of how this .zip file will be packaged into the command-line .jar, since all the sources for this tutorial are available to be downloaded.

Authentication & Session Management

When interacting with Live Forms, the Contacts application will first need to establish a session using the Data API. This is done by using the com.frevvo.forms.client.FormsService class and by providing proper credentials to authenticate.

The commandLoop() method in the Contacts class below shows how this is done in the Contacts application. Note that the FormsService instance is state-full and the same instance needs to be used throughout the session (this is specially the case when rendering form urls in the browser since an API key is automatically appended and bound to the FormsService session - as soon as you logout() the API key becomes invalid). In the case of this command-line application the session spans the life-time of the executable, but in the case of a web application the FormsService instance is usually stored in the HTTP session that the user has with the application.

When this command-line program is terminating we make sure that we properly logout from Live Forms. This ensures that Live Forms will release any unneeded resources and the user count will be decremented (licensing).

LoginAs

Live Forms supports an additional way of logging into Live Forms using the Data API: the loginAs() method. This new method allows you to login to Live Forms as any of the existing tenant users provided you can pass in the tenant's admin user and password. This is quite convenient when you want login to Live Forms using the same user that is logged into your application without having to know their password.

The following snippet shows how to login as a tenant user:

The loginAs(String, String, String) usage above assumes that you are logging in as a user that was previously created in the specific tenant.

When your tenant was configured with the DelegatingSecurityManager, you can use the overloaded loginAs() method to automatically create virtual users in Live Forms. For instance:

This will automatically create a new, non-designer user (i.e. will be able to participate in flows but not create forms/flows), if it doesnt yet exist. If you want Live Forms to auto create a new virtual user that is also a designer you need to pass in the frevvo.Designer role when calling loginAs(). For instance:

Upload Contact form

As described earlier, we have downloaded the Live FormsContacts application .zip file and embedded it in the command-line .jar. This .zip file is available from the JVM Classpath and will be automatically uploaded if it cannot be found in the Live Formsserver, i.e. usually the first time you connect to a Live Forms/tenant install.

The following code snippet shows how we do this. We first try to find the Contact Form form by ID (as we described earlier) and if we cant find it, we will upload the application .zip file.

Download the form's XML Schema

Now that you have the Contacts application, you can also get the XML Schema for the Contact form using the API. You can try this out in our sample command line program by entering the view-xsd command:

If this is the first time you are running this sample app, then you will have no contacts in the repository.

The list command is implemented as follows. We find the Contact Form by id as we have been doing already and then get its related SubmissionFeed. When getting submissions related to a specific FormTypeEntry, you are in essence querying for submissions filtered by the current form id (i.e. filter=$formTypeId eq '_pkMVwBH8EeCl2et9BuDRPg'). For your convenience we have included a link in the FormTypeEntry automatically retrieves the submissions for this entry.

As you can see here, we get a hold of the FormType Popup link, which contains a url to an html page with the form embedded, and open it in the browser.

Note also the null parameter in getFormTypePopupLink(null) call: it is here that we can customize the form link by passing in a map of name and value contants for things like:

Rendering the form in readonly or print view

Overriding the form action associate with the form (e.g. to redirect the page to one of your app's page when the form is submitted

Initializing specific controls in the form using _data

...

See Url Parameters for more details on these parameters and note that the FormTypeEntry class has a variety of constants that can be of help (FormTypeEntry.EMBED_* and FormTypeEntry.FORMTYPE_*)

View an existing Contact

Now that we have at least one contact in our simple contacts database, lets view one of them. This is done by entering the view command followed by the index of the contact you want to view (the 1st column in the list command).

Here we get a hold of the SubmissionFeed for the Contact Form, as described earlier in the Contacts.getContacts(Link) method, find the entry identified by it's index and then render the Contact Form in read-only mode. Note a couple of things here:

We are now using a slightly different link: instead of using the FormTypeEntry.getFormTypePopupLink(Map) we are using the FormTypeEntry.getFormTypeLink(Map). The former embeds the form in an outer HTML page using a script tag and the latter renders the form directly as html (this is the same raw url found in the Share Dialog).

We are setting the FormTypeEntry.FORMTYPE_READONLY_PARAMETER to TRUE.

View a PDF snapshot of the Contact form

Since we have configured the Contact Form to save a PDF snapshot (see the designer screenshot above) on submission, we have also implemented a variation of the view command that renders the PDF snapshot instead of the readonly form. Using our sample command line program you can view the PDF by entering the view-pdf command with the index of a given entry:

This code simply gets the snapshot link from the feed entry and open's it in the browser. Here is the actual link we look for in the submission entry (remember that underlying the Java Client library we are exchanging Atom xml document over HTTP):

The document links (contacts.getDocumentLinks(String contentType)) returns all the documents associated with the submission and this includes file upload attachments in addition to the XML document(s) (note that there could be more than one XML document in cases XML Schema elements are added to the form.

This sample opens the XML in the browser, but you could also download the XML document by using the FormService.getMedia(String) method:

Editing an External Contact

Note that editing a contact here is nothing more than rendering a form and initializing it with the XML document(s) stored in Live Forms's submission repository. Since this repository is embedded in Live Forms, we have automated some of the work of instantiating a form and initializing it from an XML document(s). However, what if you are integrating Live Forms with your own application and have your own database of contacts? Not a problem. You can use the API to instantiate the form passing in a list of XML documents.

Let's assume that I have an XML document that conforms to the Contact Form located somewhere in my hard-disk:

You can create a new contact using this XML document as a starting point by entering the create-from-xml command at the prompt followed by the full path to the xml file:

Here, we have used another method found in the FormTypeEntry class called createFormInstance(Map<String,Object> urlParams, List<MediaSource> documents). When using this method, we are eagerly instantiating the form from the API, as opposed to using one of the factory urls that instantiates the form only when rendered in the browser) with any number of XML document(s) as MediaSources.

At this point we have taken an external XML document, which in our case was just an xml file sitting somewhere but could have been anywhere or even dynamically generated by your application, and instantiate a form with it. Here the user is in control and can modify the contact data using the form interface. When the Contact Form is submitted, you can also get a hold of the updated XML document to update your own contact database. This can be done by configuring a Doc Action in the form designer or even finding the submission entry for the submission and downloading the XML document.

Delete an existing Contact

How do we remove a contact? This is also quite simple. We do that by entering the delete command at the prompt with the contact index seen when listing the contacts.

Querying our simple Contacts repository

By default the list command we have been using so far is a simple query that returns the first page of all Contact Form submissions. There are situations where you may want to customize this query to return a subset of the results. Although we dont provide an extensive query API there are a few things you can do.

The code for the following subsection is very simple and can be found here:

Now, let's go over some of the query parameters at your disposal in more detail.

Start Index

By default, submission queries will return entries starting from the first one. You can explicitly set a different start-index when paginating through a large set of entries (in SubmissionQuery.setStartIndex(Integer). In our sample program, you can do that by entering the start-index command at the prompt. Note that there is a bug in version 4.1.2 and earlier where start-index is interpreted as a 0-based index. This is fixed in version 4.1.3. So for instance:

no start-index set: return entries starting from the first one

'start-index set to 0: you will get entries starting from the first one

start-index set to 1: you will get entries starting from the first one

In the above interaction, we have listed all the contact submissions (2 in total) and then set the max-results to 1 forcing the query to return at most 1 entry. Note that even if you don't specify a maximum number of results, they server will, by default, force a maximum defined in the frevvo.submission.maxresults context parameter:

<context-param>
<param-name>frevvo.submission.maxresults</param-name>
<param-value>20</param-value>
<description>Limit the maximum number of submissions that can be queried</description>
</context-param>

Order by

One thing you can do is order the results by a certain criteria:

$author - The id of the user that submitted the form/flow

$name - The name of the form/flow

$updated - the last time the submission was updated

$revision - This is zero the first time you submit and is incremented everytime you edit the submission and submit it again

$formTypeId - The form/flow that generated this submissions (not so useful here)

$key{N}Value - The key value for key 1, 2, 3, 4 or 5 (remember that you can select controls from your forms to be keys in your submission).

{control.name} - If you configured your form to save the control values, you can then use the control value to order the submissions (use key fields in most cases and saved fields as a last resort)

You can also specify whether you want to use ascending (asc) or descending (desc) ordering.

For instance, let's order the list of contacts (we have 2 of them so far) based on when they were last udpated. Consider the following contacts:

Updated max/min

You can also filter submissions based on a date range using the updated-max and updated-min query parameters (SubmissionQuery.setUpdatedMax(DateTime) and SubmissionQuery.setUpdatedMin(DateTime)). These two parameters will filter submissions based on the last updated date (the updated date changes every time you save or submit a form/flow). So, back to your sample program, you can set the updated-min parameter as follows:

We have set the updated-min query parameter to 2010-12-30T19:16:24.000, which is 1 second after the contact #1 was submitted. As you can see, listing the submissions now show only the contact #2 which was submitted after that.

You can also set the updated-max query parameter to something like 2010-12-30T19:49:03.000, which is 1 second before the contact #2 was submitted:

Filtering

You can also do some basic filtering based on control values using the filter query parameter (SubmissionQuery.setFilter(String...)). This query parameter takes the following syntax: <field> eq '<value> (at this point we only support the equality operator eq). Here <field> can be any of the following:

$author - The id of the user that submitted the form/flow

$name - The name of the form/flow

$updated - the last time the submission was updated

$revision - This is zero the first time you submit and is incremented everytime you edit the submission and submit it again

$formTypeId - The form/flow that generated this submissions (not so useful)

$key{N} - The key value for key 1, 2, 3, 4 or 5 (remember that you can select controls from your forms to be keys in your submission).

{control.name} - If you configured your form to save the control values, you can then use the control value to order the submissions (use key fields in most cases and saved fields as a last resort)

For instance, considering that we have mapped key1, key2, key3, key4 and key5 to LastName, FirstName, ZipCode, City and Street, respectively (see form screenshot above), we could query for all contacts with key1 (i.e. LastName) equals to 'Doe' by entering the filter "$key1 eq 'Doe" command:

There is a performance penalty when saving and querying control by name so prefer key fields instead and use saved fields as a last resort.

You can also set more than one filter at the same time that are combined using the and semantic. For instance, filtering by LastName equal to Smarts AND FirstName equal to Dave, i.e. filter "LastName eq 'Smarts'" "FirstName eq 'Dave" command, you get (not that I edited the John Doe contact and changed the first name to Dave):

Paginating

Listing the submissions for the Contacts' form will return only the first 20 entries (this can be configured using the context parameter ''frevvo.submission.maxresults found in WEB-INF/web.xml) and so you will need to paginate through the SubmissionFeed 20 entries at a time. This can be done by using a simple pattern as you can see in the com.frevvo.forms.cli.ApiHelper.print(SubmissionFeed) found in the Tutorial sources.

Pagination is only supported in the SubmissionFeed at this point and by default the feed will contain at most 20 entries. This can be configured per server using the frevvo.submission.maxresults context parameter found in the WEB-INF/web.xml.

What's next?

This very simple application shows how to interact with a static Contact form using the Data API and the browser. Except for when querying the contact submissions, most of the other steps could probably have been implemented by just copying the right form url, adding the correct parameters (readonly, etc) and embedding it directly inside your own web application.

We have used the API here anyway to get you comfortable with using it. However, the power of the API becomes more obvious when providing a more dynamic integration where you want to enable your users to create the forms themselves. One example of such integration is our Confluence plugin: you install the plugin on Confluence and you can create any number of forms, flows in addition to a few other things. In this plugin we are allowing the user to create new forms all seamlessly integrated into Atlassian's Confluence.