FAQ - Java Client API

The FAQs provide some examples and code snippets for common tasks when a third-party application wants to interact with the frevvo server.

On this page:

In v9.1 and later frevvo "Applications" are known as "Projects," and "Themes" are known as "Styles." The API objects and methods still use the words 'application', 'app', and 'theme'.

How do I login and logout to and from a server?

See the Java code snippet below:

    FormsService fs = new FormsService("localhost", 8082);
    fs.login("myuserid", "mypassword");

    // interact with frevvo

    fs.logout();

Since there is some overhead associated with logging in and out, you need to keep the FormsService instance around for as long as you need to interact with frevvo before logging out.

How do I get the list of all projects for the current user?

    FormsService fs = ...;
    URL appFeedUrl = fs.getFeedURL(ApplicationFeed.class);
    ApplicationFeed appFeed = fs.getFeed(appFeedUrl, ApplicationFeed.class);
    for(ApplicationEntry appEntry: appFeed.getEntries()){
        System.out.println("Application Name: " + appEntry.getTitle().getPlainText());
    }

How do I get the list of all themes for the current user?

    FormsService fs = ...;
    URL themeFeedUrl = fs.getFeedURL(ThemeFeed.class);
    ThemeFeed themeFeed = fs.getFeed(themeFeedUrl, ThemeFeed.class);
    for(ThemeEntry themeEntry: themeFeed.getEntries()){
        System.out.println("Theme Name: " + themeEntry.getTitle().getPlainText());
    }

How do I get the list of all forms for the current user?

    FormsService fs = ...;
    URL ftFeedUrl = fs.getFeedURL(FormTypeFeed.class);
    FormTypeFeed ftFeed = fs.getFeed(ftFeedUrl, FormTypeFeed.class);
    for(FormTypeEntry ftEntry: ftFeed.getEntries()){
        System.out.println("FormType Name: " + ftEntry.getTitle().getPlainText());
    }

How do I get the list of all forms for a given project?

The code snippet below prints the name of all forms in the appEntry application:

    ApplicationEntry appEntry = ...;
    FormTypeFeed ftFeed = appEntry.getFormTypeFeed();
    for(FormTypeEntry ftEntry: ftFeed.getEntries()){
        System.out.println("Form Name: " + ftEntry.getTitle().getPlainText());
    }

How do I get the list of all schemas for the current user?

    FormsService fs = ...;
    URL schemaFeedUrl = fs.getFeedURL(SchemaFeed.class);
    SchemaFeed schemaFeed = fs.getFeed(schemaFeedUrl, SchemaFeed.class);
    for(SchemaEntry schemaEntry: schemaFeed.getEntries()){
        System.out.println("Schema Name: " + schemaEntry.getTitle().getPlainText());
    }

How do I get the list of all schemas for a given project?

The code snippet below prints the name of all schemas in the appEntry application:

    ApplicationEntry appEntry = ...;
    SchemaFeed schemaFeed = appEntry.getSchemaFeed();
    for(SchemaEntry schemaEntry: schemaFeed.getEntries()){
        System.out.println("Schema Name: " + schemaEntry.getTitle().getPlainText());
    }

How do I get the URL to a form so it can be embedded in my HTML pages?

First get a hold of the corresponding FormTypeEntry, then get the form URL as shown in the snipped below:

    FormTypeEntry ftEntry = ...;
    String formUrl = ftEntry.getFormTypeEmbedLink(null);

Then using the formUrl above you can generate the following script tag in your html page:

    <script type="text/javascript" src="{formUrl}"></script>

This will embed the form in your page inside an <iframe/>.

How do I get the URL to the form designer so it can be embedded in my HTML pages?

First get a hold of the corresponding FormTypeEntry, then get the form URL as shown in the snipped below:

    FormTypeEntry ftEntry = ...;
    String designerUrl = ftEntry.getFormTypeEditorEmbedLink(null);

Then using the designerUrl above you can generate the following script tag in your html page:

    <script type="text/javascript" src="{designerUrl}"></script>

This will embed the form designer in your page inside an <iframe/>.

How do I get the URL to the form submissions so it can be embedded in my HTML pages?

First get a hold of the corresponding FormTypeEntry, then get the form URL as shown in the snipped below:

    FormTypeEntry ftEntry = ...;
    String formSubmissionsUrl = ftEntry.getSubmissionsEmbedLink(null)

Then using the formSubmissionsUrl above you can generate the following script tag in your html page:

    <script type="text/javascript" src="{formSubmissionsUrl}"></script>

This will embed the submissions view in your page inside an <iframe/>.

How do I get a form entry based on a known id?

This is often needed when you need to relate a frevvo form with another concept of your project (e.g. your project has the concept of a report that has an associated frevvo form). In this case, you will store the form id somewhere and when needed fetch the form entry to embed it in your page, delete it, etc. Here is how you get the for a form entry (in fact any entry):

    FormTypeEntry ftEntry = ...;
    String formId = ftEntry.getId();

And here is how you can use that id to find the corresponding form entry:

    String formId = ...;
    FormsService fs = ...;
    URL formEntryUrl = fs.getEntryURL(FormTypeEntry.class, formId);
    FormTypeEntry ftEntry = fs.getEntry(formEntryUrl, FormTypeEntry.class);

How do I delete a form (or any other entry)?

By calling the delete method on the FormTypeEnty.

    FormTypeEntry ftEntry = ...;
    ftEntry.delete();

How do I create a new form?

First, you have to get a hold of the form feed from an existing project. See How do I get the list of all forms for a given project?

    FormsService fs = ...;
    ApplicationEntry appEntry = ...;
    FormTypeFeed ftFeed = appEntry.getFormTypeFeed();
    FormTypeEntry newEntry = ftFeed.createEntry();
    newEntry.setTitle(new PlainTextConstruct("MyForm"));
    newEntry.setSummary(new PlainTextConstruct("MyForm Description"));
    newEntry = ftFeed.insert(newEntry);

Inserting the original newEntry will not update it, but instead, a new entry will be returned.

How do I create a new form using an existing one as a template?

The only difference between creating a new form and creating a new one based on an existing form is that instead of using the entry created by calling 'ftFeed.createEntry()' you will be using an existing form entry. Find an existing form entry, update its name and description, and use that entry to insert it into a feed. Do not override the entry id otherwise, the insert will fail.

    FormsService fs = ...;
    ApplicationEntry appEntry = ...; // find app entry
    FormTypeEntry ftEntry = ...; // find template form entry 
    ftEntry.setTitle(new PlainTextConstruct("MyForm"));
    ftEntry.setSummary(new PlainTextConstruct("MyForm Description"));
    FormTypeFeed ftFeed = appEntry.getFormTypeFeed();
    FormTypeEntry newEntry = ftFeed.insert(ftEntry);

How do I copy a form?

Copying entails inserting an existing entry into a feed. The key difference between this case and a regular feed insert() is that the entry being inserted already has an id: this will trigger a copy.

    // get the FormTypeEntry you want to copy
    FormTypeEntry ftEntry = ...;
 
    // get the FormTypeFeed you will copy TO
    FormTypeFeed targetFeed = appEntry.FormTypeFeed;

    // Perform the copy
    FormTypeEntry copy = ftFeed.Insert(FormType);

You can only insert into a feed that has an explicit owner, which is guaranteed above by getting the FormTypeFeed from the ApplicationEntry as opposed to getting a FormTypeFeed containing forms for all projects.


How do I download an existing form?

It is also possible to download a form using the API similar to the way you can download one from the UI. Consider the following code snippet:

    FormsService fs = ...;
    ApplicationEntry appEntry = ...; // find app entry
    FormTypeEntry ftEntry = ...; // find template form entry 
    MediaContent mc = (MediaContent) ftEntry.getContent();
    MediaSource ms = getService().getMedia(mc);
    OutputStream formStream = new FileOutputStream("myform_form.zip");
    saveFormToDisk(ms.getInputStream(), formStream);

How do I upload a form into an existing project?

You can also upload a form that was previously downloaded using the following code snippet:

    FormsService fs = ...;
    ApplicationEntry appEntry = ...; // find app entry
    FormTypeFeed ftFeed = appEntry.getFormTypeFeed();
    InputStream formZipStream = new FileInputStream("myform_form.zip");
    MediaStreamSource formMediaSource = new     MediaStreamSource(formZipStream,"application/zip");
    FormTypeEntry ftEntry = ftFeed.insert(formMediaSource);

How do I use Self-signed Certificates with the API?

One approach is to modify the client code to accept self-signed certificates, but the recommended method is to use the standard Java mechanisms to trust a self-signed certificate; for example, to add the self-signed certificates to the JRE trusted keystore.

  • Use a key tool to create a key
  • Used installcert.java to install the certificate in a trusted keystore
  • Save the keystore in the ''jre-home\lib\security'' directory
  • Restart the server

How do I set a form's Deployment State?

FormTypeEntry ftEntry = setUpFormType(appEntry);
try {
System.out.println("Default State: " + ftEntry.getDeployState());
ftEntry.setDeployState(DeployState.PRODUCTION);
ftEntry = ftEntry.update();
ftEntry = ftEntry.getSelf();
assertEquals("Should be PRODUCTION state", ftEntry.getDeployState(), DeployState.PRODUCTION);

ftEntry.setDeployState(DeployState.DEVELOPMENT);
ftEntry = ftEntry.update();
ftEntry = ftEntry.getSelf();
assertEquals("Should be DEVELOPMENT state", ftEntry.getDeployState(), DeployState.DEVELOPMENT);

FormTypeFeed ftFeed = appEntry.getFormTypeFeed();
FormTypeEntry newEntry = ftFeed.createEntry();
newEntry.setTitle(new PlainTextConstruct("MyForm123"));
newEntry.setSummary(new PlainTextConstruct("MyForm123 Description"));
newEntry.setVisibility(Visibility.PUBLICTENANT);
newEntry.setDeployState(DeployState.PRODUCTION);
newEntry = ftFeed.insert(newEntry);
assertNotNull(newEntry.getSelf());
assertEquals("Should be PRODUCTION state", newEntry.getDeployState(), DeployState.PRODUCTION);
newEntry.delete();

How can I get the submissions for a form/workflow?

q.setStringCustomParameter("ownerId", "applicationID!userId");
q.setFilter("$formTypeId eq " + formTypeId");
SubmissionFeed submissionFeed = formsService.getFeed(q, SubmissionFeed.class);

The submissions feed will retrieve submissions in the submitted and saved states. Submissions in the pending, aborted or waiting states are not returned. Let's say you want to sort submissions that are saved versus those that are submitted. You can use the SubmissionEntry.getState() method. This will return the current state of a SubmissionEntry (SAVED and SUBMITTED). You can use this property to distinguish between your submissions.

CategoryFilter f = new CategoryFilter();
Category submitted = new Category(FormsService.FREVVO_STATE_SCHEME, FormsService.SCHEME_STATE_SUBMITTED);
f.addCategory(submitted);
q.addCategoryFilter(f);

What do I do if API submission access fails?

Ensure the form/workflow submissions you are trying to access has either the userid or Roles that the user is a member of in "Who can view submissions" ACL.

How do I get a form submission PDF when Save PDF is not enabled?

Using frevvo API, you can instantiate each form submission, get the PDF for that instance and then cancel the form instance. Note that the PDF will not show up in the form submission when using this approach as the instance is canceled.

Here is an example API script that will download PDFs for all form submissions to disc:

/ formTypeID of your form. You can get the formTypeId of a form by looking at its Share URL. For example, if your forms Raw URL is: http://localhost:8082/frevvo/web/tn/qa/user/fd/app/_S5QyQQ8GEeKoZPV3UpCRog/formtype/_W03sMA8GEeKoZPV3UpCRog?_method=post&embed=true&locale=, then the part of this URL between formtype/ and ?_method is your formTypeId.
String formTypeId = "_W03sMA8GEeKoZPV3UpCRog";  

// Get the Forms Service.
FormsService service = new FormsService("http", "localhost", 8082, null);
service.login("designer@tutorial", "designerpswd");

// Get Submission Feed
SubmissionQuery q = new SubmissionQuery(service.getFeedURL(SubmissionFeed.class));
q.setStringCustomParameter("ownerId", "applicationId!userId"); 
q.setFilter("$formTypeId eq " + formTypeId");
q.setOrderby("$updated");  
SubmissionFeed sFeed = service.getFeed(q, SubmissionFeed.class);

int counter = 1;
// Download PDF for each submission
for (SubmissionEntry contact : sFeed.getEntries()) {
       // re-instantiate the form from the submission
       URL fUrl = contact.createFormInstance(null, null);
       // Construct the URL which will generate the PDF
       String pdfUrl = fUrl.toString() + "&print=true&format=pdf";
       String filename = "E:\\myFormPDF" + counter + ".PDF";
       BufferedInputStream in = null;
       FileOutputStream fout = null;
       try
       {
             MediaSource source = service.getMedia(pdfUrl);
			 in = new BufferedInputStream(source.getInputStream());
             fout = new FileOutputStream(filename);

             byte data[] = new byte[1024];
             int count;
             while ((count = in.read(data, 0, 1024)) != -1)
             {
                    fout.write(data, 0, count);
             }
       }
       finally
       {
             if (in != null)
                    in.close();
             if (fout != null)
                    fout.close();
       }      
       counter ++;
       // Cancel the instance
       Helper.cancelInstance(service, fUrl);    
}

How do I batch upload users from the api?

Users csv upload through the Java data api

The users csv upload is available through the Java data api in frevvo v6.1.4+. Here is the code snippet:

InputStream userCsvData = // Obtain an input stream to your user csv file. 		
		FormsService service = // Obtain form service logged in as tenant admin user 		
		UserFeed userFeed = service.getFeed(
				service.getFeedURL(UserFeed.class),
				UserFeed.class);
		
		String notificationEmailAddress = // some email address 		
		userFeed.uploadUsersCsv(userCsvData, notificationEmailAddress); 
                // now check for the email with results

To get the users csv data from frevvo:

InputStream is = userFeed.getUsersCsv();

You can specify who receives an email reporting the upload status when it is done through the API. The email is sent to the "notificationEmailAddress" that is passed in the API. The email may say something like this if there are errors during the upload:

Validation occurred with errors. Users data NOT loaded. Refer to attached CSV data file for validation and/or loading result details.

The attached file, results.csv, will contain the details.

How do I use the Security Manager Built-In Admin?

LDAP, SAML, and SAML Azure Security Managers provide a built-in admin login directly to frevvo, which is helpful if your security manager logins should become inaccessible and you need to access frevvo.  This built-in admin is automatically enabled from the API when using SAML, but for LDAP it needs to be explicitly enabled by setting the custom property "backdoorLogin" to true in the loginAs call. This will allow the API to login in the same way a built-in admin can log in using /frevvo/web/admin/login.

service.loginAs("loginAsUser", "adminuser@tenant"), "????", true, null, null, null, null, Map.of("backdoorLogin", "true"));