Search code examples
javaxquerymarklogic

MarkLogic: pass Map-Object from Java to XQuery


I would like to pass a simple Java Map<String, String> through the MarkLogic Java API to an XQuery script. The script is already deployed to the /ext directory on the server and starts like this:

xquery version "1.0-ml";

declare variable $dr as xs:string external;
declare variable $en as xs:string external;
declare variable $fi as map:map external;
...

I'm using the pattern described on the MarkLogic Site: https://docs.marklogic.com/guide/java/resourceservices#id_70532 ("Basic Steps for Module Invocation").

My Java code looks like this:

Map<String, String> map = new HashMap<>();
map.put("key1", "value1");
map.put("key2", "value2");

ServerEvaluationCall invoker = client.newServerEval();
invoker.addVariable("dr", "foo");
invoker.addVariable("en", "bar");
invoker.addVariableAs("fi", map);
String response = invoker.evalAs(String.class);

This fails with this exception:

java.lang.IllegalArgumentException: No factory for class java.util.HashMap
    at com.marklogic.client.impl.HandleFactoryRegistryImpl.makeHandle(HandleFactoryRegistryImpl.java:98) ~[marklogic-client-api-4.0.3.jar:?]
    at com.marklogic.client.impl.ServerEvaluationCallImpl.addVariableAs(ServerEvaluationCallImpl.java:123) ~[marklogic-client-api-4.0.3.jar:?]

I think I need to convert the map before sending it to ML or maybe use one of the handler classes, but I was not able to solve it or find any examples of this. Has anyone done this before?


Solution

  • It should work to pass a Jackson JSON object to an XQuery external variable. The value in XQuery should be either an XQuery map or a JSON node. If it's a JSON node, the xdmp:from-json() function can convert the value to an XQuery map.

    For the Java part, look for the example introduced as "the following code uses a Jackson object mapper to set an external variable value to a JSON object":

    https://docs.marklogic.com/guide/java/resourceservices#id_21827

    Hoping that helps,