Skip to content

Issue Writing Empty Document Properties #1153

Closed
@Zipunrar

Description

@Zipunrar

Hi MarkLogic,

I do have an issue writing document properties with the new Java Client API Version 4.
Here are the details:

Version of MarkLogic Java Client API

4.2.0

Version of MarkLogic Server

9.0.8

Java version

Java(TM) SE Runtime Environment (build 1.8.0_121-b13)

Input: Some code to illustrate the problem, preferably in a state that can be independently

DatabaseClient markLogic = ... // create client connection
XMLDocumentManager manager = markLogic.newXMLDocumentManager();
DocumentMetadataHandle metadata = new DocumentMetadataHandle();
// this won't work
metadata.getProperties().put("foobar", "");
StringHandle data = new StringHandle("<root>Test</root>");
// error is thrown here
manager.write("/test.xml", metadata, data);
markLogic.release();

Actual output: What did you observe? What errors did you see? Can you attach the logs? (Java logs, MarkLogic logs)

The following stacktrace is thrown:

java.lang.NullPointerException
	at com.ctc.wstx.sw.BaseStreamWriter.writeCharacters(BaseStreamWriter.java:464)
	at com.marklogic.client.io.DocumentMetadataHandle$ValueSerializer.process(DocumentMetadataHandle.java:917)
	at com.marklogic.client.impl.ValueConverter.convertFromJava(ValueConverter.java:253)
	at com.marklogic.client.impl.ValueConverter.convertFromJava(ValueConverter.java:94)
	at com.marklogic.client.io.DocumentMetadataHandle.sendPropertiesImpl(DocumentMetadataHandle.java:886)
	at com.marklogic.client.io.DocumentMetadataHandle.sendMetadataImpl(DocumentMetadataHandle.java:788)
	at com.marklogic.client.io.DocumentMetadataHandle.write(DocumentMetadataHandle.java:574)
	at com.marklogic.client.impl.StreamingOutputImpl.writeTo(StreamingOutputImpl.java:58)
	at okhttp3.MultipartBody.writeOrCountBytes(MultipartBody.java:173)
	at okhttp3.MultipartBody.writeTo(MultipartBody.java:114)
	at okhttp3.internal.http.CallServerInterceptor.intercept(CallServerInterceptor.java:72)
	at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.java:147)
	at okhttp3.internal.connection.ConnectInterceptor.intercept(ConnectInterceptor.java:45)
	at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.java:147)
	at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.java:121)
	at okhttp3.internal.cache.CacheInterceptor.intercept(CacheInterceptor.java:93)
	at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.java:147)
	at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.java:121)
	at okhttp3.internal.http.BridgeInterceptor.intercept(BridgeInterceptor.java:93)
	at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.java:147)
	at okhttp3.internal.http.RetryAndFollowUpInterceptor.intercept(RetryAndFollowUpInterceptor.java:126)
	at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.java:147)
	at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.java:121)
	at com.burgstaller.okhttp.AuthenticationCacheInterceptor.intercept(AuthenticationCacheInterceptor.java:45)
	at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.java:147)
	at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.java:121)
	at okhttp3.RealCall.getResponseWithInterceptorChain(RealCall.java:200)
	at okhttp3.RealCall.execute(RealCall.java:77)
	at com.marklogic.client.impl.OkHttpServices.sendRequestOnce(OkHttpServices.java:757)
	at com.marklogic.client.impl.OkHttpServices.sendRequestOnce(OkHttpServices.java:752)
	at com.marklogic.client.impl.OkHttpServices.putPostDocumentImpl(OkHttpServices.java:1609)
	at com.marklogic.client.impl.OkHttpServices.putDocument(OkHttpServices.java:1319)
	at com.marklogic.client.impl.DocumentManagerImpl.write(DocumentManagerImpl.java:920)
	at com.marklogic.client.impl.DocumentManagerImpl.write(DocumentManagerImpl.java:758)
	at com.marklogic.client.impl.DocumentManagerImpl.write(DocumentManagerImpl.java:702)
	at com.din.xscore.core.domain.marklogic.operation.MarkLogicDocumentPatcherTest.test(MarkLogicDocumentPatcherTest.java:83)
	at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
	at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
	at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
	at java.lang.reflect.Method.invoke(Method.java:498)
	at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:50)
	at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12)
	at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:47)
	at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:17)
	at org.junit.internal.runners.statements.RunBefores.evaluate(RunBefores.java:26)
	at org.springframework.test.context.junit4.statements.RunBeforeTestMethodCallbacks.evaluate(RunBeforeTestMethodCallbacks.java:75)
	at org.junit.internal.runners.statements.RunAfters.evaluate(RunAfters.java:27)
	at org.springframework.test.context.junit4.statements.RunAfterTestMethodCallbacks.evaluate(RunAfterTestMethodCallbacks.java:86)
	at org.springframework.test.context.junit4.statements.SpringRepeat.evaluate(SpringRepeat.java:84)
	at org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:325)
	at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.runChild(SpringJUnit4ClassRunner.java:252)
	at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.runChild(SpringJUnit4ClassRunner.java:94)
	at org.junit.runners.ParentRunner$3.run(ParentRunner.java:290)
	at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:71)
	at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:288)
	at org.junit.runners.ParentRunner.access$000(ParentRunner.java:58)
	at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:268)
	at org.junit.internal.runners.statements.RunBefores.evaluate(RunBefores.java:26)
	at org.springframework.test.context.junit4.statements.RunBeforeTestClassCallbacks.evaluate(RunBeforeTestClassCallbacks.java:61)
	at org.springframework.test.context.junit4.statements.RunAfterTestClassCallbacks.evaluate(RunAfterTestClassCallbacks.java:70)
	at org.junit.runners.ParentRunner.run(ParentRunner.java:363)
	at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.run(SpringJUnit4ClassRunner.java:191)
	at org.gradle.api.internal.tasks.testing.junit.JUnitTestClassExecuter.runTestClass(JUnitTestClassExecuter.java:114)
	at org.gradle.api.internal.tasks.testing.junit.JUnitTestClassExecuter.execute(JUnitTestClassExecuter.java:57)
	at org.gradle.api.internal.tasks.testing.junit.JUnitTestClassProcessor.processTestClass(JUnitTestClassProcessor.java:66)
	at org.gradle.api.internal.tasks.testing.SuiteTestClassProcessor.processTestClass(SuiteTestClassProcessor.java:51)
	at sun.reflect.GeneratedMethodAccessor3.invoke(Unknown Source)
	at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
	at java.lang.reflect.Method.invoke(Method.java:498)
	at org.gradle.internal.dispatch.ReflectionDispatch.dispatch(ReflectionDispatch.java:35)
	at org.gradle.internal.dispatch.ReflectionDispatch.dispatch(ReflectionDispatch.java:24)
	at org.gradle.internal.dispatch.ContextClassLoaderDispatch.dispatch(ContextClassLoaderDispatch.java:32)
	at org.gradle.internal.dispatch.ProxyDispatchAdapter$DispatchingInvocationHandler.invoke(ProxyDispatchAdapter.java:93)
	at com.sun.proxy.$Proxy2.processTestClass(Unknown Source)
	at org.gradle.api.internal.tasks.testing.worker.TestWorker.processTestClass(TestWorker.java:109)
	at sun.reflect.GeneratedMethodAccessor2.invoke(Unknown Source)
	at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
	at java.lang.reflect.Method.invoke(Method.java:498)
	at org.gradle.internal.dispatch.ReflectionDispatch.dispatch(ReflectionDispatch.java:35)
	at org.gradle.internal.dispatch.ReflectionDispatch.dispatch(ReflectionDispatch.java:24)
	at org.gradle.internal.remote.internal.hub.MessageHubBackedObjectConnection$DispatchWrapper.dispatch(MessageHubBackedObjectConnection.java:147)
	at org.gradle.internal.remote.internal.hub.MessageHubBackedObjectConnection$DispatchWrapper.dispatch(MessageHubBackedObjectConnection.java:129)
	at org.gradle.internal.remote.internal.hub.MessageHub$Handler.run(MessageHub.java:404)
	at org.gradle.internal.concurrent.ExecutorPolicy$CatchAndRecordFailures.onExecute(ExecutorPolicy.java:63)
	at org.gradle.internal.concurrent.StoppableExecutorImpl$1.run(StoppableExecutorImpl.java:46)
	at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142)
	at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)
	at java.lang.Thread.run(Thread.java:745)

However the root cause of this issue is a function called "StringToString" in com.marklogic.client.impl.ValueConverter at line 579 that returns a "null" value for "null" string but sadly also for "empty" strings (see line 581).

Expected output: What specifically did you expect to happen?

I would expect that I am able to write empty properties as before with Client API 3 and ML 8.
A property should accept empty strings as a valid value since that might be a real-world scenario like in my case. I want to have an empty property to express the different between "not available" and "not set". The value "null" might be worth an error, however empty string is valid in my opinion.

Thanks in advance for any help.

Metadata

Metadata

Type

No type

Projects

No projects

Relationships

None yet

Development

No branches or pull requests

Issue actions