Jactl 1.3.0 fixes a few minor bugs and adds some language features. The main new feature is to support the ability to checkpoint script instance execution state and have it restored and resumed on another instance after a failure.


Native support for JSON encoding and decoding (#16)

Jactl can convert objects into JSON using the toJson() method:

def x = [a:1,b:[x:3,y:4],c:['a','b','c']]
x.toJson()         // {"a":1,"b":{"x":3,"y":4},"c":["a","b","c"]}

The corresponding fromJson() method on strings will convert back from JSON to simple objects:

def json = '{"a":1,"b":{"x":3,"y":4},"c":["a","b","c"]}'
json.fromJson()   // [a:1, b:[x:3, y:4], c:['a', 'b', 'c']] 

For user defined classes, Jactl will generate a toJson() method and a class static method fromJson():

class X { int i; String s }
X x = new X(i:3, s:'abc')
x.toJson()      // {"i":3,"s":"abc"}
x = X.fromJson('{"i":3,"s":"abc"}')

Native array support (#17)

Jactl now supports array types, including multidimensional arrays. Previously, lists were used in place of arrays but for performance sensitive code, arrays can now be used instead.

int[] someInts = [1,2,3,4]

The usual list methods (each(), filter(), map(), etc.) also apply to arrays:

String[] strArr = ['abc', 'xyz', 'x']
strArr.map{ it.size() }.sum()     // result is 7

List-specific versions of min(), max(), sum(), and avg() (#19)

This enhancement was just an optimisation to improve the performance of these methods when applied to simple lists.

Support checkpointing of execution state (#20)

This enhancement leveraged the existing ability suspends script execution and resume later when scripts perform blocking operations. Scripts can now perform a checkpoint() call whenever they want to checkpoint their current state. The application in which Jactl is embedded can then persist or repicate this state so that if a failure occurs the state can be restored and the script can continue running from where it left off.

See the Jactl Integration Guide for information on how to integrate this feature with your application.

The Jactl Language Guide for information about the checkpoint() function.

There is also a blog post that discusses a Proof of Concept project where checkpoint persistence and replication was implemented, along with tests showing the restoration and resumption of scripts that were running when failures occurred.

Substring and subList functions should support 0 as end index when start index is negative (#22)

This enhancement allows you to use negative indexes with the substring() and subList() functions that are interpreted as being relative to the end of the string/list:

'abcde'.substring(-2)      // result is 'de'
'abcde'.substring(-3,-1)   // result is 'cd'

[1,2,3,4].subList(-2,0)    // result is [3, 4]

New ‘??’ operator for existence test (#23)

A new ?? operator allows you to test for existence:

def x
?? x.a.b.c         // returns false rather than giving an error

Add byte and byte[] types to support binary data (#24)

Jactl now supports byte and byte[] data types to better support binary data. Jactl also supports appropriate conversions:

'abc' as byte[]    // result is [97, 98, 99]

Bug fixes

  • #18: Non-numeric operand error using ‘new’ immediately after newline
  • #21: Regex capture variable usage can sometimes lead to “No match found” error
  • #26: className() method on instances cannot be passed by value
  • #27: Base class field initialisers not being invoked when using named arg constructor
  • #30: JSON decoding is not initialising missing fields in base classes
  • #31: Inner class of base class should be visible to child class
  • #32: Null for string in regex match should return false

Known Issues

  • #34: NullPointerException instead of NullError if null used for list/array index or for field of a map