For each XML we store in MarkLogic we store calculated values in the document's associated properties. One of these values is a potentially large decimal value. Which is causing an exception because the Marklogic Java API is formatting the number in the XML it sends to the MarkLogic server in a way that the MarkLogic server doesn’t like.
We have a Range Element Index set up on a “TotalObligatedAmount” element that we store in the properties:
The Java code below reproduces the issues we are seeing:
import java.nio.charset.StandardCharsets;
import org.apache.commons.io.IOUtils;
import org.w3c.dom.Document;
import com.marklogic.client.DatabaseClient;
import com.marklogic.client.document.XMLDocumentManager;
import com.marklogic.client.io.DOMHandle;
import com.marklogic.client.io.DocumentMetadataHandle;
@Component
public class LoadTester {
private final XMLDocumentManager mgr;
public LoadTester(DatabaseClient client) {
this.mgr = client.newXMLDocumentManager();
}
public void loadTest() throws Exception {
String uri = "testDocument.xml";
DOMHandle handle = new DOMHandle();
String xml = "<test><value>Hello World</value></test>";
Document doc = handle.getFactory().newDocumentBuilder()
.parse(IOUtils.toInputStream(xml, StandardCharsets.UTF_8));
DocumentMetadataHandle metadataHandle = new DocumentMetadataHandle();
metadataHandle.withProperty("TotalObligatedAmount",Double.valueOf(18912626.00));
handle.set(doc);
mgr.write(mgr.newDescriptor(uri), metadataHandle, handle);
}
}
This results in the following Exception:
Exception in thread "main" com.marklogic.client.FailedRequestException: Local message: write failed: Bad Request. Server Message: XDMP-RANGEINDEX: Range index error: decimal xdmp:document-properties("testDocument.xml")/prop:properties/TotalObligatedAmount: XDMP-LEXVAL: Invalid lexical value "1.8912626E7"
at com.marklogic.client.impl.OkHttpServices.putPostDocumentImpl(OkHttpServices.java:1697)
at com.marklogic.client.impl.OkHttpServices.putDocument(OkHttpServices.java:1344)
at com.marklogic.client.impl.DocumentManagerImpl.write(DocumentManagerImpl.java:940)
at com.marklogic.client.impl.DocumentManagerImpl.write(DocumentManagerImpl.java:888)
at com.marklogic.client.impl.DocumentManagerImpl.write(DocumentManagerImpl.java:827)
The properties data XML that the Java API is generating and sending to the server is:
<?xml version='1.0' encoding='utf-8'?>
<rapi:metadata xmlns:rapi="http://marklogic.com/rest-api"
xmlns:prop="http://marklogic.com/xdmp/property"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:xs="http://www.w3.org/2001/XMLSchema">
<prop:properties>
<TotalObligatedAmount xsi:type="xs:double">1.8912626E7</TotalObligatedAmount>
</prop:properties>
</rapi:metadata>
When serializing the properties to XML the decimal value of 18,912,626.00 is being turned into the string 1.8912626E7 and the MarkLogic server is rejecting that string.
I was able to step through the code to find out how the double gets converted to a string. The com.marklogic.client.impl.ValueConverter does the conversion and it uses the javax.xml.bind.DatatypeConverter.printDouble() method to convert the Double to the “1.8912626E7” String (ultimately using the String.valueOf(doubleValue) method.
Does anyone know how I can get around this? Is there a change I need to make on the server or a way to configure the Java API?
I'm using version 5.2.0 of the Java API and version 10.0-8.1 of the MarkLogic server.