XStreamMarshallingStrategy.javaReferenceByXPathMarshallingStrategy to serve as the top-level plumbing that connects the Hibernate proxy-aware marshaller to XStream's serialization engine. This is the strategy class that XStream is configured to use — it overrides the factory method createMarshallingContext() to replace the default XPath marshaller with HibernateProxyXPathMarshaller, injecting Hibernate proxy awareness into every XStream serialization operation. This is the single configuration point that makes the entire XStream+Hibernate bridge layer operational. Without this strategy, none of the converter, mapper, or marshaller classes in this package would be activated during XStream serialization.MarshallingStrategy (interface)
└── AbstractTreeMarshallingStrategy
├── ReferenceByXPathMarshallingStrategy (XPath-based circular reference handling)
│ └── XStreamMarshallingStrategy (this class — swaps in HibernateProxyXPathMarshaller)
└── ReferenceByIdMarshallingStrategy (ID/IDREF-based circular reference handling)
└── ProxyIdRefMarshallingStrategy (#709 — swaps in ProxyIdRefMarshaller)
public XStreamMarshallingStrategy(int mode) {
super(mode);
}
Accepts an XPath reference mode constant (RELATIVE, ABSOLUTE, SINGLE_NODE, etc.) and passes it to the superclass. The mode controls how XPath expressions are generated for back-references in circular entity graphs.
@Override
protected TreeMarshaller createMarshallingContext(
HierarchicalStreamWriter writer,
ConverterLookup converterLookup,
Mapper mapper)
{
return new HibernateProxyXPathMarshaller(writer, converterLookup, mapper, RELATIVE);
}
This is the single overridden method — a textbook Template Method pattern. The superclass ReferenceByXPathMarshallingStrategy calls createMarshallingContext() whenever it needs a TreeMarshaller to serialize an object graph. Instead of returning the default ReferenceByXPathMarshaller, this override returns a HibernateProxyXPathMarshaller instance.
mode parameter, the createMarshallingContext() override hardcodes RELATIVE rather than using the instance's mode. This means the constructor parameter is effectively ignored for marshaller creation. If a different XPath mode were needed, this class would need modification or a subclass with a different override.xstream.setMarshallingStrategy(new XStreamMarshallingStrategy(ReferenceByXPathMarshallingStrategy.RELATIVE)). This is typically done once during application startup when configuring the XStream instance for XML export.XStreamMarshallingStrategy (this class) | ProxyIdRefMarshallingStrategy | |
|---|---|---|
| Reference mechanism | XPath expressions (e.g., reference="../../task") | ID/IDREF attributes (e.g., id="1", reference="1") |
| Depends on document structure | Yes — XPath paths break if XML structure changes | No — IDs are document-structure independent |
| Human readability | Lower — XPath paths are structural, not semantic | Higher — sequential numeric IDs are easy to follow |
| Proxy unwrapping | In marshaller only (HibernateProxyXPathMarshaller) | In marshaller (ProxyIdRefMarshaller) + CGLIB stripping |
| Spring CGLIB support | No | Yes (strips Enhancer proxies) |
When XStream serializes a JPA entity graph in ProjectForge, the following pipeline executes:
XStreamMarshallingStrategy (this class) is invoked to create a marshalling context.convertAnother(), which unwraps HibernateProxy instances before delegating to XStream's reference tracking.PersistentCollection, HibernateCollectionConverter forces initialization and delegates to the appropriate JDK collection converter.HibernateProxy, HibernateProxyConverter unwraps it to the real entity before serialization.TreeMarshaller implementation. This is the canonical XStream extension point for custom marshalling behavior.RELATIVE in createMarshallingContext() means the constructor's mode parameter is vestigial. This is likely an oversight or a deliberate decision to ensure proxy-aware marshalling always uses relative XPaths regardless of what callers pass. In practice, RELATIVE is the most robust mode for entity graphs because entity hierarchies can shift during refactoring.868d6abb7 2025 -> 2026 63081666f Source file headers: 2024-> 2025. b6092df09 Copyright 2023 -> 2024 ab45d51fa Copyright 2001-2022 -> 2001-2023. 5f7ef41b8 Copyright 2021 -> 2022 ceb63e8a1 Source code header: (C) 2001-2021. 7c79f1922 Copyright of source header -> 2020. dd5ca38ac CopyRight of all java file-header updated or created. 9ebb88522 Initial commit