Skip to main content

Version: 21.05

Delivery Function

Delivery Functions are used to deliver user-entered form data when a transaction is submitted. This form data includes the submitted form XML and the PDF receipt document, and may also include user uploaded file attachments. Note that delivery functions can also be used to deliver data from user-abandoned transactions if so configured.

Function API

class DeliveryFunction {
DeliveryFuncResult invoke(FuncParam param) {
// Add delivery code ...
return new DeliveryFuncResultBuilder()
.setStatusCompleted()
.build();
}
}

Function Parameter

The invoke method takes a single parameter: a FuncParam object which provides the set of inputs for the function's execution.

Delivery Function Processing

Delivery Functions have special execution facilities provided by Journey Manager to ensure they can be re-run if errors occur. Before a delivery function is run, it is registered with the transaction and its execution is tracked. If the function completes successfully its invocation status will be marked as 'Completed'. However, if a function fails its invocation status will be marked as 'Error'. This transaction delivery function can then be retried automatically by the background Transaction Processor job.

Delivery Functions can be invoked when a form is submitted by configuring them to run on the "User Submit" form trigger. This facility enables Straight-Through Processing (STP) or real-time delivery. If a Delivery Function fails when the user submits the form due to a back-end error or some schedule maintenance then the function can be re-run automatically by the Transaction Processor job in the next few minutes.

Note that when configuring delivery functions to run on the user thread, they should complete relatively quickly so they do not impact the user experience. A reasonable maximum period of time for delivery is around 10-30 seconds; longer than this, the user may be confused by the application not responding. When making remote HTTP calls, ensure short connection timeouts are set, so the function does not block for long periods of time on these calls. The default executionTimeout configuration for Delivery Functions is 30 seconds; after this period of time, the execution of the function will be aborted.

Delivery functions can also be configured to run in background delivery mode only by configuring the "Background Delivery" form trigger.

Note that when a Delivery Function is executing when the user submits a form, the PDF receipt document will not be available yet. Generally, PDF receipts are generated using a background process and, generally, these take a couple of minutes to generate after a form has been submitted. If you need both real-time delivery for STP and the delivery of the PDF receipt to another system, configure two separate Delivery Functions: one to be executed on the "User Submit" trigger, and another configured to execute on the "Background Delivery" trigger.

If a delivery function determines that it can't complete at this point in time, it should return a DeliveryFuncResult result with the delivery status of 'In Progress'. This delivery function will be executed again when the configure delay period has been reached.

The DeliveryFuncResult can be used to specify the period (in minutes) before the function is retried, and can also specify the maximum number of Error retry attempts.

When all of a transactions delivery functions have completed successfully, the Transaction is finished and its PII data will be configured to be purged at a future time. The default PII data retention settings is seven days; this provides some time to enable re-delivery of transaction PII data if a downstream processing error has occurred.

Error Handling

If a Delivery Function throws an exception, it will be caught and the transaction delivery function will be marked as being in an 'Error' state. When delivery functions are executed in the background by the Transaction Processor, they are executed in their own database transaction and any changes they make in this transaction will be rolled back. However, when delivery functions are executed by the user submitting a form, they will execute in the user's database transaction, and any changes they make will be committed to the database.

We recommend developers use try ... catch blocks in their Delivery Function Groovy code to control their error handling behavior and return a DeliveryFuncResult object specifying the 'Error' status and what the function retry semantics should be.

The Delivery Function can be configured with the maxDeliveryAttempts service parameter to specify the automatic retry attempts, and also the retryDelayMins to specify when the function should be retried again. Note that the maxDeliveryAttempts configuration parameter applies to transaction delivery functions in an 'Error' and 'In Progress' state. Once the maximum number of attempts has been reached, the system will not continue to retry the function.

Function Template

A Groovy script function template follows.

import com.avoka.tm.func.*
import com.avoka.tm.util.*
import com.avoka.tm.vo.*
class DeliveryFunction {
// Injected at runtime
public Logger logger
/*
* Perform Delivery Function call.
*
* returns: DeliveryFuncResult
*/
DeliveryFuncResult invoke(FuncParam param) {
// TODO: add delivery code
return new DeliveryFuncResultBuilder()
.setStatusCompleted()
.build();
}
}

Unit Test Template

A Groovy script unit test template follows.

import com.avoka.tm.func.*
import static com.avoka.tm.func.FuncParam.*
import com.avoka.tm.svc.*
import com.avoka.tm.test.*
import com.avoka.tm.util.*
import com.avoka.tm.vo.*
import org.junit.*
class UnitTest extends AbstractJUnitTest {
// Injected at runtime
public static Logger logger
/*
* Perform service unit test
*
* throws exception if unit test fails
*/
@Test
void testFunction() throws Exception {
String xmlData = testParams['Test XML Data']
XmlDoc xmlDoc = new XmlDoc(xmlData)
Txn txn = new MockVoBuilder().createTxnDeliveryReadyWithXml(xmlData)
FuncParam funcParam = new FuncParam(TRIGGER_BACKGROUND_DELIVERY, xmlDoc.document, [:], null, svcDef, txn, null)
DeliveryFuncResult result = (DeliveryFuncResult) new ServiceInvoker(svcDef)
.invoke("funcParam", funcParam)
logger.info result
assert result != null
}
}