Get HibernateProxy at one object

I work at a spring boot API. It's the first time I get this problem.

I'm loading different company objects via the findById function with the repository. All company objects are loaded correctly, expect one. This one loads a handler property of type JavassistLazyInitalizer with it. The remaining properties are all on the default value. In the handler object in the target node is the object loaded correctly how I want it.

So I found out that this is a type of hibernate lazy loading, because when I want to access a property with a getter, it works correctly.

My problem is, that I want to serialize the object with gson at the end and I get this error during serilazition process:

Attempted to serialize java.lang.Class: org.hibernate.proxy.HibernateProxy. Forgot to register a type adapter?

I understand why this error occurs. But I don't understand why only one of the different company objects is loaded lazy(or is a hibernateProxy). So what is the smartest way to avoid the hibernateProxy, respectively to serialize the object?

Thanks for your answers :)

2 answers

  • answered 2018-11-14 12:40 v.ladynev

    The reason can be that you do some operations with correctly loaded objects. For example, if you call any method (not necessary getter) of a loaded persistent class, Hibernate initializes all proxies.

    And you do nothing with an object that is loaded incorrectly.

  • answered 2018-11-14 13:51 Amannti

    This Adapter is my solution.

    public class HibernateProxyTypeAdapter extends TypeAdapter<HibernateProxy> {
    
    public static final TypeAdapterFactory FACTORY = new TypeAdapterFactory() {
        @Override
        @SuppressWarnings("unchecked")
        public <T> TypeAdapter<T> create(Gson gson, TypeToken<T> type) {
            return (HibernateProxy.class.isAssignableFrom(type.getRawType()) ? (TypeAdapter<T>) new HibernateProxyTypeAdapter(gson) : null);
        }
    };
    private final Gson context;
    
    private HibernateProxyTypeAdapter(Gson context) {
        this.context = context;
    }
    
    @Override
    public HibernateProxy read(JsonReader in) throws IOException {
        throw new UnsupportedOperationException("Not supported");
    }
    
    @SuppressWarnings({"rawtypes", "unchecked"})
    @Override
    public void write(JsonWriter out, HibernateProxy value) throws IOException {
        if (value == null) {
            out.nullValue();
            return;
        }
        // Retrieve the original (not proxy) class
        Class<?> baseType = Hibernate.getClass(value);
        // Get the TypeAdapter of the original class, to delegate the serialization
        TypeAdapter delegate = context.getAdapter(TypeToken.get(baseType));
        // Get a filled instance of the original class
        Object unproxiedValue = ((HibernateProxy) value).getHibernateLazyInitializer()
                .getImplementation();
        // Serialize the value
        delegate.write(out, unproxiedValue);
    }
    

    }

    You have to add this to your gsonBuilder.

    new GsonBuilder().registerTypeAdapterFactory(HibernateProxyTypeAdapter.FACTORY).create();
    

    Answer found on this question Could not serialize object cause of HibernateProxy