This documentation is for Live Forms 9.1. v9.1 is a Cloud Only release. Not for you? Earlier documentation is available too.
COVID-19 Response Info: At frevvo, our top priorities have always been employees and customers. We have taken several steps to promote the well-being of our people, to minimize services disruptions, and to help where we can. Visit our website for updates.
Getting Started with the Data API - Java Client Library Tutorial
So you've decided to use the Data Java client library to have a deeper integration between your application and
. 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 Tomcat bundle from LiveForms web site. The Tomcat bundle contains all the required Java Client jars.
In v9.1 and later 's "Applications" are known as "Projects." The API objects and methods still use the word Application.
On this page:
What are we going to build?
We are going to build a simple contacts project using and the Data API Java Client Library.
This project 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 '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 project into
- 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 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 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 project .zip (more details about this below).
You can download the command line binaries and the sources.
Assuming that you have an installation of 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:
java -cp com.frevvo.forms.cli-4.1.3.jar com.frevvo.forms.cli.Tutorial -s http://localhost:8082 -t tutorial -u admin -p {adminpwd}
If you are running this for the first time you should see:
Using embedded Contacts application ... Connecting to tenant demo at localhost:8080 ... Contacts application doesnt exist. Uploading ... Application uploaded!
And then the command prompt:
http://admin@localhost:8082/tutorial>
You are now logged into tenant tutorial as user admin connected to server http://admin@localhost:8082.
Enter the list command to list all the submissions for the Contact Form (the first time you should have none):
http://admin@localhost:8080/tutorial> list List all existing contacts... URL ! http://localhost:8080/frevvo/web/tn/tutorial/api/submissions?filter=%24formTypeId+eq+%27_pkMVwBH8EeCl2et9BuDRPg%27 # | ID | CREATED | UPDATED | KIND | STATE | PDF?
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 , create a project 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 Searchable Fields. Searchable fields can be used for quick searches when using the API.
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.
Here is how you would find a form by name:
public class Contacts { ... protected FormTypeEntry getContactForm2(String formTypeName) throws IOException, ServiceException { FormsService s = getService(); try { URL formsUrl = s.getFeedURL(FormTypeFeed.class); FormTypeFeed forms = s.getFeed(formsUrl, FormTypeFeed.class); for (FormTypeEntry form : forms.getEntries()) { if (formTypeName.equals(form.getTitle().getPlainText())) return form; } return null; } catch (ResourceNotFoundException e) { return null; } } ... }
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:
<feed xmlns="http://www.w3.org/2005/Atom" xml:base="http://localhost:8080" xml:lang="en"> <title><strong>Form Types<strong></title> <updated>2010-12-29T16:34:41.077-05:00</updated> <link rel="self" type="application/atom+xml" href="/frevvo/web/tn/tutorial/api/formtypes"/> <entry xmlns:fd="http://schemas.frevvo.com/fdata/2008" xml:lang="en"> <id>_pkMVwBH8EeCl2et9BuDRPg!_lJ8_ERH8EeCl2et9BuDRPg!admin</id> <title type="text">Contact Form</title> <summary type="text">Edit the form to change this description.</summary> <updated>2010-12-27T16:02:44.062</updated> <category scheme="http://schemas.frevvo.com/fdata/2008#kind" term="FORM"/> <link type="application/atom+xml" href="/frevvo/web/tn/tutorial/api/formtype/_pkMVwBH8EeCl2et9BuDRPg!_lJ8_ERH8EeCl2et9BuDRPg!admin"/>
Now that we know the id of our Contact Form, here is how you can find a form by id using the API:
public class Contacts { ... protected FormTypeEntry getContactForm(String formTypeId) throws IOException, ServiceException { FormsService s = getService(); try { URL url = s.getEntryURL(FormTypeEntry.class, formTypeId); return s.getEntry(url, FormTypeEntry.class); } catch (ResourceNotFoundException e) { return null; } } ... }
Note that we plan to make this a bit more straightforward in future releases.
Download/Upload the Contacts project
Now that we have already created the Contact Form, we will manually download it from the UI, by going to the projects page and clicking the download button, and then use the project.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 project (the same applies to forms, workflows, 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 , 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.
public class Contacts { ... private void commandLoop() throws IOException, ServiceException { // create the FormsService to hold the session with frevvo FormsService s = new FormsService(getProtocol(), getHost(), getPort(), null); try { // login to frevvo s.login(getUsername() + '@' + getTenant(), getPassword()); // save the service to be used in subsequent interactions this.service = s; // Auto-upload the contact application, if not already there if (getContactForm() == null) { uploadContactApplication(s); } // start the interactive shell ShellFactory.createConsoleShell(getPrompt(), null, this).commandLoop(); } finally { this.service = null; s.logout(); } } ... }
When this command-line program is terminating we make sure that we properly logout from . This ensures that
will release any unneeded resources and the user count will be decremented (licensing).
LoginAs
supports an additional way of logging into
using the Data API: the loginAs() method. This new method allows you to login to
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
using the same user that is logged into your project 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 . For instance:
... String tenantAdmin = getUsername() + '@' + getTenant(); String tenantAdminPwd = getPassword(); String username = getAsUsername(); FormsService s = new FormsService(getProtocol(), getHost(), getPort(), null); s.loginAs(username, tenantAdmin, tenantAdminPwd, true, null, null, null, null, null); ...
This will automatically create a new, non-designer user (i.e. will be able to participate in workflows but not create forms/workflows), if it doesnt yet exist. If you want 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:
... String tenantAdmin = getUsername() + '@' + getTenant(); String tenantAdminPwd = getPassword(); String username = getAsUsername(); List<String> roles = new ArrayList<String>(); roles.add("frevvo.Designer"); FormsService s = new FormsService(getProtocol(), getHost(), getPort(), null); s.loginAs(username, tenantAdmin, tenantAdminPwd, true, roles, null, null, null, null); ...
Upload Contact form
As described earlier, we have downloaded the Contacts 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
server, i.e. usually the first time you connect to a
/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 project.zip file.
public class Contacts { ... private void commandLoop() throws IOException, ServiceException { ... // Auto-upload the contact application, if not already there if (getContactForm() == null) { uploadContactApplication(s); } ... } ... private void uploadContactApplication(FormsService s) throws IOException, ServiceException { System.out.println("Contacts application doesnt exist. Uploading ... "); // oops the contacts app doesnt exist, let's upload it UserEntry user = ApiHelper.getUserEntry(s); ApplicationFeed apps = user.getApplicationFeed(); InputStream is = Contacts.class.getResourceAsStream(APP_RESOURCE); if (is == null) throw new IOException("Could not find contacts application file in classpath: " + APP_RESOURCE); try { ApiHelper.uploadNewApplication(s, apps, is); } finally { System.out.println("Contacts application uploaded!"); is.close(); } } ...
The ApiHelper class referenced above is a helper class containing code that is reusable across applications. Here are the two definitions that are relevant here:
public class ApiHelper { ... static public ApplicationEntry uploadNewApplication(FormsService service, ApplicationFeed feed, InputStream is) throws ServiceException, IOException { MediaStreamSource ms = new MediaStreamSource(is, "application/zip"); ApplicationEntry entry = feed.insert(ms); return entry; } ... public static UserEntry getUserEntry(FormsService service) throws IOException, ServiceException { // strip away the tenant from the user name if any String username = service.getUsername(); if (username.contains("@")) username = username.split("@")[0]; return getEntry(service, UserEntry.class, username); } ... }
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:
http://admin@localhost:8080/tutorial> view-xsd Viewing XML Schema for form Contact Form [rel=schema,type=application/xml; xmlns="http://www.frevvo.com/schemas/_pkMVwBH8EeCl2et9BuDRPg",href=http://localhost:8080/frevvo/web/tn/demo/user/demo/app/_lJ8_ERH8EeCl2et9BuDRPg/formtype/_pkMVwBH8EeCl2et9BuDRPg/schema?apikey=ddxut73apg%252FNhRxDMClyxldCETWBw6Sf3UV5zZo5hjobtt58kllmRXA9OroaCiWfSRqrm66ICIW5vpaMStoztA%253D%253D] ...
Here is how the view-xsd command is implemented using the API:
public class Contacts { ... @Command public String viewXsd() { try { FormTypeEntry contactForm = getContactForm(getContactFormId()); Link contactXsd = contactForm.getFormTypeSchemaLink(); if (contactXsd != null && contactXsd.getHref() != null) { Util.openURL(contactXsd.getHref()); } return "Viewing XML Schema for form " + ApiHelper.getName(contactForm) + " [rel=" + contactXsd.getRel() + ",type=" + contactXsd.getType() + ",href=" + contactXsd.getHref() + "] ...\n"; } catch (Exception e) { return "Could not view XML Schema for form: " + e.getMessage(); } } }
List existing Contacts
Now that we are logged in to and have the Contact project uploaded, let's list the current contacts we have in the submission's repository. This is done by entering the list command:
http://admin@localhost:8080/tutorial> list List all existing contacts... URL ! http://localhost:8080/frevvo/web/tn/tutorial/api/submissions?filter=%24formTypeId+eq+%27_pkMVwBH8EeCl2et9BuDRPg%27 # | ID | CREATED | UPDATED | KIND | STATE | PDF?
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.
Here is the list command implementation:
public class Contacts { ... public String list() { try { FormTypeEntry contactForm = getContactForm(); SubmissionFeed contacts = getContacts(contactForm.getSubmissionFeedLink()); return ApiHelper.print(contacts); } catch (Exception e) { return "Could not get the contacts: " + e.getMessage(); } } ... protected FormTypeEntry getContactForm() throws IOException, ServiceException { FormsService s = getService(); try { URL url = s.getEntryURL(FormTypeEntry.class, getContactFormId()); return s.getEntry(url, FormTypeEntry.class); } catch (ResourceNotFoundException e) { return null; } } ... private SubmissionFeed getContacts(Link contactsLink) throws IOException, ServiceException { URL contactsUrl = new URL(contactsLink.getHref()); SubmissionQuery q = new SubmissionQuery(contactsUrl); if (getFilter() != null) q.setFilter(getFilter()); if (getOrderBy() != null) q.setOrderby(getOrderBy()); if( startIndex != null && startIndex >= 1 ) q.setStartIndex(startIndex); if( maxResults != null && maxResults >= 0 ) q.setMaxResults(maxResults); if( updatedMax != null ) q.setUpdatedMax(updatedMax); if( updatedMin != null ) q.setUpdatedMin(updatedMin); return getService().getFeed(q, SubmissionFeed.class); } ...
Create a new Contact
At this point we have no contacts in the repository. Let's go ahead and add one. This can be done by entering the create command in the command prompt:
http://admin@localhost:8080/tutorial> create Opening add contact form... http://admin@localhost:8080/tutorial>
At this point you should see your system browser pop up and render the Customer Form:
Enter the contact details and press Submit. If you now enter the list command at the command-line prompt, you should see the newly added contact:
http://admin@localhost:8080/tutorial> list List all existing contacts... URL ! http://localhost:8080/frevvo/web/tn/tutorial/api/submissions?filter=%24formTypeId+eq+%27_pkMVwBH8EeCl2et9BuDRPg%27 # | ID | CREATED | UPDATED | KIND | STATE | PDF? | LASTNAME | FIRSTNAME | ZIPCODE | CITY | STREET 1 | _rvicgBQsEeCkOMNSkDQKVw | 2010-12-30T10:51:36.000 | 2010-12-30T10:51:36.000 | FORM | SUBMITTED | true | Doe | John | 70778 | Atlanta
The following code snippet show how the create command was implemented:
public class Contacts { ... public String create() { try { FormTypeEntry contactForm = getContactForm(); Link contactFormLink = contactForm.getFormTypePopupLink(null); Util.openURL(contactFormLink.getHref()); return "Opening add contact form..."; } catch (Exception e) { return "Could not create get the contacts: " + e.getMessage(); } } ... }
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).
http://admin@localhost:8080/tutorial> list List all existi