54

I am getting the following error response from the server.

HTTP Status 500 -

type Exception report

message

descriptionThe server encountered an internal error () that prevented it from fulfilling this request.

exception

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

root cause

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

From Java debugger:

org.hibernate.proxy.pojo.javassist.JavassistLazyInitializer@7632012e

I am using Gson to convert my Java objects to JSON. Below I have pasted some of my code.

This is my resource:

@Stateless
@LocalBean
@Path("/autos")
@Produces(MediaType.APPLICATION_JSON)
public class AutoResource {

    @EJB
    private CarAssembler warehouse;
    @Context
    private UriInfo uriInfo;

    @GET
    public Response allAutos() {
        // Building a context, lots of code...
        // Creating a Gson instance and configures it...

        final Auto auto = warehouse.list(context);
        final String autoJson = gson.toJson(auto);

        return Response.ok(autoJson).build();
    }
}

The CarAssembler is just an service which invokes a repository. I have not pasted the code of the service here.

Repository:

@Override
public Question findById(final int id, final FetchType fetchType) {

    final Auto question = getEntityManager().find(Auto.class, id);

    if (fetchType == FetchType.LAZY) {
        return auto;
    }

    Hibernate.initialize(auto.getManufacturer());
    Hibernate.initialize(auto.getAssemblyHouse());

    return auto;
}

As you see, I provide both lazy and eager loading of objects. I use Hibernate.initialize to eager fetch JPA associations. However, the question is how I can fix the proxy error I am getting. Why come there is only AssemblyHouse that is still attached to JavaAssist, while Manufacturer is not (I have seen the type in Java Debugger). How do I know when to unproxy objects? Should I unproxy all associations this auto may have? And in which layer of my code? Does it affect the performance of my application when I unproxy? Are there other solutions? I see from the error message that I can make a type adapter. Yes, I could but then I have to do that for all domain objects to be sure that conversion is done correctly. Maybe other objects in my domain starts failing when I try to convert it into JSON representation too, but I don't know when or why. Is it just luck that the other objects are fine?

This is the way I am unproxing objects, but I have not implemented it yet, because I don't know if this is good or bad, and in what layer to do this, and when I should do it. Should I unproxy objects all the time?

public class HibernateUtilities {

    public static <T> T unproxy(T proxy) {
        if (proxy == null) {
            return null;
        }

        if (proxy instanceof HibernateProxy) {
            Hibernate.initialize(proxy);

            HibernateProxy hibernateProxy = (HibernateProxy) proxy;
            T unproxiedObject = (T) hibernateProxy.getHibernateLazyInitializer().getImplementation();

            return unproxiedObject;
        }

        return proxy;
    }
}

Stacktrace as requested:

[#|2012-11-22T17:17:13.285+0100|WARNING|glassfish3.1.2|javax.enterprise.system.container.web.com.sun.enterprise.web|_ThreadID=71;_ThreadName=Thread-8;|StandardWrapperValve[javax.ws.rs.core.Application]:
PWC1406: Servlet.service() for servlet javax.ws.rs.core.Application
threw exception java.lang.UnsupportedOperationException: Attempted to
serialize java.lang.Class: org.hibernate.proxy.HibernateProxy. Forgot
to register a type adapter?
    at com.google.gson.internal.bind.TypeAdapters$1.write(TypeAdapters.java:64)
    at com.google.gson.internal.bind.TypeAdapters$1.write(TypeAdapters.java:61)
    at com.google.gson.internal.bind.TypeAdapterRuntimeTypeWrapper.write(TypeAdapterRuntimeTypeWrapper.java:68)
    at com.google.gson.internal.bind.ArrayTypeAdapter.write(ArrayTypeAdapter.java:93)
    at com.google.gson.internal.bind.TypeAdapterRuntimeTypeWrapper.write(TypeAdapterRuntimeTypeWrapper.java:68)
    at com.google.gson.internal.bind.ReflectiveTypeAdapterFactory$1.write(ReflectiveTypeAdapterFactory.java:89)
    at com.google.gson.internal.bind.ReflectiveTypeAdapterFactory$Adapter.write(ReflectiveTypeAdapterFactory.java:195)
    at com.google.gson.internal.bind.TypeAdapterRuntimeTypeWrapper.write(TypeAdapterRuntimeTypeWrapper.java:68)
    at com.google.gson.internal.bind.ReflectiveTypeAdapterFactory$1.write(ReflectiveTypeAdapterFactory.java:89)
    at com.google.gson.internal.bind.ReflectiveTypeAdapterFactory$Adapter.write(ReflectiveTypeAdapterFactory.java:195)
    at com.google.gson.internal.bind.TypeAdapterRuntimeTypeWrapper.write(TypeAdapterRuntimeTypeWrapper.java:68)
    at com.google.gson.internal.bind.ReflectiveTypeAdapterFactory$1.write(ReflectiveTypeAdapterFactory.java:89)
    at com.google.gson.internal.bind.ReflectiveTypeAdapterFactory$Adapter.write(ReflectiveTypeAdapterFactory.java:195)
    at com.google.gson.internal.bind.TypeAdapterRuntimeTypeWrapper.write(TypeAdapterRuntimeTypeWrapper.java:68)
    at com.google.gson.internal.bind.CollectionTypeAdapterFactory$Adapter.write(CollectionTypeAdapterFactory.java:96)
    at com.google.gson.internal.bind.CollectionTypeAdapterFactory$Adapter.write(CollectionTypeAdapterFactory.java:60)
    at com.google.gson.internal.bind.TypeAdapterRuntimeTypeWrapper.write(TypeAdapterRuntimeTypeWrapper.java:68)
    at com.google.gson.internal.bind.ReflectiveTypeAdapterFactory$1.write(ReflectiveTypeAdapterFactory.java:89)
    at com.google.gson.internal.bind.ReflectiveTypeAdapterFactory$Adapter.write(ReflectiveTypeAdapterFactory.java:195)
    at com.google.gson.Gson.toJson(Gson.java:586)
    at com.google.gson.Gson.toJson(Gson.java:565)
    at com.google.gson.Gson.toJson(Gson.java:520)
    at com.myapp.AutoResource.produceAuto(AutoResource.java:48)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:601)
    at org.glassfish.ejb.security.application.EJBSecurityManager.runMethod(EJBSecurityManager.java:1052)
    at org.glassfish.ejb.security.application.EJBSecurityManager.invoke(EJBSecurityManager.java:1124)
    at com.sun.ejb.containers.BaseContainer.invokeBeanMethod(BaseContainer.java:5388)
    at com.sun.ejb.EjbInvocation.invokeBeanMethod(EjbInvocation.java:619)
    at com.sun.ejb.containers.interceptors.AroundInvokeChainImpl.invokeNext(InterceptorManager.java:800)
    at com.sun.ejb.EjbInvocation.proceed(EjbInvocation.java:571)
    at com.sun.ejb.containers.interceptors.SystemInterceptorProxy.doAround(SystemInterceptorProxy.java:162)
    at com.sun.ejb.containers.interceptors.SystemInterceptorProxy.aroundInvoke(SystemInterceptorProxy.java:144)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:601)
    at com.sun.ejb.containers.interceptors.AroundInvokeInterceptor.intercept(InterceptorManager.java:861)
    at com.sun.ejb.containers.interceptors.AroundInvokeChainImpl.invokeNext(InterceptorManager.java:800)
    at com.sun.ejb.containers.interceptors.InterceptorManager.intercept(InterceptorManager.java:370)
    at com.sun.ejb.containers.BaseContainer.__intercept(BaseContainer.java:5360)
    at com.sun.ejb.containers.BaseContainer.intercept(BaseContainer.java:5348)
    at com.sun.ejb.containers.EJBLocalObjectInvocationHandler.invoke(EJBLocalObjectInvocationHandler.java:214)
    at com.sun.ejb.containers.EJBLocalObjectInvocationHandlerDelegate.invoke(EJBLocalObjectInvocationHandlerDelegate.java:89)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:601)
    at com.sun.jersey.spi.container.JavaMethodInvokerFactory$1.invoke(JavaMethodInvokerFactory.java:60)
    at com.sun.jersey.server.impl.model.method.dispatch.AbstractResourceMethodDispatchProvider$ResponseOutInvoker._dispatch(AbstractResourceMethodDispatchProvider.java:205)
    at com.sun.jersey.server.impl.model.method.dispatch.ResourceJavaMethodDispatcher.dispatch(ResourceJavaMethodDispatcher.java:75)
    at com.sun.jersey.server.impl.uri.rules.HttpMethodRule.accept(HttpMethodRule.java:288)
    at com.sun.jersey.server.impl.uri.rules.ResourceClassRule.accept(ResourceClassRule.java:108)
    at com.sun.jersey.server.impl.uri.rules.RightHandPathRule.accept(RightHandPathRule.java:147)
    at com.sun.jersey.server.impl.uri.rules.RootResourceClassesRule.accept(RootResourceClassesRule.java:84)
    at com.sun.jersey.server.impl.application.WebApplicationImpl._handleRequest(WebApplicationImpl.java:1469)
    at com.sun.jersey.server.impl.application.WebApplicationImpl._handleRequest(WebApplicationImpl.java:1400)
    at com.sun.jersey.server.impl.application.WebApplicationImpl.handleRequest(WebApplicationImpl.java:1349)
    at com.sun.jersey.server.impl.application.WebApplicationImpl.handleRequest(WebApplicationImpl.java:1339)
    at com.sun.jersey.spi.container.servlet.WebComponent.service(WebComponent.java:416)
    at com.sun.jersey.spi.container.servlet.ServletContainer.service(ServletContainer.java:537)
    at com.sun.jersey.spi.container.servlet.ServletContainer.service(ServletContainer.java:708)
    at javax.servlet.http.HttpServlet.service(HttpServlet.java:770)
    at org.apache.catalina.core.StandardWrapper.service(StandardWrapper.java:1550)
    at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:281)
    at org.apache.catalina.core.StandardContextValve.__invoke(StandardContextValve.java:175)
    at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java)
    at org.apache.catalina.core.StandardPipeline.doInvoke(StandardPipeline.java:655)
    at org.apache.catalina.core.StandardPipeline.invoke(StandardPipeline.java:595)
    at org.apache.catalina.core.StandardHostValve.__invoke(StandardHostValve.java:161)
    at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java)
    at org.apache.catalina.connector.CoyoteAdapter.doService(CoyoteAdapter.java:331)
    at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:231)
    at com.sun.enterprise.v3.services.impl.ContainerMapper$AdapterCallable.call(ContainerMapper.java:317)
    at com.sun.enterprise.v3.services.impl.ContainerMapper.service(ContainerMapper.java:195)
    at com.sun.grizzly.http.ProcessorTask.invokeAdapter(ProcessorTask.java:860)
    at com.sun.grizzly.http.ProcessorTask.doProcess(ProcessorTask.java:757)
    at com.sun.grizzly.http.ProcessorTask.process(ProcessorTask.java:1056)
    at com.sun.grizzly.http.DefaultProtocolFilter.execute(DefaultProtocolFilter.java:229)
    at com.sun.grizzly.DefaultProtocolChain.executeProtocolFilter(DefaultProtocolChain.java:137)
    at com.sun.grizzly.DefaultProtocolChain.execute(DefaultProtocolChain.java:104)
    at com.sun.grizzly.DefaultProtocolChain.execute(DefaultProtocolChain.java:90)
    at com.sun.grizzly.http.HttpProtocolChain.execute(HttpProtocolChain.java:79)
    at com.sun.grizzly.ProtocolChainContextTask.doCall(ProtocolChainContextTask.java:54)
    at com.sun.grizzly.SelectionKeyContextTask.call(SelectionKeyContextTask.java:59)
    at com.sun.grizzly.ContextTask.run(ContextTask.java:71)
    at com.sun.grizzly.util.AbstractThreadPool$Worker.doWork(AbstractThreadPool.java:532)
    at com.sun.grizzly.util.AbstractThreadPool$Worker.run(AbstractThreadPool.java:513)
    at java.lang.Thread.run(Thread.java:722) |#]
Luke Woodward
  • 56,377
  • 16
  • 76
  • 100
Andreas
  • 2,332
  • 1
  • 16
  • 20
  • 1
    Do you remember when you were learning how to build applications, and someone explained to you the idea of having layers. This is what happens when you mix presentation, business and database logic in the same class (those annotations leak logic into your classes, they are not as transparent as you might think) – Augusto Nov 21 '12 at 22:39
  • 2
    @Augusto Do you think the code snippets are all from the same class? – Andreas Nov 22 '12 at 12:25
  • I'm not totally convinced your problem is on `Manufacturer`. Try serializing with `final String autoJson = gson.toJson(auto, Auto.class);` If it does not work, can you post the stack trace? – Flavio Nov 22 '12 at 15:51
  • It is the only class that is of type HibernateProxy in debugger, and that is the problem. It also works great when I exclude this property from serialization. – Andreas Nov 22 '12 at 16:07
  • From the stack trace it appears you have some trouble in an array, lower down in the hierarchy. Can you verify what it is? – Flavio Nov 22 '12 at 16:28
  • To be honest, I do not know what that has to do with it. – Andreas Nov 22 '12 at 17:58

6 Answers6

92

You can do without manually unproxying everything by using a custom TypeAdapter. Something along these lines:

/**
 * This TypeAdapter unproxies Hibernate proxied objects, and serializes them
 * through the registered (or default) TypeAdapter of the base class.
 */
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);
    }
}

To use it you must first register it:

GsonBuilder b = new GsonBuilder();
...
b.registerTypeAdapterFactory(HibernateProxyTypeAdapter.FACTORY);
...
Gson gson = b.create();

Notice that this will recursively initialize every proxy you have in the object hierarchy; since however you have to serialize the whole data, you should have done that anyway.

How does this work?

GSON contains a number of TypeAdapterFactory implementations, for various types (primitive types, common types like String or Date, lists, arrays...). Each factory is asked if it is able to serialize a certain Java type (the parameter to create is a TypeToken instead of a Class in order to capture possible information about generic types, which Class does not have). If the factory is able to serialize/deserialize a type, it responds with a TypeAdapter instance; otherwise it responds with null.

HibernateProxyTypeAdapter.FACTORY verifies whether type implements HibernateProxy; in that case, it returns an instance of HibernateProxyTypeAdapter for serialization. The write method is called when an actual object has to be serialized; the adapter extracts the original type of the underlying object, and asks GSON for the standard TypeAdapter for the original type, which generally is a ReflectiveTypeAdapter.

Then it retrieves an instance of the original class, instead of directly using the proxy. This is necessary because ReflectiveTypeAdapter accesses directly to fields, instead of using getters; accessing to the fields of a proxied object does not work, and is a classical Hibernate pitfall.

As a possible performance improvement, the delegate TypeAdapter should be acquired in the create method. I found out that calling getSuperclass() on the proxy Class appears to yield the original base class. The code can then become:

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((TypeAdapter)gson.getAdapter(TypeToken.get(type.getRawType().getSuperclass()))) 
     : null);
    }
};
private final TypeAdapter<Object> delegate;

private HibernateProxyTypeAdapter(TypeAdapter<Object> delegate) {
    this.delegate = delegate;
}

@SuppressWarnings({"rawtypes", "unchecked"})
@Override
public void write(JsonWriter out, HibernateProxy value) throws IOException {
    if (value == null) {
        out.nullValue();
        return;
    }
    delegate.write(out, ((HibernateProxy) value).getHibernateLazyInitializer()
            .getImplementation());
}
Flavio
  • 11,228
  • 2
  • 30
  • 36
  • I had the time to test and fix it, try again with the current code. – Flavio Nov 24 '12 at 11:47
  • AWESOME! Would you mind explaining some of your code and comment? This adapter will only trigger when the object that is going to be serialized of type HibernateProxy right? Does gson find a matching typeadapter for each object it is going to serialize? – Andreas Nov 24 '12 at 16:00
  • I added some comments in the code, and a (somewhat lengthy) explanation! – Flavio Nov 24 '12 at 21:07
  • 2
    This is quite an old answer, but just thought I'd comment. This code is resulting in stack overflow exceptions when I pass single objects. It works fine for serializing `List` types. – christopher Apr 09 '14 at 11:28
  • where should i convert the entity to json? in my DAO? – Ker p pag Aug 07 '14 at 07:14
  • @Kerppag mainly you may have the need to convert the jpa entities in the controller if you are creating restful services – Shady Mohamed Sherif Jan 06 '15 at 03:35
  • 2
    @Flavio thanks for your answer but it gives me stack overflow! – Shady Mohamed Sherif Jan 06 '15 at 03:43
  • I quite forgot what this is about by now ^^ However maybe you have a structure with cycles? That is a parent object which points to a child object, and the child pointing back to the parent? – Flavio Jan 06 '15 at 21:08
  • Thanks @Flavio !!!! For those who are having a stack overflow: check if you have within the serializable class a bidirectional relation. When I made a restful web service a year ago, I had come up with a stack overflow when parsing classes with bidirectional associations. These cycles are causing the overflow. – russellhoff Feb 18 '15 at 15:45
  • Giving `java.lang.StackOverflowError` – Madushan Perera Jan 21 '16 at 09:16
  • Thank you very much for such a clear concise answer. Very much appreciated. – Zoidberg May 08 '18 at 14:19
4

Seeing as though you mentioned that the error persists with eager loading, then the issue likely is not so much Hibernate, but possibly on the GSON implementation. I think you will need a Type when creating your JSON, not sure if it was registered, but perhaps something like this:

public String autosToJson(Auto autos) {  
    GsonBuilder gsonBuilder = new GsonBuilder();
    Gson gson = gsonBuilder.registerTypeAdapter(Auto.class, new AutoAdapter()).create();
    return gson.toJson(autos);
}   

Then just create an AdapterClass, for example:

public class AutoAdapter implements JsonSerializer<Auto> {
  @Override
  public JsonElement serialize(Auto auto, Type type, JsonSerializationContext jsc) {
    JsonObject jsonObject = new JsonObject();
    jsonObject.addProperty("auto_id", auto.getId());
    jsonObject.addProperty("auto_name", auto.getAutoName());
    jsonObject.addProperty("auto__manufacture_date", auto.getManufactureDate().toString());
    return jsonObject;      
  }
}
msj121
  • 2,702
  • 2
  • 25
  • 46
  • The error is that event though invoking `Hibernate.initialize(auto.getManufacturer());`, the Manufacturer object returned by the getter is still a `HibernateProxy`. I have seen this while debugging the application. However the other object is not a `HibernateProxy`. – Andreas Nov 22 '12 at 14:13
  • The fact that I can add properties individually and transform them when needed is what I was looking for. Thank you! – paralaks Jun 20 '17 at 17:23
2

In usual cases you don't want your domain objects to be exposed as XML/JSON via services, often you need to create a DTO because your Entity does not fit the needs of your consumer. And even if it does now, after internal refactoring of the database, it won't fit tomorrow. So my advice would be to create DTOs right now if you got into such a trouble. BTW, you can create those DTOs even on the Hibernate level by using Result Transformers or creating Views and mapping Hibernate entities onto these Views.

Another trick would be to use Dozer in order to copy needed fields into the other class (which actually is the same class, but without proxy).

And a note: you're using Gson, which access your fields, instead of accessors, this makes it impossible to work with Hibernate proxy because it will try to access the fields of proxy itself which always are null.

Stanislav Bashkyrtsev
  • 11,403
  • 7
  • 33
  • 38
1

Yes, you can just unproxy all the time, if it has a HibernateProxy (which won't serialize) it will be gone and replaced with the actual underlying implementation, or it will leave the class as is and give you an implementation. I think your solution should work fine. Mind you I don't really use Hibernate much, but it does make sense to me.

On the other hand you might be trusting Hibernate some more, but a simpler method might be:

Hibernate.getClass(obj);

This solution should not give you implemented/initialized classes, just the class, or that function should be offered by:

HibernateProxyHelper.getClassWithoutInitializingProxy(superClass)

I believe the latter might return the super class though, so you might start with Hibernate.getClass(obj);

also:

public static <T> T initializeAndUnproxy(T entity) {
    if (entity == null) {
        throw new 
           NullPointerException("Entity passed for initialization is null");
    }

    Hibernate.initialize(entity);
    if (entity instanceof HibernateProxy) {
        entity = (T) ((HibernateProxy) entity).getHibernateLazyInitializer()
                .getImplementation();
    }
    return entity;
}

The above code was borrowed from: Converting Hibernate proxy to real object the variable names from it are probably better, as they don't imply the entity is always a proxy. Also it will throw an exception to warn you, but that is up to you whether you want the exception or not.

Of course you can also get rid of lazy load, but I don't think thats the best solution.

Community
  • 1
  • 1
msj121
  • 2,702
  • 2
  • 25
  • 46
  • So, does unproxying objects cause massive performance problems for some reason? And should I be unproxying all objects in the repository all the time to prevent running into this issue? – Andreas Nov 21 '12 at 21:21
  • Its a good question, one definitely for Hibernate Staff. That being said, my opinion would be as follows: It depends, how many times do you need to serialize (ie: how often is it called). How many objects need to be instantiated (How many of your objects that are regularly serialized have proxies, lazyinit). The worst case scenario is that it is no worse than having all your objects instantiated when created. – msj121 Nov 21 '12 at 23:57
  • If you really need optimization you can return the Hibernate.getClass(obj), this will be a class object, not an instantiated one. – msj121 Nov 22 '12 at 00:33
  • Eager loading does not however seem to unproxy objects though, since I already use `Hibernate.initialize(..)`. – Andreas Nov 22 '12 at 12:24
0

I was experiencing this very problem when I bumped into this post, which pointed me in the right direction for my situation. I realized I didn't need to serialize the entire entity, specifically for the very reason that I has marked some fields to be lazy loaded. So I sought to find a way to skip these fields and ExclusionStrategy was magical. This seems to have fixed my issue

public class ExcludeProxiedFields implements ExclusionStrategy{

    @Override
    public boolean shouldSkipField(FieldAttributes fa) {
        return fa.getAnnotation(ManyToOne.class) != null ||
           fa.getAnnotation(OneToOne.class) != null  ||
           fa.getAnnotation(ManyToMany.class) != null  ||
           fa.getAnnotation(OneToMany.class) != null ;
    }

    @Override
    public boolean shouldSkipClass(Class<?> type) {
        return false;
    }   
}

Then I applied this class to the GsonBuilder like this:

Gson gson = new GsonBuilder().setExclusionStrategies(new ExcludeProxiedFields()).create();
mainas
  • 696
  • 1
  • 6
  • 13
0

Try parsing through ObjectMapper as

final Auto auto = warehouse.list(context);
final String autoJson = new ObjectMapper().writeValueAsString(auto);

return Response.ok(autoJson).build();