[ 
https://issues.apache.org/jira/browse/SOLR-18196?page=com.atlassian.jira.plugin.system.issuetabpanels:all-tabpanel
 ]

Geoffrey Slinker updated SOLR-18196:
------------------------------------
    Description: 
Bug Report: Java Serialization Broken for QueryResponse in SolrJ 10.0.0

Summary
-------
org.apache.solr.client.solrj.response.QueryResponse declares "implements 
Serializable" (inherited from SolrResponse) but cannot be serialized using 
Java's ObjectOutputStream in SolrJ 10.0.0. This is a regression from SolrJ 9.x 
where Java serialization worked correctly.

Affected Version
----------------
SolrJ 10.0.0

Steps to Reproduce
------------------
1. Obtain a QueryResponse from any SolrClient.query() call.
2. Attempt to serialize it with ObjectOutputStream:

   QueryResponse response = solrClient.query("collection", query, 
SolrRequest.METHOD.POST);
   ByteArrayOutputStream baos = new ByteArrayOutputStream();
   ObjectOutputStream oos = new ObjectOutputStream(baos);
   oos.writeObject(response);  // FAILS

Expected Behavior
-----------------
The QueryResponse object should serialize successfully, as it did in SolrJ 9.x. 
The class hierarchy declares Serializable:

   SolrResponse implements Serializable (with serialVersionUID)
   SolrResponseBase extends SolrResponse
   QueryResponse extends SolrResponseBase

Actual Behavior
---------------
Serialization fails with:

   java.lang.NoSuchFieldException: serialPersistentFields

The exception is thrown during ObjectOutputStream.writeObject() when Java's 
serialization mechanism attempts to introspect the class hierarchy.

Root Cause
----------
In Solr 10.0.0, SimpleOrderedMap was changed to implement java.util.Map as part 
of SIP-22 (NamedList Reduction):

   SolrJ 9.x:  public class SimpleOrderedMap<T> extends NamedList<T>
   SolrJ 10.0:  public class SimpleOrderedMap<T> extends NamedList<T> 
implements Map<String, T>

QueryResponse internally contains a NamedList (via SolrResponseBase.response), 
which at runtime is a SimpleOrderedMap. When Java's ObjectOutputStream walks 
the class hierarchy of SimpleOrderedMap to build serialization metadata, it 
encounters the Map interface and attempts to locate serialPersistentFields on 
the class. This introspection fails with NoSuchFieldException, which causes 
serialization to fail.

Impact
------
Any code that relies on Java serialization of QueryResponse (or any 
SolrResponse subclass containing SimpleOrderedMap instances) is broken. This 
includes:

   - Caching serialized Solr responses
   - Storing Solr responses for test fixtures
   - Any framework that serializes Serializable objects (session replication, 
distributed caches, etc.)



  was:
Bug Report: Java Serialization Broken for QueryResponse in SolrJ 10.0.0

Summary
-------
org.apache.solr.client.solrj.response.QueryResponse declares "implements 
Serializable" (inherited from SolrResponse) but cannot be serialized using 
Java's ObjectOutputStream in SolrJ 10.0.0. This is a regression from SolrJ 9.x 
where Java serialization worked correctly.

Affected Version
----------------
SolrJ 10.0.0

Steps to Reproduce
------------------
1. Obtain a QueryResponse from any SolrClient.query() call.
2. Attempt to serialize it with ObjectOutputStream:

   QueryResponse response = solrClient.query("collection", query, 
SolrRequest.METHOD.POST);
   ByteArrayOutputStream baos = new ByteArrayOutputStream();
   ObjectOutputStream oos = new ObjectOutputStream(baos);
   oos.writeObject(response);  // FAILS

Expected Behavior
-----------------
The QueryResponse object should serialize successfully, as it did in SolrJ 9.x. 
The class hierarchy declares Serializable:

   SolrResponse implements Serializable (with serialVersionUID)
   SolrResponseBase extends SolrResponse
   QueryResponse extends SolrResponseBase

Actual Behavior
---------------
Serialization fails with:

   java.lang.NoSuchFieldException: serialPersistentFields

The exception is thrown during ObjectOutputStream.writeObject() when Java's 
serialization mechanism attempts to introspect the class hierarchy.

Root Cause
----------
In Solr 10.0.0, SimpleOrderedMap was changed to implement java.util.Map as part 
of SIP-22 (NamedList Reduction):

   SolrJ 9.x:  public class SimpleOrderedMap<T> extends NamedList<T>
   SolrJ 10.0:  public class SimpleOrderedMap<T> extends NamedList<T> 
implements Map<String, T>

QueryResponse internally contains a NamedList (via SolrResponseBase.response), 
which at runtime is a SimpleOrderedMap. When Java's ObjectOutputStream walks 
the class hierarchy of SimpleOrderedMap to build serialization metadata, it 
encounters the Map interface and attempts to locate serialPersistentFields on 
the class. This introspection fails with NoSuchFieldException, which causes 
serialization to fail.

Impact
------
Any code that relies on Java serialization of QueryResponse (or any 
SolrResponse subclass containing SimpleOrderedMap instances) is broken. This 
includes:

   - Caching serialized Solr responses
   - Storing Solr responses for test fixtures
   - Any framework that serializes Serializable objects (session replication, 
distributed caches, etc.)

Suggested Fix
-------------
Option 1: Fix SimpleOrderedMap serialization by adding proper 
serialPersistentFields, writeObject, and readObject methods to handle the Map 
interface correctly during Java serialization.

Option 2: Remove Serializable from SolrResponse if Java serialization is no 
longer intended to be supported. Remove the serialVersionUID from SolrResponse 
to make the contract explicit. Update the migration guide to document this 
breaking change and recommend JavaBinCodec as the alternative.

Option 3: At minimum, add a note to the Solr 10 upgrade guide that Java 
serialization of QueryResponse is no longer supported, and that JavaBinCodec 
should be used instead. Note that JavaBinCodec only serializes the NamedList 
response data and does not preserve client-side fields like elapsedTime.

Workaround
----------
Use JavaBinCodec to serialize the NamedList from QueryResponse.getResponse():

   // Encode
   JavaBinCodec codec = new JavaBinCodec();
   ByteArrayOutputStream baos = new ByteArrayOutputStream();
   codec.marshal(response.getResponse(), baos);
   byte[] bytes = baos.toByteArray();

   // Decode
   NamedList namedList = (NamedList) new JavaBinCodec().unmarshal(new 
ByteArrayInputStream(bytes));
   QueryResponse restored = new QueryResponse(namedList);

Note: elapsedTime (a client-side measurement set by SolrClient after the HTTP 
round-trip) is NOT part of the NamedList and is lost during this process. QTime 
(Solr's server-side query time) IS preserved as it is part of the 
responseHeader in the NamedList.



> Java serialization broken for QueryResponse - SimpleOrderedMap implements Map 
> breaks ObjectOutputStream 
> --------------------------------------------------------------------------------------------------------
>
>                 Key: SOLR-18196
>                 URL: https://issues.apache.org/jira/browse/SOLR-18196
>             Project: Solr
>          Issue Type: Bug
>          Components: clients - java
>    Affects Versions: 10.0
>         Environment: Client using SolrJ on Mac OS using Java 21. Solr 
> instances running in AWS on EC2 instances.
>            Reporter: Geoffrey Slinker
>            Priority: Major
>
> Bug Report: Java Serialization Broken for QueryResponse in SolrJ 10.0.0
> Summary
> -------
> org.apache.solr.client.solrj.response.QueryResponse declares "implements 
> Serializable" (inherited from SolrResponse) but cannot be serialized using 
> Java's ObjectOutputStream in SolrJ 10.0.0. This is a regression from SolrJ 
> 9.x where Java serialization worked correctly.
> Affected Version
> ----------------
> SolrJ 10.0.0
> Steps to Reproduce
> ------------------
> 1. Obtain a QueryResponse from any SolrClient.query() call.
> 2. Attempt to serialize it with ObjectOutputStream:
>    QueryResponse response = solrClient.query("collection", query, 
> SolrRequest.METHOD.POST);
>    ByteArrayOutputStream baos = new ByteArrayOutputStream();
>    ObjectOutputStream oos = new ObjectOutputStream(baos);
>    oos.writeObject(response);  // FAILS
> Expected Behavior
> -----------------
> The QueryResponse object should serialize successfully, as it did in SolrJ 
> 9.x. The class hierarchy declares Serializable:
>    SolrResponse implements Serializable (with serialVersionUID)
>    SolrResponseBase extends SolrResponse
>    QueryResponse extends SolrResponseBase
> Actual Behavior
> ---------------
> Serialization fails with:
>    java.lang.NoSuchFieldException: serialPersistentFields
> The exception is thrown during ObjectOutputStream.writeObject() when Java's 
> serialization mechanism attempts to introspect the class hierarchy.
> Root Cause
> ----------
> In Solr 10.0.0, SimpleOrderedMap was changed to implement java.util.Map as 
> part of SIP-22 (NamedList Reduction):
>    SolrJ 9.x:  public class SimpleOrderedMap<T> extends NamedList<T>
>    SolrJ 10.0:  public class SimpleOrderedMap<T> extends NamedList<T> 
> implements Map<String, T>
> QueryResponse internally contains a NamedList (via 
> SolrResponseBase.response), which at runtime is a SimpleOrderedMap. When 
> Java's ObjectOutputStream walks the class hierarchy of SimpleOrderedMap to 
> build serialization metadata, it encounters the Map interface and attempts to 
> locate serialPersistentFields on the class. This introspection fails with 
> NoSuchFieldException, which causes serialization to fail.
> Impact
> ------
> Any code that relies on Java serialization of QueryResponse (or any 
> SolrResponse subclass containing SimpleOrderedMap instances) is broken. This 
> includes:
>    - Caching serialized Solr responses
>    - Storing Solr responses for test fixtures
>    - Any framework that serializes Serializable objects (session replication, 
> distributed caches, etc.)



--
This message was sent by Atlassian Jira
(v8.20.10#820010)

---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]

Reply via email to