Using Freemarker (FTL) with ProntoForms

About

In ProntoForms, FreeMarker Templating Language is used to build text-based templates for any data destination that allows documents. Compose custom integration messages in the text-based format of your choice containing ProntoForms data.

 

About FreeMarker

FTL (for FreeMarker Template Language) is used to build templates.  Templates then use a data-model to create an output.  In ProntoForms, FreeMarker is used to collect specified data from submitted forms and input it into a document. Read here for more information about FreeMarker.

With FreeMarker you can:

  • Generate your own HTML, XML or JSON structure, or any other text-format that suits your needs
  • Generate just about any HTTP request body you require
  • Use loops, conditional sections
  • Create and change variables within a template
  • Use complex expressions:  string operations, calculations, arrays,  etc

Basics of FreeMarker

This is a very simple programming language, composed of the following:  

  • Text: Text that will be printed to the output as is.
  • Interpolation: Sections will be replaced with a value from the data-model in the output. Interpolations are delimited by ${ and }

See sample template below for an example that uses interpolation to display username, datarecord state, and form name.

Sample template:

Username: ${dataRecord.submitted.username}
DR state:  ${dataRecord.state}
Form name: ${dataRecord.form.name.defaultString}

Sample output:

Username: John Doe
DR state:  Completed
Form name:  Inventory
  • FTL tags: FTL tags are similar to HTML tags, but they are instructions to FreeMarker and will not be printed to the output.  Use FTL tags to call directives, which are instructions to FreeMarker. Read about directives here.

Sample template using directives:

<#list page.dataQuestions as dataQuestion>
<#if dataQuestion.answer??>             <#-- checks "if" dataQuestion.answer is missing or not -->
<${dataQuestion.question.formDataConfiguration.label.defaultString}>
${dataQuestion.answer.values[0].value}
</${dataQuestion.question.formDataConfiguration.label.defaultString}>
  </#if>
</#list>

Note that FreeMarker doesn't care about the nesting of XML  tags, only about the nesting of FTL tags. It just sees XML as flat text, it doesn't interpret it in any way.

  • Comments: Comments are similar to HTML comments, but they are delimited by <#-- and -->. Comments will be ignored by FreeMarker, and will not be written to the output.

[ top ]

 

ProntoForms Variables and Methods

Answers to questions are placed in a map variable named answers, with Question Label as the map key. 

dataRecord

This variable contains the raw data record data. The object structure is defined below.

- dataRecord
- - identifier
- - referenceNumber
- - state
- - dataPersisted
- - user
- - - identifier
- - - username
- - - firstName
- - - lastName
- - - email
- - - role
- - - locale
- - - preferredTimeZone
- - - phoneNumber
- - - fax
- - - companyName
- - formIteration
- - - iteration
- - - state
- - - initiationMethod
- - - dispatchDeclinable
- - - notes
- - - passthrough
- - - form
- - - - identifier
- - - - name.defaultString
- - - - description.defaultString
- - - - state
- - entryTimestamp
- - entryTimestampUtc
- - submitted
- - - userIdentifier
- - - username
- - - displayName
- - - actionTimestamp
- - dispatched
- - - userIdentifier
- - - username
- - - displayName
- - - actionTimestamp
- - dataView
- - - geoStamp
- - - pages
- - - - page
- - - - - identifier
- - - - - name.defaultString
- - - - dataQuestions
- - - - - question
- - - - - - identifier
- - - - - - questionText.defaultString
- - - - - - formDataConfiguration.label.defaultString
- - - - - answer
- - - - - - identifier
- - - - - - values
- - - - - - - identifier
- - - - - - - value

 

answers

This variable contains a map of question labels to answer objects. &nbspMost answers have a simple String value. The following have multiple properties.

Attachment
- filename
- contentType
- bytes (byte array)
Barcode
- barcodeType
- barcodeValue
Credit Card Transaction
- responseCode
- transactionId
- cardType
- redactedCardNumber
- amount
- timestamp
Geo Location
- coordinates
- - latitude
- - longitude
- - altitude
- timestamp
- geoSource
- address
- success
- errorMessage

 

drel( )

This method can execute DREL (Data Record Expression Language) on a data record and output the result as a string in the template. DREL expressions can be run using a custom drel() method (eg drel("%d")).

 

Example Templates using ProntoForms Variables

The following examples demonstrate the different ways you can access your data.

Using the dataRecord Variable

<?xml version="1.0"?>
<data>
	<#list dataRecord.dataView.pages as page>
		<#list page.dataQuestions as dataQuestion>
			<#if dataQuestion.answer??>
				<${dataQuestion.question.formDataConfiguration.label.defaultString}>
					${dataQuestion.answer.values[0].value}
				</${dataQuestion.question.formDataConfiguration.label.defaultString}>
			</#if>
		</#list>
	</#list>
</data>

Using the answers Variable

This example demonstrates a SOAP request.  A SOAP request will also require you to set the Content-Type request header to application/soap+xml; charset=utf-8

<?xml version="1.0"?>
<soap:Envelope
	xmlns:soap="http://www.w3.org/2001/12/soap-envelope"
	soap:encodingStyle="http://www.w3.org/2001/12/soap-encoding">

	<soap:Body xmlns:m="http://www.example.org/stock">
		<m:GetStockPrice>
			<m:StockName>${answers["stockname"][0]}</m:StockName>
		</m:GetStockPrice>
	</soap:Body>

</soap:Envelope>

 

Using the drel( ) Method

<createOrder>
	<entryTime>${drel("%d[yyyy-MM-dd'T'HH:mm:ss][UTC]")}</entryTime>
	<orderAmount>${drel("%a[amount]")}</orderAmount>
</createOrder>

[ top ]

 

Sending Response Codes to ProntoForms

It is important that your server indicates to the ProntoForms system whether a transaction was successful by sending an appropriate HTTP response code.  If all processing on your server was successful, send a 200 in the response.  The ProntoForms system will mark the transaction as complete, which will be visible in the portal user interface.  If there was a problem, send a non-200 response code (usually a 500) in the response code header.  This indicates to the ProntoForms system that it should retry sending the data to your server.  

Note that some SOAP-based systems tend to return 200 OK response codes even when an error has occurred, and provide information on the error only in the body of the response message.  In this scenario, ProntoForms will not detect that an error has occurred, and will not retry the transaction.

[ top ]

Was this article helpful?
0 out of 0 found this helpful
Have more questions? Submit a request

Comments

  • Avatar
    IT Support

    Is there some trick to getting this to work?

    I used the example above to see what it would produce... I created a simple FTL template with the following contents to one of my existing forms:

    <?xml version="1.0"?>

    <data>

    <#list dataRecord.dataView.pages as page>

    <#list page.dataQuestions as dataQuestion>

    <#if dataQuestion.answer??>

    <${dataQuestion.question.formDataConfiguration.label.defaultString}>

    ${dataQuestion.answer.values[0].value}

    </${dataQuestion.question.formDataConfiguration.label.defaultString}>

    </#if>

    </#list>

    </#list>

    </data>

    but it fails with:

    freemarker.core.InvalidReferenceException: Expression dataRecord.dataView is undefined on line 3, column 8 in body template for Document 'My Form' (231292080).

    I submitted a support request, which I got a suggestion which didn't work and now I am not getting a response!

    Anyone else get this working?

    Does it matter if my form is one page instead of multiple pages?

    I tried this (which was the suggestion that failed): <#list dataRecord.dataView.pages[0] as page>

    Maybe this page could have a complete working sample?