Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Replace XStream with Jackson for XML Object Mapping. #27996

Open
2 tasks
spbolton opened this issue Mar 18, 2024 · 0 comments
Open
2 tasks

Replace XStream with Jackson for XML Object Mapping. #27996

spbolton opened this issue Mar 18, 2024 · 0 comments

Comments

@spbolton
Copy link
Contributor

spbolton commented Mar 18, 2024

Note this was originally part of #27993, but due to the addition of add-opens parameters XStream no longer fails in Java21. This is a patch though and the underlying issues with serialization/deserialization of internal classes here remain and should be a priority, it is just this is no longer a blocker for running on Java 21 initially.

Create Dual Mapping using either XStream or Jackson (through jackson-dataformat-xml) . Allow for configuration of which classes uses which processor.

There are two main Locations in the code we do mapping from Objects to and from XML These are

  • BundlerUtil. Used specifically to create bundles based upon the objects
  • XmlSerializerUtil . Used by other classes requiring an XML representation

There are then a couple of side uses of XStream more API dependencies that may be able to be removed or adjusted to use Jackson at some point.

  • DotObjectCodec
  • DotPrettyPrintWriter

From review in intellij of the usage of the XStream method to create XML from Objects and Objects from XML I have identified what should be a full list of Top Level Classes being serialized. Within each of these classes we need to review the basic class types we are serializing and the sub-classes to make sure we have appropriate mappings.

Most of the issues with have with Java21 and XStream are due to some classes falling back to either Reflection-based or Java "Serializable" based mappings which may previously work without error, but can both expose implementation details in the XML, e.g. implementation class name and private information in the use of Concurrent Hashmap rather than a generic Map serialization. This also makes the deserialization process brittle. Java 21 no longer allows for the dynamic changing of the visibility of private fields and the reflection of internal classes so we will need to modify the serialization of these.

Initially, we will allow for the ability to select based on the class, whether Jackson or Xstream should be used for the serialization and deserialization allowing us to work on a class-by-class basis eventually switching over to Jackson only before the final Java 21 switch.

We should also create for testing and migration the ability to read and write through either implementation and compare the results. This would then become the basis for the conversion of legacy testing bundles into the new structure and can be used to convert Customer bundles before they migrate to our Java 21 release. Our final Java 11 .

Key takeaways.
If we can easily change to use Jackson for a class and there is no legacy data for files, or can easily confirm compatible xml is produced then just do it we do not need to have both,
Unless some special functionality is required instead of using XStreamHandler.newXStreamInstance(); directly as of now we should just have a Util class we can use for any XMLSerialization/Deserialization and can include Json. This is the model of BundlerUtil and we may want to rename this and reuse this across the board in place of the patter currently used in the HandlerClasses that get their own xstream instance currently.

  1. Refactor BundlerUtil object<>xml and object<>json methods into a new SerializationUtils class. That hides the Implementing library and can be used outside the Bundler.

  2. Add Feature flag and configuration to enable choice of XML serializer by class, also allow for debugging of non-configured class for comparison. e.g. Write to with XStream, but also if configured to debug the class, then it can also write with Jackson ( If jackson fails then just log issue and move on, or make it easy to compare the output produced )

  3. Work through each class type and subtypes found.

  • Identify any cases where an abstract mapping should be used and not implementation. eg. mapping for Map and not ConcurrentHashMap. Locale, Timezone
  • Identify and use consistent mapping for Dates, Instant etc.
  • Handle Generic collection types properly e.g. Set, List<>, especially with deserialization of generic types without using the Implementation Class name in the XML.
  • Identify any fields being persisted currently that should be transient and not stored in the Serialized XML. (PushPublisherConfig has caused some issues here with dependencyProcessor )
  • Identify and document any custom classes we Serialize/Deserialize that are not root classes below and are only used within other classes. e.g. (PublishingEndPoint in PushPublisherConfig)

Bundler Util Top Level Classes

  • PublisherConfig extended by PushPublisherConfig
  • CategoryWrapper
  • ContainerWrapper
  • PushContentWrapper
  • PushContentWorkflowWrapper
  • FileAssetWrapper
  • FolderWrapper
  • HostWrapper
  • HTMLPageAsContentWrapper
  • LanguageWrapper
  • LinkWrapper
  • RelationshipWrapper
  • RuleWrapper
  • StructureWrapper
  • TemplateWrapper
  • URLMapWrapper
  • UserWrapper
  • WorkflowWrapper

XmlSerializerUtil Top-level classes and classes using them

  • ContainerWrapper ( ContainerHandler )
  • ContentWrapper ( ContentHandler,ContentHandlerTest )
  • PushContentWorkflowWrapper ( ContentWorkflowHandler )
  • FolderWrapper (FolderHandler)
  • LanguageWrapper (LanguageHandler)
  • LinkWrapper (LinkHandler)
  • CategoryWrapper (PushCategoryUtil)
  • RelationshipWrapper (RelationshipHandler)
  • RuleWrapper(RuleHandler)
  • StructuredWrapper(StructuredHandler)
  • TemplateWrapper(TemplateHandler)
  • UserWrapper(UserHandler)
  • WorkflowWrapper(WorkflowHandler, SystemActionWorkflowActionMappingTest)
  • SystemActionWorkflowActionMapping (SystemActionWorkflowActionMappingTest)
  • PublishAuditHistory (PublishAuditHistory-self)
  • Contentlet (ESContentlet)

Custom concat Serialization of maps using Xstream

  • ContentResource ( Refactor code combining object map to xml and adding of wrapper through string concatenation use Jackson)

  • TestResource ( Refactor code combining object map to xml and adding of wrapper through string concatenation use Jackson)

  • FixTasks: These all use the same code to serialize a field called modifiedData a simple Map<String,String> Firstly Provide a util method for this mapping of map to XML so details of implementing library are not required. Just use Jackson to serialize.

    • FixTask00001CheckAssetsMissingIdentifiers.java
    • FixTask00003CheckContainersInconsistencies.java
    • FixTask00006CheckLinksInconsistencies.java
    • FixTask00007CheckTemplatesInconsistencies.java
    • FixTask00008CheckTreeInconsistencies.java
    • FixTask00009CheckContentletsInexistentInodes.java
    • FixTask00011RenameHostInFieldVariableName.java
    • FixTask00012UpdateAssetsHosts.java
    • FixTask00020DeleteOrphanedIdentifiers.java
    • FixTask00030DeleteOrphanedAssets.java
    • FixTask00050FixInodesWithoutContentlets.java
    • FixTask00060FixAssetType.java
    • FixTask00080DeleteOrphanedContentTypeFields.java
    • FixTask00090RecreateMissingFoldersInParentPath.java
    • FixTask00095DeleteOrphanRelationships.java

Tasks

Preview Give feedback
@nollymar nollymar moved this from New to Next 1-3 Sprints in dotCMS - Product Planning Mar 25, 2024
@nollymar nollymar moved this from Next 1-3 Sprints to Future in dotCMS - Product Planning Mar 25, 2024
@spbolton spbolton changed the title Pre-J21 Replace XStream with Jackson for XML Object Mapping. Replace XStream with Jackson for XML Object Mapping. Jun 3, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
Status: Future
Development

No branches or pull requests

1 participant