Skip to content

P6 Core 6.10.23

Release date: Friday, June 19, 2026

Documentation can be found here.

TL;DR

This release hardens the Groovy script engine under load — fixing an intermittent crash when several executions of the same script run at once, removing a bottleneck that made cold scripts time out during traffic bursts, and caching repeated content-check lookups so document validation stays fast. On the data side, sorting now works correctly in Tables and Table Records, XML serialisation no longer corrupts CDATA payloads, and an empty application-config default no longer crashes the invoice routing flow. Operators also get a new option to let an application install proceed (with a warning) when its declared version range doesn’t match the running platform, instead of failing outright. Rounding things out are clearer content-check labels and messages for invoicing, plus an important DSL documentation clarification about how scripts share their pipeline.

Scripting & Groovy DSL

  • Resolved several stability and performance problems in the Groovy script engine that surfaced under concurrent load. An intermittent crash when reading a script’s results while another execution of the same script was running is gone (the result is now returned as an isolated snapshot). A “compile storm” — where a burst of traffic against a not-yet-cached script forced all compilations to queue behind a single lock and exceed the job timeout — has been removed by letting cold scripts compile in parallel. The engine is also more resilient to cache entries being evicted mid-lookup. (STN-28320)
  • Clarified the DSL reference for p6.script.call: the called script shares the caller’s pipeline by reference, and the map it returns is the caller’s own pipeline — not a copy. The documentation now spells out that changes made by the called script are visible (and permanent) in the caller, and points to p6.script.start when isolation is needed. This prevents a recurring class of scripting bugs. (STN-27798)

    // ❌ Common mistake: the returned map IS p6.pipeline — putting its
    // entries back is a no-op, and the callee may have removed keys you needed.
    def result = p6.script.call('MyApp.GenerateInvoice')
    result.each { k, v -> p6.pipeline.put(k, v) } // does nothing useful
    
    // ✅ If you need the caller's pipeline left untouched, snapshot and restore:
    def snapshot = new LinkedHashMap(p6.pipeline)
    try {
        p6.script.call('MyApp.GenerateInvoice')
    } finally {
        p6.pipeline.clear()
        p6.pipeline.putAll(snapshot)
    }
    
    // ✅ Or run the sub-script in a fresh context with p6.script.start.
    def jobId = p6.script.start('MyApp.GenerateInvoice')
    

Application Installation

  • Added an option to let an application installation continue with a visible warning — instead of failing — when the application’s minimum/maximum supported platform version doesn’t match the running version. This lets operators install applications in controlled scenarios without re-packaging them, while still flagging the mismatch in the job log. (STN-27810)

Tables

  • Fixed sorting in Tables and Table Records. The sortAscending option was previously ignored, so filtered results always came back in the same order; sort direction is now respected. (STN-28147)

XML & Configuration Handling

  • Fixed XML serialisation so that <![CDATA[…]]> sections are preserved. Previously, serialising a document containing CDATA would unwrap it and escape its contents, silently altering the payload for any downstream consumer (XSLT outputs, view-config transformers, XML DSL bodies, etc.). Round-tripping now keeps documents byte-for-byte intact. (STN-27796)
  • Fixed a crash when reading an application configuration whose default value is an empty object but whose stored value is not. This previously threw a null-pointer error — notably breaking the connector-based invoice routing flow — and now correctly returns the configured value. (STN-28048)

    // Config "TargetConnectorByTargetSystem": default = {}, value = {"DemoMock":"ABS"}
    // Before: this threw a NullPointerException while merging the empty default.
    // Now: the merge returns the stored overrides unchanged.
    def routing = p6.appconfig.getAsJson('TargetConnectorByTargetSystem')
    p6.log.debug 'ABS routing for DemoMock: ' + routing.DemoMock // => "ABS"
    

Content Checks & Invoicing

  • Corrected several content-check field labels and the associated error-message formatting so they display the right text during invoice validation. (STN-28047, STN-27799)