#708: HibernateProxyHelper.java

projectforge-business/src/main/java/org/projectforge/framework/persistence/xstream/HibernateProxyHelper.java Java utility — static helper that unwraps Hibernate proxy objects to their underlying entity instances, projectforge-business/src/main/java/org/projectforge/framework/persistence/xstream/HibernateProxyHelper.java 49 lines · 13 code · 33 comments · 3 blank
A small static utility class providing a single generic method get(T object) that detects whether an object is a HibernateProxy and, if so, unwraps it to the real entity via getHibernateLazyInitializer().getImplementation(). If the object is not a proxy, it returns the object unchanged. This is the simplest and most reusable proxy-unwrapping utility in the XStream+Hibernate bridge layer — used by ProxyIdRefMarshaller for ID-based reference tracking and available for any code that needs to inspect the real object behind a proxy wrapper.

Architecture

Class Design

HibernateProxyHelper is a pure utility class with a single public static generic method. It has no state, no dependencies (beyond org.hibernate.proxy.HibernateProxy), and no instance methods. The generic type parameter <T> preserves the compile-time type through the unwrap operation, so callers don't need to cast.

get(T object) Method

public static <T> T get(T object) {
    if (object instanceof HibernateProxy) {
        HibernateProxy proxy = (HibernateProxy) object;
        return (T) proxy.getHibernateLazyInitializer().getImplementation();
    }
    return object;
}

The logic is straightforward:

  1. Proxy check: Uses instanceof HibernateProxy — the standard way to detect Hibernate proxies, since all Hibernate-generated proxies implement this interface.
  2. Unwrap: Calls getHibernateLazyInitializer().getImplementation() which forces proxy initialization (triggers lazy loading) and returns the real entity.
  3. Identity return: If not a proxy, returns the same object reference — a no-op pass-through.
The getImplementation() call forces proxy initialization. If the entity has not been loaded from the database, this triggers a SQL query. Callers must ensure an active Hibernate session is available, or handle the potential LazyInitializationException.

Integration Points

Relationship to Other Proxy Handling

ClassApproachContext
HibernateProxyHelper (this class)Static utility method get()General-purpose unwrap for any code
HibernateProxyConverterXStream converter that intercepts before reflection serializationIntegrated into XStream converter chain
HibernateProxyXPathMarshallerUnwraps proxies before XPath reference trackingIntegrated into XStream marshalling strategy
HibernateMapperResolves proxy's real class name for XML element namingIntegrated into XStream mapper chain

Each of these solves the proxy problem at a different layer of the XStream architecture. HibernateProxyHelper is the lowest-level, most reusable building block.

Design Decisions & Gotchas

Git History

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