This is an automated email from the ASF dual-hosted git repository.
dsmiley pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/solr.git
The following commit(s) were added to refs/heads/main by this push:
new 06768041f92 SOLR-17635: solr.solrj.javabin.readMapAsNamedList=true
opt-in (#3163)
06768041f92 is described below
commit 06768041f9223d64e1f07ad821bc2aec269b285b
Author: Renato Haeberli <[email protected]>
AuthorDate: Wed Jun 25 05:47:22 2025 +0200
SOLR-17635: solr.solrj.javabin.readMapAsNamedList=true opt-in (#3163)
javabin format: provide option to decode maps as SimpleOrderedMap (a
NamedList & Map)
instead of LinkedHashMap. Intended to aid in 10.x compatibility. Enable
via sys prop: solr.solrj.javabin.readMapAsNamedList=true
---
solr/CHANGES.txt | 4 +++
.../solrj/request/JavaBinUpdateRequestCodec.java | 1 +
.../org/apache/solr/common/util/JavaBinCodec.java | 30 ++++++++++++++--
.../solr/common/util/TestFastJavabinDecoder.java | 8 ++---
.../apache/solr/common/util/TestJavaBinCodec.java | 40 +++++++++++++---------
5 files changed, 60 insertions(+), 23 deletions(-)
diff --git a/solr/CHANGES.txt b/solr/CHANGES.txt
index 35447fc2fcb..2813b433806 100644
--- a/solr/CHANGES.txt
+++ b/solr/CHANGES.txt
@@ -369,6 +369,10 @@ Other Changes
* SOLR-17625: Replaced NamedList.findRecursive usages with _get, which can do
Map traversal, and
thus makes it easier to transition intermediate NamedLists to Maps. (Gaurav
Tuli)
+* SOLR-17635: javabin format: provide option to decode maps as
SimpleOrderedMap (a NamedList & Map)
+ instead of LinkedHashMap. Intended to aid in 10.x compatibility. Enable
via sys prop: solr.solrj.javabin.readMapAsNamedList=true
+ (Renato Haeberli, David Smiley)
+
================== 9.8.1 ==================
Bug Fixes
---------------------
diff --git
a/solr/solrj/src/java/org/apache/solr/client/solrj/request/JavaBinUpdateRequestCodec.java
b/solr/solrj/src/java/org/apache/solr/client/solrj/request/JavaBinUpdateRequestCodec.java
index 782f441eb19..6ce10ef381b 100644
---
a/solr/solrj/src/java/org/apache/solr/client/solrj/request/JavaBinUpdateRequestCodec.java
+++
b/solr/solrj/src/java/org/apache/solr/client/solrj/request/JavaBinUpdateRequestCodec.java
@@ -106,6 +106,7 @@ public class JavaBinUpdateRequestCodec {
// reads documents, sending to handler. Other data is in NamedList
try (var codec = new StreamingCodec(handler)) {
+ codec.readMapAsNamedList(false);
namedList = codec.unmarshal(is);
}
diff --git a/solr/solrj/src/java/org/apache/solr/common/util/JavaBinCodec.java
b/solr/solrj/src/java/org/apache/solr/common/util/JavaBinCodec.java
index 7373632da28..a19896ff2b3 100644
--- a/solr/solrj/src/java/org/apache/solr/common/util/JavaBinCodec.java
+++ b/solr/solrj/src/java/org/apache/solr/common/util/JavaBinCodec.java
@@ -124,6 +124,9 @@ public class JavaBinCodec implements PushWriter {
private boolean alreadyUnmarshalled;
protected boolean readStringAsCharSeq = false;
+ private boolean readMapAsNamedList =
+ EnvUtils.getPropertyAsBool("solr.solrj.javabin.readMapAsNamedList",
false);
+
public JavaBinCodec() {
resolver = null;
writableDocFields = null;
@@ -848,9 +851,14 @@ public class JavaBinCodec implements PushWriter {
return size < 0 ? new LinkedHashMap<>() :
CollectionUtil.newLinkedHashMap(size);
}
- public Map<Object, Object> readMap(DataInputInputStream dis) throws
IOException {
+ public Map<?, Object> readMap(DataInputInputStream dis) throws IOException {
int sz = readVInt(dis);
- return readMap(dis, sz);
+
+ if (readMapAsNamedList) {
+ return readMapAsSimpleOrderedMapForStringKeys(dis, sz);
+ } else {
+ return readMap(dis, sz);
+ }
}
protected Map<Object, Object> readMap(DataInputInputStream dis, int sz)
throws IOException {
@@ -863,6 +871,17 @@ public class JavaBinCodec implements PushWriter {
return m;
}
+ protected Map<?, Object>
readMapAsSimpleOrderedMapForStringKeys(DataInputInputStream dis, int sz)
+ throws IOException {
+ SimpleOrderedMap<Object> entries = new SimpleOrderedMap<>(sz);
+ for (int i = 0; i < sz; i++) {
+ Object key = readVal(dis);
+ Object val = readVal(dis);
+ entries.add((String) key, val); // using NL.add() since key won't repeat
+ }
+ return entries;
+ }
+
public final ItemWriter itemWriter =
new ItemWriter() {
@Override
@@ -1436,4 +1455,11 @@ public class JavaBinCodec implements PushWriter {
daos.flushBuffer();
}
}
+
+ /**
+ * If set, Maps will be deserialized as {@link SimpleOrderedMap} instead of
{@link LinkedHashMap}
+ */
+ public void readMapAsNamedList(boolean readMapAsNamedList) {
+ this.readMapAsNamedList = readMapAsNamedList;
+ }
}
diff --git
a/solr/solrj/src/test/org/apache/solr/common/util/TestFastJavabinDecoder.java
b/solr/solrj/src/test/org/apache/solr/common/util/TestFastJavabinDecoder.java
index 9759fd84b92..6c572f91fcd 100644
---
a/solr/solrj/src/test/org/apache/solr/common/util/TestFastJavabinDecoder.java
+++
b/solr/solrj/src/test/org/apache/solr/common/util/TestFastJavabinDecoder.java
@@ -91,8 +91,8 @@ public class TestFastJavabinDecoder extends SolrTestCaseJ4 {
.withInputStream(new FastInputStream(null, baos.getbuf(), 0,
baos.size()))
.decode(FastJavaBinDecoder.getEntryListener());
assertEquals(
- Utils.writeJson(m2, new StringWriter(), true).toString(),
- Utils.writeJson(fastMap, new StringWriter(), true).toString());
+ Utils.writeJson(m2, new StringWriter(), false).toString(),
+ Utils.writeJson(fastMap, new StringWriter(), false).toString());
@SuppressWarnings({"unchecked", "rawtypes"})
Object newMap =
@@ -125,8 +125,8 @@ public class TestFastJavabinDecoder extends SolrTestCaseJ4 {
});
((Map) m2.get("mapk")).remove("k2");
assertEquals(
- Utils.writeJson(m2, new StringWriter(), true).toString(),
- Utils.writeJson(newMap, new StringWriter(), true).toString());
+ Utils.writeJson(m2, new StringWriter(), false).toString(),
+ Utils.writeJson(newMap, new StringWriter(), false).toString());
}
public void testFastJavabinStreamingDecoder() throws IOException {
diff --git
a/solr/solrj/src/test/org/apache/solr/common/util/TestJavaBinCodec.java
b/solr/solrj/src/test/org/apache/solr/common/util/TestJavaBinCodec.java
index eb9cc217113..52d5cf1e3c9 100644
--- a/solr/solrj/src/test/org/apache/solr/common/util/TestJavaBinCodec.java
+++ b/solr/solrj/src/test/org/apache/solr/common/util/TestJavaBinCodec.java
@@ -69,6 +69,7 @@ public class TestJavaBinCodec extends SolrTestCaseJ4 {
jbcO.marshal(s, os);
try (JavaBinCodec jbcI = new JavaBinCodec();
ByteArrayInputStream is = new
ByteArrayInputStream(os.toByteArray())) {
+ jbcI.readMapAsNamedList(false);
Object o = jbcI.unmarshal(is);
assertEquals(s, o);
}
@@ -86,6 +87,17 @@ public class TestJavaBinCodec extends SolrTestCaseJ4 {
compareObjects((List) getObject(getBytes(types, true)), (List) types);
}
+ public void testReadMap() throws Exception {
+ Map<String, String> types = new HashMap<>();
+ types.put("1", "one");
+
+ byte[] bytes = getBytes(types, true);
+ Object result = getObjectWithMapAsNl(bytes, true);
+
+ assertTrue(result instanceof SimpleOrderedMap);
+ assertEquals("one", ((SimpleOrderedMap<?>) result).get("1"));
+ }
+
public static SolrDocument generateSolrDocumentWithChildDocs() {
SolrDocument parentDocument = new SolrDocument();
parentDocument.addField("id", "1");
@@ -162,11 +174,6 @@ public class TestJavaBinCodec extends SolrTestCaseJ4 {
types.add(new byte[] {1, 2, 3, 4, 5});
- // TODO?
- // List<String> list = new ArrayList<String>();
- // list.add("one");
- // types.add(list.iterator());
-
types.add((byte) 15); // END
SolrInputDocument idoc = new SolrInputDocument();
@@ -211,6 +218,7 @@ public class TestJavaBinCodec extends SolrTestCaseJ4 {
return super.readIterator(fis);
}
}; ) {
+ javabin.readMapAsNamedList(false);
@SuppressWarnings({"unchecked"})
List<Object> unmarshalledObj = (List<Object>) javabin.unmarshal(is);
List<Object> matchObj = generateAllDataTypes();
@@ -285,6 +293,7 @@ public class TestJavaBinCodec extends SolrTestCaseJ4 {
ByteArrayOutputStream os = new ByteArrayOutputStream()) {
Object data = generateAllDataTypes();
+ javabin.readMapAsNamedList(false);
javabin.marshal(data, os);
byte[] newFormatBytes = os.toByteArray();
@@ -294,7 +303,7 @@ public class TestJavaBinCodec extends SolrTestCaseJ4 {
for (int i = 1;
i < currentFormatBytes.length;
i++) { // ignore the first byte. It is version information
- assertEquals(newFormatBytes[i], currentFormatBytes[i]);
+ assertEquals("for i:" + i, newFormatBytes[i], currentFormatBytes[i]);
}
}
}
@@ -383,6 +392,7 @@ public class TestJavaBinCodec extends SolrTestCaseJ4 {
try (InputStream is = getClass().getResourceAsStream(fileName)) {
try (DataInputInputStream dis = new FastInputStream(is)) {
try (JavaBinCodec javabin = new JavaBinCodec()) {
+ javabin.readMapAsNamedList(false);
return javabin.readMapEntry(dis);
}
}
@@ -410,12 +420,18 @@ public class TestJavaBinCodec extends SolrTestCaseJ4 {
}
}
- private static Object getObject(byte[] bytes) throws IOException {
+ private static Object getObjectWithMapAsNl(byte[] bytes, boolean
mapAsNamedList)
+ throws IOException {
try (JavaBinCodec jbc = new JavaBinCodec()) {
+ jbc.readMapAsNamedList(mapAsNamedList);
return jbc.unmarshal(new ByteArrayInputStream(bytes));
}
}
+ private static Object getObject(byte[] bytes) throws IOException {
+ return getObjectWithMapAsNl(bytes, false);
+ }
+
@Test
public void testResponseChildDocuments() throws IOException {
SolrDocument result =
@@ -582,16 +598,6 @@ public class TestJavaBinCodec extends SolrTestCaseJ4 {
System.out.println("Free Memory:" + runtime.freeMemory() / mb);
}
- public static void main(String[] args) throws IOException {
- TestJavaBinCodec test = new TestJavaBinCodec();
- test.genBinaryFiles();
- // try {
- // doDecodePerf(args);
- // } catch (Exception e) {
- // throw new RuntimeException(e);
- // }
- }
-
// common-case ascii
static String str(Random r, int sz) {
StringBuilder sb = new StringBuilder(sz);