Skip to content

Conversation

@isaric
Copy link

@isaric isaric commented Jan 6, 2026

https://issues.apache.org/jira/browse/SOLR-17600

Description

This pull request replaces the deprecated MapSerializable interface with MapWriter across the Solr codebase. MapSerializable relied on the toMap(Map) pattern, which often led to unnecessary object allocations and inconsistent serialization behavior. By migrating to MapWriter and its writeMap(EntryWriter) pattern, we improve memory efficiency and ensure more consistent serialization across different formats like JavaBin and JSON.

Solution

The migration involved several key steps:

  1. Interface Removal: Deleted the MapSerializable interface and removed its usage from the MapWriter interface. MapWriter now serves as the primary interface for object-to-map serialization.
  2. Refactoring Components: Updated numerous classes across the codebase to implement MapWriter instead of MapSerializable. Key areas include:
    • Core Configuration: SolrConfig, PluginInfo, SolrIndexConfig, CacheConfig, ConfigOverlay, RequestParams, IndexSchema.
    • Cloud & Admin APIs: Many V2 API response classes such as CreateCore, InstallShardData, MigrateDocsAPI, ModifyCollectionAPI, MoveReplicaAPI, SplitShardAPI, and more.
    • Internal State: ZkNodeProps, IndexFingerprint.
  3. Method Migration: Converted toMap(Map<String, Object> map) implementations to writeMap(EntryWriter ew). This allows for direct writing to the underlying data structure (like JavaBinCodec's output stream) without necessarily creating intermediate Map objects.
  4. Utility Updates: Updated Utils.convertToMap, Utils.reflectToMap, and other utility methods to support the new pattern. Utils.makeDeepCopy now uses SimpleOrderedMap with MapWriter for better efficiency.
  5. Clean up: Removed redundant toMap calls and simplified serialization logic in several handlers and components. Updated JavaBinCodec, TextWriter, and JSONWriter to optimize for MapWriter.

Tests

Existing tests were updated to accommodate the change in serialization:

  • Updated TestConfig, SolrIndexConfigTest, CacheConfigTest, and NodeConfigClusterPluginsSourceTest to verify that the configuration objects are still correctly serialized.
  • Updated TestSchemaDesignerAPI and SolrExampleCborTest to ensure API and serialization consistency.
  • Verified that JavaBinCodec and JSONWriter correctly handle the new MapWriter implementations.
  • Ran core Solr tests to ensure no regressions in response formatting or internal state representation.

Checklist

Please review the following and check all that apply:

  • I have reviewed the guidelines for How to Contribute and my code conforms to the standards described there to the best of my ability.
  • I have created a Jira issue and added the issue ID to my pull request title.
  • I have given Solr maintainers access to contribute to my PR branch. (optional but recommended, not available for branches on forks living under an organisation)
  • I have developed this patch against the main branch.
  • I have run ./gradlew check.
  • I have added tests for my changes.
  • I have added documentation for the Reference Guide
  • I have added a changelog entry for my change

isaric added 13 commits January 6, 2026 10:12
…Map` for consistency in plugin and handler serialization
…deredMap` for consistent serialization in config and handler classes
…plugin and component info serialization with `SimpleOrderedMap`
Map deepCopy = Utils.getDeepCopy(data, 3);
Map p = (Map) deepCopy.get(NAME);
if (p == null) deepCopy.put(NAME, p = new LinkedHashMap<>());
if (paramSet == null) p.remove(name);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I wonder if this if should have { } to match the else?

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I agree that in Java conditionals should always use curly braces for clarity. This is the existing code that was not changed in my PR.

I am hesitant to change it as I am not sure if there is a convention regarding this practice in the project.

"cacheControl",
cacheControlHeader);
public void writeMap(EntryWriter ew) throws IOException {
ew.put("never304", never304)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this is nicer pattern, less a "unique magic pattern".


public static CreateCoreParams createRequestBodyFromV1Params(SolrParams solrParams) {
final var v1ParamMap = solrParams.toMap(new HashMap<>());
final var v1ParamMap = new SimpleOrderedMap<>(solrParams);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There is a subtle semantic difference here. Previously, we had a bonafide Map. If there were duplicate keys, the last value wins (looking at Utils.convertToMap, called by toMap). Probably wasn't intended but there is integrity of the Map contract at least. The constructor you use assumes the input has no duplicate keys. They will be added, and SimpleOrderedMap will not quite act exactly like a Map. I'm not sure what the final effect is without trying/testing. We could change SimpleOrderedMap's constructor here to have a hack for the NamedList (that isn't SimpleOrderedMap) case. Or don't use SimpleOrderedMap here, which I can see was chosen for your convenience, not because it's needed.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Replaced with Utils.convertToMap.

…CreateCore` for parameter handling simplification
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants