Skip to content

Martini Workflows Repeat Node

Overview

The Workflow Repeat Node enables iterative execution within Martini workflows, similar to while and for loops in programming languages. It processes arrays, cursors, or conditional expressions by executing connected workflow nodes for each iteration, making it essential for data transformation, batch operations, and repetitive processing tasks.

What You Will Learn

By the end of this guide, you'll understand how to:

  • Add and configure Repeat Nodes in the Workflow Designer
  • Set up array-based iterations for data processing and transformation
  • Implement condition-based loops for dynamic execution control
  • Connect workflow nodes to iteration logic using each and then edges
  • Configure break conditions and index tracking for loop management

When To Use This

Use the Workflow Repeat Node when you need to:

  • Iterate through arrays and perform operations on each element
  • Process input and output cursors for batch read and write operations
  • Transform data collections from one array format to another
  • Execute conditional loops that repeat while a condition remains true

Prerequisites

Adding Repeat Nodes to Workflows

The Repeat Node provides iteration capabilities for processing arrays and implementing loops in your workflows.

Getting Started with Workflow Repeat Nodes

Add a Repeat Node to begin iterating through data in your workflow:

  1. Navigate to your Martini Package and open your workflow.
  2. Click the Add Node button in the toolbar.
  3. Select Repeat from the available node types.
  4. Drag the Repeat Node to your desired position in the workflow.

Expected result: The Repeat Node appears in your workflow, displaying each and then edge handles () for configuring iteration logic.

Configuring Workflow Repeat Node Settings

Configure the Repeat Node to define iteration behavior and data processing rules.

  1. Click the expand icon on your Repeat Node to open the Repeat Panel.
  2. Repeat On: Select your iteration approach:

    • Array: Iterate through array elements (similar to for-each loops)
    • Condition: Execute while a condition remains true (similar to while loops)

Expected Result: Configuration options update based on your selected iteration type.

Array-Based Iteration Configuration

Configure the node to process arrays and cursors systematically:

💡 Tip: Ensure that array properties have been declared in your workflow properties before attempting to select them in the Input Array and Output Array options.

  1. Input Array: Click the three-dots icon next to the Input Array input to select an existing workflow array property to iterate through.
  2. Output Array: (Optional) Click the three-dots icon next to the Input Array to select an existing workflow array property to store transformed results.
  3. Index Property Name: Use default $repeatIndex or specify a custom variable name for tracking position. This property can then be used in the break condition to create a condition that breaks when a certain iteration position is reached (e.g., $repeatIndex >= 10 to stop after 10 iterations).
  4. Break Condition: Enter a conditional expression to terminate iteration early when needed.

    Click the on the top right of the Repeat Panel to select your preferred script language for your Break Condition (see Supported Languages).

Expected result: The Repeat Node is configured to process your specified array with defined transformation rules.

Condition-Based Iteration Configuration

Set up conditional loops that execute while specified criteria remain true:

💡 Tip: Ensure that array properties have been declared in your workflow properties before attempting to select them in the Output Array option.

  1. Condition: Enter the expression that determines when to continue iteration.

    Click the on the top right of the Repeat Panel to select your preferred script language for your Condition (see Supported Languages).

  2. Output Array: (Optional) Specify an array to collect results from each iteration.

  3. Index Property Name: Define the variable name for tracking iteration count (default: $repeatIndex). This property can be used in the condition to limit iterations based on position (e.g., $repeatIndex < 50 to stop after 50 iterations).

Expected result: The Repeat Node will execute connected logic repeatedly until the condition evaluates to false.

Supported Languages

Martini supports multiple scripting languages for conditions and expressions:

  • Groovy (default) - Full Java compatibility with simplified syntax
  • JavaScript - Modern ECMAScript support for web-familiar developers
  • Python - Available when Python runtime is installed
  • Batch - For system command execution and file operations

Click the three-dots icon in the Repeat Panel header to select your preferred scripting language.

Workflow Repeat Node Key Terms

Term Definition
Input Array The source array that the Repeat Node iterates through
Output Array The destination array where transformed or processed results are stored
Each Edge Connection point that executes for every iteration of the loop
Then Edge Connection point that executes after all iterations complete
Condition Expression that can terminate iteration early based on specified criteria
Index Property Variable tracking the current position in the iteration (default: $repeatIndex)

Connecting Workflow Nodes to Repeat Logic

The Repeat Node provides two edge handles () for organizing iteration workflow:

Establishing Repeat Node Connections

Connect your workflow logic to the appropriate execution phases:

  1. Each Edge: Drag from the each handle to connect nodes that execute during every iteration.
  2. Then Edge: Drag from the then handle to connect nodes that execute after all iterations complete.

Expected result: Your workflow nodes are properly sequenced for iterative processing and workflow continuation after iteration completion.

Understanding How Repeat Node Works

The Repeat Node provides sophisticated iteration mechanics that handle data access, collection, and indexing automatically. Understanding these internal processes helps you build more effective workflows and troubleshoot iteration issues.

Accessing Current Element Record in Each Iteration

During each iteration, the Repeat Node automatically makes the current element available to all connected nodes:

Current Element Availability in each iteration:

  • The Input Array property becomes available as a non-array property to each node connected to the each edge
  • This includes Map Nodes, Script Nodes, Invoke Function Nodes, and expressions
  • The current element is also accessible in break conditions for conditional termination
  • Each iteration updates this property with the next array element

Example with Actual Data:

If your input array is customerOrders containing this data:

1
2
3
4
5
customerOrders = [
  { "order_id": "ORD-001", "customer_name": "John Smith", "amount": 299.99, "items": 3 },
  { "order_id": "ORD-002", "customer_name": "Jane Doe", "amount": 150.50, "items": 2 },
  { "order_id": "ORD-003", "customer_name": "Bob Wilson", "amount": 75.25, "items": 1 }
]

During each iteration, the customerOrders property (now a single object, not an array) will contain the current element. For example, in the first iteration it will contain:

1
2
3
4
5
6
customerOrders = {
  "order_id": "ORD-001",
  "customer_name": "John Smith", 
  "amount": 299.99,
  "items": 3
}

You can then access individual fields like customerOrders.order_id, customerOrders.customer_name, customerOrders.amount in your Map Nodes, Script Nodes, or expressions.

Understanding Output Array Population

The Repeat Node provides a mechanism to collect results from each iteration:

Output Array Mechanism:

  • The Output Array property becomes available as a non-array property to each node connected to the each edge
  • This includes Map Nodes, Script Nodes, Invoke Function Nodes, expressions, and repeat conditions
  • Any value assigned to this property during an iteration gets automatically appended to the output array
  • The append operation occurs at the end of each iteration, preserving the order of processing

Example with Actual Data:

Continuing with the customerOrders example from above, if your output array is processedOrders:

During each iteration:

  • You have the current element: the customerOrders object (with the current order data)
  • The processedOrders becomes available as a singular object (not an array) that you can populate
  • You append/assign the current element data to this singular processedOrders object:
1
2
3
4
5
6
7
8
// You assign to the singular processedOrders object:
processedOrders = {
  "order_id": "ORD-001",
  "customer_name": "John Smith",
  "total_with_tax": 329.99,
  "status": "processed", 
  "processing_date": "2025-01-15"
}

Mapping your current element to the singular processedOrders object tells Martini to append this object to the real processedOrders array at the end of the iteration.

After all iterations complete, your final processedOrders array will contain:

1
2
3
4
5
processedOrders = [
  { "order_id": "ORD-001", "customer_name": "John Smith", "total_with_tax": 329.99, "status": "processed", "processing_date": "2025-01-15" },
  { "order_id": "ORD-002", "customer_name": "Jane Doe", "total_with_tax": 165.55, "status": "processed", "processing_date": "2025-01-15" },
  { "order_id": "ORD-003", "customer_name": "Bob Wilson", "total_with_tax": 82.77, "status": "processed", "processing_date": "2025-01-15" }
]

Key Point: During each iteration, you work with a singular processedOrders object, assign your processed data to it, and Martini automatically appends that object to the actual processedOrders array.

Index Property Usage and Nested Repeats

The Index Property serves multiple purposes, especially important for complex iteration scenarios:

Primary Uses:

  • Tracking iteration position for logging, debugging, and conditional logic
  • Implementing pagination or chunked processing strategies
  • Managing nested repeat operations with distinct tracking

Nested Repeat Scenarios:

When using multiple Repeat Nodes within each other, customize index property names to avoid conflicts:

  • Outer Repeat: Set Index Property Name to outerRepeatIndex
  • Inner Repeat: Set Index Property Name to innerRepeatIndex
  • Access both indices in inner loop logic for complex processing patterns

Example Use Cases:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
// Break condition using custom index names
outerRepeatIndex >= 10 && innerRepeatIndex >= 5

// Logging with multiple indices  
log.info("Processing item ${outerRepeatIndex}.${innerRepeatIndex}")

// Conditional processing based on position
if (outerRepeatIndex % 2 == 0) {
    // Process even-numbered outer iterations differently
}

Repeat Node Execution Overview

The Repeat Node orchestrates execution flow through distinct phases:

Initialization Phase:

  • Evaluates input array or initial condition
  • Sets up index tracking and iteration variables
  • Prepares output array if specified

Iteration Phase:

  • For each array element or while condition is true:
  • Updates index and current element variables
  • Executes all nodes connected to the each edge
  • Evaluates break condition (if specified)
  • Processes results into output array (if configured)

Completion Phase:

  • Executes nodes connected to the then edge
  • Finalizes output array with all processed results

This systematic approach ensures reliable data processing and proper resource management during complex iterations.

Workflow Repeat Node Benefits and Use Cases

Data Transformation Efficiency: Repeat Nodes streamline array processing by automatically handling iteration mechanics, letting you focus on transformation logic rather than loop management. This reduces development time and minimizes iteration-related errors.

Batch Processing Optimization: When working with large datasets or outputs from the Workflow Databas eNode, Repeat Nodes provide controlled batch processing.

Troubleshooting Workflow Repeat Node Issues

Problem Detection Cause Fix Affected Versions
Infinite loop execution Workflow never completes, high CPU usage Missing or incorrect break condition Add proper break condition or verify condition logic All versions
Array index out of bounds Runtime error during iteration Index property used beyond array length Check array bounds in break conditions v2.2+
Output array not populating Empty results despite successful iteration Output array not properly configured Verify output array mapping in each iteration v2.2+
Break condition not working Loop continues past expected termination Syntax error in condition expression Validate condition syntax in selected scripting language All versions

Working with Cursors in Repeat Nodes

The Repeat Node can efficiently process cursors returned from various workflow nodes, enabling you to iterate through large datasets without loading everything into memory at once. This approach is essential for handling streaming data, paginated results, and resource-intensive operations.

💡 Note: For specific information on using batch operations and cursors with Database Nodes, see Working with Batch Operations and Cursors in the Database Node guide.

What Are Cursors in Workflows

Cursors are iterator objects that provide sequential access to data collections. Unlike arrays that load all data into memory simultaneously, cursors fetch data incrementally as you iterate through them. This makes cursors ideal for:

  • Processing large datasets that exceed available memory
  • Streaming data operations where data arrives continuously
  • Paginated results from external APIs or services
  • Resource-efficient operations that minimize memory usage

Understanding Input vs Output Cursors in Martini Designer

In Martini Designer, cursor terminology follows the data flow direction:

  • Input Cursors: Used for reading data (receiving/inputting data into your workflow)

    • Examples: inputCursor, getInputCursorFromFile
    • Purpose: Iterate and read through data retrieved from databases, files, or services
  • Output Cursors: Used for writing data (outputting data from your workflow)

    • Examples: outputCursor, json.openJsonOutputCursor
    • Purpose: Stream and write data to databases, files, or external systems

Configuring Repeat Nodes with Cursors

Set up cursor-based iteration to process streaming data efficiently:

Cursor Read Operations for ETL Extract Phase

Cursor read operations retrieve data from various sources and return them as a cursor for efficient iteration through large datasets. This represents the Extract phase of ETL (Extract, Transform, Load) processes where you pull data from source systems.

Real-World ETL Example: Processing Customer Orders

Business scenario: Your ETL workflow needs to extract all pending customer orders from a source system, transform their status, and load them into a target system.

Sample data:

1
2
3
4
5
6
// Orders cursor data
[
  { "order_id": "ORD-001", "customer": "John Smith", "amount": 299.99, "status": "pending" },
  { "order_id": "ORD-002", "customer": "Jane Doe", "amount": 150.50, "status": "pending" },
  { "order_id": "ORD-003", "customer": "Bob Wilson", "amount": 75.25, "status": "pending" }
]

  • Expected workflow input: Orders cursor from source system
  • Expected workflow output: Array of processed order records
Setting Up Cursor Read Processing for ETL Extract

Step 1: Prepare Your Cursor Source

  1. Create or obtain a cursor from one of these sources:

    • Database Node: Configure for batch read operations that return inputCursor from source systems
    • Invoke Function Node: Get a cursor from functions like Json.getInputCursorFromFile to read from JSON files
    • Workflow Input: Accept a cursor as a workflow parameter
    • Previous Node Output: Use cursor from previous workflow nodes

💡 Tip: When using Invoke Function Nodes for cursors, open the Function view and search for "cursor" to see all available cursor functions and choose the one suited for your needs.

  1. Map cursor to workflow property:

    • Open the Data Mapper Panel on your cursor source node
    • In the Output Panel, find the cursor property (e.g., inputCursor)
    • Drag the cursor to empty space to create a new workflow property (e.g., ordersCursor)
    • Or drag to an existing Array property in your workflow

Step 2: Configure the Repeat Node for Cursor Reading

  1. Add a Repeat Node after your cursor source node and connect them with an edge

  2. Open Repeat Node configuration:

    • Click the expand icon on your Repeat Node
    • Set Repeat On to "Array"
  3. Configure cursor processing:

    • Input Array: Select the workflow property containing your cursor (e.g., ordersCursor)
    • Output Array: (Optional) Select or create an array property to collect processed results (e.g., processedOrders)
    • Index Property Name: Use default $repeatIndex or specify custom name for position tracking
    • Break Condition: (Optional) Add conditions to terminate iteration early

Step 3: Process Each Cursor Element

  1. Connect processing logic to the each edge:

    • Add workflow nodes (Map Node, Invoke Function Node, etc.) to the each edge
    • These nodes execute for every cursor element
  2. Access current element data:

    • Each iteration automatically provides the current cursor element
    • Access element properties like order_id, customer, amount, status
    • Use $repeatIndex to track current position if needed
  3. Handle element processing (Transform phase):

Step 4: Handle Read Completion

  1. Connect completion logic to the then edge:

    • Add nodes that execute after all cursor elements are processed
    • Examples: final data aggregation, cleanup operations, result validation
  2. Access final results:

    • If using Output Array, access the complete processed dataset
    • Use iteration statistics for reporting or logging
    • Handle any accumulated errors or warnings

Expected result: Your workflow efficiently processes cursor data without memory overload, handling each element individually while maintaining overall performance.

Cursor Write Operations for ETL Load Phase

Cursor write operations allow you to process transformed data and write results to various destinations using cursors for efficient batch operations. This represents the Load phase of ETL processes where you write processed data to target systems.

Real-World Example: Bulk Customer Data Export to JSON

Business scenario: Export processed customer data to a JSON file after applying business rules and transformations.

Sample input data:

1
2
3
4
5
[
  { "customer_id": "CUST-001", "name": "John Smith", "region": "North", "tier": "Premium" },
  { "customer_id": "CUST-002", "name": "Jane Doe", "region": "South", "tier": "Standard" },
  { "customer_id": "CUST-003", "name": "Bob Wilson", "region": "East", "tier": "Premium" }
]

Expected result: All customer records processed and written to JSON file with success confirmation.

Setting Up Cursor Write Processing

Step 1: Prepare Your Cursor Source

  1. Create or obtain a cursor from one of these sources:

    • Database Node: Configure for batch write operations that return outputCursor
    • Invoke Function Node: Use functions like json.openJsonOutputCursor for JSON file writing
    • Previous Node Output: Use cursor from previous workflow nodes

💡 Tip: When using Invoke Function Nodes for cursors, open the Function tab and search for "cursor" to see all available cursor functions and choose the one suited for your needs.

  1. Map cursor to workflow property:

    • Open the Data Mapper Panel on your cursor source node
    • In the Output Panel, find the cursor property (e.g., outputCursor)
    • Drag the cursor to empty space to create a new workflow property (e.g., writeCursor)
    • Or drag to an existing Array property in your workflow

Step 2: Configure the Repeat Node for Cursor Writing

  1. Add a Repeat Node after your cursor source node and connect them with an edge

  2. Open Repeat Node configuration:

    • Click the expand icon on your Repeat Node
    • Set Repeat On to "Array"
  3. Configure cursor processing:

    • Input Array: Select the workflow property containing your cursor (e.g., writeCursor)
    • Output Array: (Optional) Select or create an array property to collect write results (e.g., writeResults)
    • Index Property Name: Use default $repeatIndex or specify custom name for position tracking
    • Break Condition: (Optional) Add conditions to terminate iteration early

Step 3: Process Each Cursor Element

  1. Connect processing logic to the each edge:

  2. Access current element data:

    • Each iteration automatically provides the current cursor element
    • Access element properties like customer_id, name, region, tier
    • Use $repeatIndex to track current position if needed
  3. Handle element processing (Transform phase):

Step 4: Handle Write Completion

  1. Connect completion logic to the then edge:

    • Add nodes that execute after all cursor elements are processed
    • Examples: success logging, error handling, notification sending
  2. Access final results:

    • If using Output Array, access the complete write results dataset
    • Use iteration statistics for reporting or logging
    • Handle any accumulated errors or warnings

Expected result: Your ETL workflow efficiently processes the complete Extract-Transform-Load pipeline using cursor-based operations, ensuring data integrity and providing comprehensive job status reporting.

Cursor Processing Best Practices

Memory Management: Configure appropriate batch sizes and break conditions to prevent memory overflow when processing large cursors. Use the index property to implement pagination or chunking strategies.

Error Handling: Include proper error handling within your iteration logic, as cursor errors can occur during network operations, database disconnections, or resource constraints.

Resource Cleanup: Cursors are automatically closed when iteration completes, but consider implementing break conditions for long-running operations to ensure timely resource release.

This ensures proper resource management when your workflow continues executing other operations after cursor processing completes.

Helpful Resources