HibernateProxyXPathMarshaller.javaReferenceByXPathMarshaller to intercept the convertAnother() method — the central dispatch point where XStream traverses from one object to another during XML serialization of an entity graph. Before delegating to the parent class for XPath-based reference tracking, it unwraps any HibernateProxy to its real entity implementation. This ensures XStream's reference tracking operates on the real entity identity rather than proxy identity, preventing duplicate serialization of the same entity appearing through both direct and proxy references. This is a critical component for serializing JPA entity graphs that contain bidirectional associations with lazy loading.HibernateProxyXPathMarshaller extends com.thoughtworks.xstream.core.ReferenceByXPathMarshaller, which itself extends AbstractReferenceMarshaller (which extends TreeMarshaller). The XStream marshalling hierarchy is:
TreeMarshaller
└── AbstractReferenceMarshaller (adds object reference tracking)
├── ReferenceByXPathMarshaller (uses XPath expressions for references)
│ └── HibernateProxyXPathMarshaller (this class — adds proxy unwrapping)
└── ReferenceByIdMarshaller (uses ID/IDREF attributes for references)
└── ProxyIdRefMarshaller (#708 — alternative ID-based strategy)
HibernateProxyXPathMarshaller and ProxyIdRefMarshaller solve the same problem (proxy-aware marshalling) but use different XStream reference modes: XPath vs. ID/IDREF. The choice between them is made by XStreamMarshallingStrategy (uses XPath) and the ProxyIdRefMarshallingStrategy (uses ID/IDREF).Takes four parameters matching the ReferenceByXPathMarshaller constructor signature:
| Parameter | Type | Purpose |
|---|---|---|
writer | HierarchicalStreamWriter | XML output writer |
converterLookup | ConverterLookup | XStream converter registry |
mapper | Mapper | XStream class name mapper |
mode | int | XPath reference mode (RELATIVE, ABSOLUTE, etc.) |
This is the only overridden method — the single point where proxy unwrapping is injected into the XPath marshalling flow:
HibernateProxy.class.isAssignableFrom(item.getClass()). Uses isAssignableFrom rather than instanceof because item may be passed in a non-null context where the static type is broader.((HibernateProxy) item).getHibernateLazyInitializer().getImplementation() to get the real entity. This triggers lazy loading if the proxy hasn't been initialized.toConvert object to super.convertAnother(toConvert, converter), which handles XPath reference tracking and XML writing.XStream's ReferenceByXPathMarshaller handles circular references by writing XPath expressions (e.g., <task reference="../../../task">) instead of serializing the same object twice. The mode parameter controls whether these XPath expressions are relative or absolute. Relative paths make the XML more resilient to structural changes and are generally preferred for document-oriented XML.
RELATIVE mode. This is the only place HibernateProxyXPathMarshaller is instantiated — the strategy acts as a factory.convertAnother() for each object reference it encounters.// http://jira.codehaus.org/browse/XSTR-226 links to the original Codehaus JIRA issue that motivated this class — a known limitation in XStream where Hibernate proxies broke the reference tracking mechanism. This class is the fix for that issue.getImplementation() forces initialization — a database hit for lazy proxies.mode is not configurable per-call — it's fixed at construction time by the strategy. XStreamMarshallingStrategy always passes RELATIVE. If absolute XPaths were needed, a new strategy class would be required.HibernateProxyXPathMarshaller has package visibility (public class but the package is internal). It's exposed publicly only to allow the strategy class to construct it.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. 32f634b88 Optimize imports dd5ca38ac CopyRight of all java file-header updated or created. 9ebb88522 Initial commit