Arrays
LittleHorse provides a native ARRAY variable type that gives you strongly-typed, ordered lists with per-element type enforcement.
Use ARRAY when you want compile-time and runtime guarantees that every element in your list conforms to a specific type. Use JSON_ARR when you need an untyped or heterogeneous list, or for backward compatibility with existing workflows.
Supported Element Types
An ARRAY can hold elements of any TypeDefinition:
- Primitives:
INT,DOUBLE,STR,BOOL,BYTES, etc... - Complex types:
STRUCT(backed by a registeredStructDef) - Nested arrays:
ARRAY(arrays of arrays)
Input Validation
The LittleHorse server validates array inputs at ingress (e.g., when running a workflow or returning from a task). If an element does not match the Array's declared type, the server rejects the request with INVALID_ARGUMENT.
In Practice
To use an ARRAY variable in LittleHorse:
- Declare an
ARRAYvariable in yourWfSpecusingdeclareArray(). - Produce and consume arrays in your task workers, marking them as distinct
ARRAYs instead ofJSON_ARRusing the@LHType(isLHArray = true)annotation. - Use mutation operations to manipulate array contents.
Declaring an ARRAY Variable
Use the declareArray method on WorkflowThread to create a typed array variable. You specify the element type as a class.
- Java
import io.littlehorse.sdk.wfsdk.WfRunVariable;
import io.littlehorse.sdk.wfsdk.WorkflowThread;
public void wfLogic(WorkflowThread wf) {
// Declare an array of Long elements
WfRunVariable longArray = wf.declareArray("my-numbers", Long.class);
// Declare an array of String elements
WfRunVariable stringArray = wf.declareArray("my-strings", String.class);
}
Task Workers with Native Arrays
Task workers can produce and consume native arrays using the @LHType(isLHArray = true) annotation. Without the annotation, Java arrays would default to JSON_ARR serialization. This is done for backwards compatibility purposes, since old clients automatically treated Java arrays as JSON arrays.
Producing an Array
Annotate the task method with @LHType(isLHArray = true) and return a Java array:
- Java
import io.littlehorse.sdk.worker.LHTaskMethod;
import io.littlehorse.sdk.worker.LHType;
public class ArrayWorker {
@LHTaskMethod("produce-array")
@LHType(isLHArray = true)
public Long[] produceArray() {
return new Long[] {1L, 2L, 3L};
}
}
Consuming an Array
Annotate a method parameter with @LHType(isLHArray = true) and accept a Java array:
- Java
import io.littlehorse.sdk.worker.LHTaskMethod;
import io.littlehorse.sdk.worker.LHType;
public class ArrayWorker {
@LHTaskMethod("consume-array")
public String consumeArray(@LHType(isLHArray = true) Long[] arr) {
return "Received " + arr.length + " elements";
}
}
Arrays in Struct Fields
For struct properties that are arrays, use the @LHStructField(isLHArray = true) annotation on the getter or field:
- Java
import io.littlehorse.sdk.worker.LHStructDef;
import io.littlehorse.sdk.worker.LHStructField;
@LHStructDef("shopping-cart")
public class ShoppingCart {
@LHStructField(isLHArray = true)
private Long[] itemIds;
public Long[] getItemIds() {
return itemIds;
}
public void setItemIds(Long[] itemIds) {
this.itemIds = itemIds;
}
}
Mutation Operations
The ARRAY type supports the following mutation operations:
| Operation | Description |
|---|---|
ASSIGN | Assign an array value to the variable |
EXTEND | Append a single element to the array (type-checked against the element type) |
REMOVE_IF_PRESENT | Remove all occurrences of a value from the array |
REMOVE_INDEX | Remove the element at a specific index |
- Java
import io.littlehorse.sdk.wfsdk.NodeOutput;
import io.littlehorse.sdk.wfsdk.WfRunVariable;
import io.littlehorse.sdk.wfsdk.WorkflowThread;
public void wfLogic(WorkflowThread wf) {
WfRunVariable arrVar = wf.declareArray("my-array", Long.class);
// Assign the result of a task to the array
NodeOutput produced = wf.execute("produce-array");
arrVar.assign(produced);
// Append a single element
arrVar.assign(arrVar.extend(4L));
// Remove all occurrences of a value
arrVar.assign(arrVar.removeIfPresent(2L));
// Remove the element at index 1
arrVar.assign(arrVar.removeIndex(1));
}
Accessing Array Elements
You can use index-based access to read individual elements from an ARRAY variable using the .get() method with a numeric index:
- Java
public void wfLogic(WorkflowThread wf) {
WfRunVariable arrVar = wf.declareArray("my-array", Long.class);
// Access the element at index 0
wf.execute("process-item", arrVar.get(0));
// Access the element at index 2
wf.execute("process-item", arrVar.get(2));
}
Conditionals with IN and NOT_IN
The doesContain and doesNotContain methods work with native ARRAY variables:
- Java
import io.littlehorse.sdk.wfsdk.WfRunVariable;
import io.littlehorse.sdk.wfsdk.WorkflowThread;
public void wfLogic(WorkflowThread wf) {
WfRunVariable arrVar = wf.declareArray("my-array", Long.class);
WfRunVariable valueToCheck = wf.declareInt("value-to-check");
wf.doIfElse(
arrVar.doesContain(valueToCheck),
ifBody -> {
ifBody.execute("handle-found", valueToCheck);
},
elseBody -> {
elseBody.execute("handle-not-found", valueToCheck);
}
);
}
Spawning Threads per Element
The spawnThreadForEach method works with native ARRAY variables, spawning one child thread per element in the array. Each child thread receives the corresponding element as input.
- Java
import io.littlehorse.sdk.wfsdk.SpawnedThreads;
import io.littlehorse.sdk.wfsdk.WfRunVariable;
import io.littlehorse.sdk.wfsdk.WorkflowThread;
public void wfLogic(WorkflowThread wf) {
WfRunVariable arrVar = wf.declareArray("my-array", Long.class);
SpawnedThreads threads = wf.spawnThreadForEach(
arrVar,
"process-element",
this::processElementThread,
null
);
wf.waitForThreads(threads);
}
public void processElementThread(WorkflowThread wf) {
WfRunVariable input = wf.declareInt("INPUT").required();
wf.execute("process-item", input);
}
Full Example
A complete working example is available in the LittleHorse examples repository.
Further Resources
- Variables Concepts — overview of all variable types in LittleHorse.
- Mutating Variables — guide to variable mutation operations.
- StructDefs and Structs — another complex type that can be used as an
ARRAYelement type. - Threads — learn about
spawnThreadForEachand other threading concepts. - Java Arrays Example — full working example on GitHub.