#975·JsonPath

concurrency issue / race condition

Author: DarkvaterCreated Dec 21, 2023Updated May 13, 2026
LabelsBUG

Hi,

I've been investigating strange behaviour in wiremock (see https://github.com/wiremock/wiremock/issues/706#issuecomment-1862732727) and over the course of several days narrowed the issue down to a race condition in json-path. While I am still trying to pin down the exact culprit please find my findings below. Maybe someone with intimate knowledge of the library can see immediately what is wrong which would save me a lot of time.

  • version used: json-path 2.8.0 (but json-path 2.7.0 exhibits the same behaviour)
  • issue: JsonPath.read(<<json>>, "concat($.keys())") returns the keys from a json called in a different thread

log and explanation

  • I have annotated certain classes with logging.
  • the log format is [<thread-id> - <class-instance-hash>] <class-name>::<method> ... parameters of interest]
  • I have simplified the log here a bit to give the same simple name to all objects that are the same. So everywhere you see <<BODY>> it means the same JSON payload; everywhere you see <<CONFIG>> it is the same object instance.
  • you can see from the log there is a recursive call here to evaluate $.keys and then concat()
  • somewhere after correctly evaluating $.keys to "transactionId-ZFOr/PRIIPS" the result of EvaluationContext::addResult on concat() is suddenly "transactionId-ZFOr/MIFID" which is another call. You can see this between the section highlighted in -----
  • EVALUATIONCONTEXTIMPL::addResult-1 is on calling addResult method
  • EVALUATIONCONTEXTIMPL::addResult-2 is after adding valueResult in addResult
  • EVALUATIONCONTEXTIMPL::addResult-3 is after adding pathResult in addResult

notes

  • I'm adding some more logging to check evaluation context's valueResult and indexes there, but each run takes a while as it really only happens occasionally, and even less so with the extra logging added
bash
[qtp1615908941-218 - <<JSON_PATH_1>>]          JSONPATH::read jsonObject: <<BODY>>, configuration: <<CONFIG>>, jsonProvider: <<JSONPROVIDER>>

[qtp1615908941-218 - <<COMPILED_PATH_1>>]      COMPILEDPATH::evaluate-1.0 document: <<BODY>>, rootDocument: <<BODY>>, configuration: <<CONFIG>>
[qtp1615908941-218 - <<COMPILED_PATH_1>>]      COMPILEDPATH::evaluate-2.0 path: $.concat(...), document: <<BODY>>, rootDocument: <<BODY>>, configuration: <<CONFIG>>, jsonProvider: <<JSONPROVIDER>>
[qtp1615908941-218 - <<COMPILED_PATH_1>>]      COMPILEDPATH::evaluate-2.1 ctx: <<EVALUATIONCTX>>, path: $.concat(...), configuration: <<CONFIG>>, jsonProvider: <<JSONPROVIDER>>
[qtp1615908941-218 - <<COMPILED_PATH_2>>]      COMPILEDPATH::evaluate-1.0 document: <<BODY>>, rootDocument: <<BODY>>, configuration: <<CONFIG>>
[qtp1615908941-218 - <<COMPILED_PATH_2>>]      COMPILEDPATH::evaluate-2.0 path: $.keys(), document: <<BODY>>, rootDocument: <<BODY>>, configuration: <<CONFIG>>, jsonProvider: <<JSONPROVIDER>>
[qtp1615908941-218 - <<COMPILED_PATH_2>>]      COMPILEDPATH::evaluate-2.1 ctx: <<EVALUATIONCTX_2>>, path: $.keys(), configuration: <<CONFIG>>, jsonProvider: <<JSONPROVIDER>>
[qtp1615908941-218 - <<EVALUATION_CONTEXT_1>>] EVALUATIONCONTEXTIMPL::addResult-1 path: $.keys, model: [transactionId-ZFOr/PRIIPS], configuration: <<CONFIG>>, jsonProvider: <<JSONPROVIDER>>
[qtp1615908941-218 - <<EVALUATION_CONTEXT_1>>] EVALUATIONCONTEXTIMPL::addResult-2 valueResult: [[transactionId-ZFOr/PRIIPS]], resultIndex: 0, configuration: <<CONFIG>>, jsonProvider: <<JSONPROVIDER>>
[qtp1615908941-218 - <<EVALUATION_CONTEXT_1>>] EVALUATIONCONTEXTIMPL::addResult-3 valueResult: [[transactionId-ZFOr/PRIIPS]], resultIndex: 0, configuration: <<CONFIG>>, jsonProvider: <<JSONPROVIDER>>
[qtp1615908941-218 - <<COMPILED_PATH_2>>]      COMPILEDPATH::evaluate-2.2 ctx: <<EVALUATIONCTX_2>>, path: $.keys(), configuration: <<CONFIG>>, jsonProvider: <<JSONPROVIDER>>
[qtp1615908941-218 - <<COMPILED_PATH_2>>]      COMPILEDPATH::evaluate-2.4 ctx: <<EVALUATIONCTX_2>>, path: $.keys(), configuration: <<CONFIG>>, jsonProvider: <<JSONPROVIDER>>
[qtp1615908941-218 - <<COMPILED_PATH_2>>]      COMPILEDPATH::evaluate-1.1 result: <<EVALUATIONCTX_2>>, document: <<BODY>>, rootDocument: <<BODY>>, configuration: <<CONFIG>>
[qtp1615908941-218 - <<EVALUATION_CONTEXT_1>>] EVALUATIONCONTEXTIMPL::getValue-1.1 value: [transactionId-ZFOr/PRIIPS], unwrap: true
[qtp1615908941-218 - <<EVALUATION_CONTEXT_1>>] EVALUATIONCONTEXTIMPL::getValue-1.2 result: [transactionId-ZFOr/PRIIPS], unwrap: true
--------------------------------------------------------------------------------------------------------------------------------------------
[qtp1615908941-218 - <<EVALUATION_CONTEXT_2>>] EVALUATIONCONTEXTIMPL::addResult-1 path: $.concat, model: [transactionId-ZFOr/MIFID], configuration: <<CONFIG>>, jsonProvider: <<JSONPROVIDER>>
[qtp1615908941-218 - <<EVALUATION_CONTEXT_2>>] EVALUATIONCONTEXTIMPL::addResult-2 valueResult: [[transactionId-ZFOr/MIFID]], resultIndex: 0, configuration: <<CONFIG>>, jsonProvider: <<JSONPROVIDER>>
[qtp1615908941-218 - <<EVALUATION_CONTEXT_2>>] EVALUATIONCONTEXTIMPL::addResult-3 valueResult: [[transactionId-ZFOr/MIFID]], resultIndex: 0, configuration: <<CONFIG>>, jsonProvider: <<JSONPROVIDER>>
[qtp1615908941-218 - <<COMPILED_PATH_1>>]      COMPILEDPATH::evaluate-2.2 ctx: <<EVALUATIONCTX>>, path: $.concat(...), configuration: <<CONFIG>>, jsonProvider: <<JSONPROVIDER>>
[qtp1615908941-218 - <<COMPILED_PATH_1>>]      COMPILEDPATH::evaluate-2.4 ctx: <<EVALUATIONCTX>>, path: $.concat(...), configuration: <<CONFIG>>, jsonProvider: <<JSONPROVIDER>>
[qtp1615908941-218 - <<COMPILED_PATH_1>>]      COMPILEDPATH::evaluate-1.1 result: <<EVALUATIONCTX>>, document: <<BODY>>, rootDocument: <<BODY>>, configuration: <<CONFIG>>
[qtp1615908941-218 - <<EVALUATION_CONTEXT_2>>] EVALUATIONCONTEXTIMPL::getValue-1.1 value: [transactionId-ZFOr/MIFID], unwrap: true
[qtp1615908941-218 - <<EVALUATION_CONTEXT_2>>] EVALUATIONCONTEXTIMPL::getValue-1.2 result: [transactionId-ZFOr/MIFID], unwrap: true
 --------------------------------------------------------------------------------------------------------------------------------------------

[qtp1615908941-218 - <<JSON_PATH_1>>]          JSONPATH::read-3 result: [transactionId-ZFOr/MIFID], jsonObject: <<BODY>>, configuration: <<CONFIG>>, jsonProvider: <<JSONPROVIDER>>
[qtp1615908941-218 - 1482307509] JSONPROVIDER::parse json: <<BODY>>