Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Gson deserialize json. java.lang.RuntimeException: Failed to invoke public com.derp.procedure.model.SkeletonElement() with no args] with root cause

It is my first time with json and java. I've check a lot of question/ post with the same error like mine. But haven't find anything usefull.

I've uderstood that I have to add no args constructor. I've maded, but it didnt helped me. Still the same error occur. It can work that way. I think that is related with quite complecated iheritance of mine code.

ERROR:

SEVERE: Servlet.service() for servlet [dispatcher] in context with path [/derp] threw exception [Request processing failed; nested exception is java.lang.RuntimeException: Failed to invoke public com.derp.procedure.model.SkeletonElement() with no args] with root cause java.lang.InstantiationException

StackTrace:

gru 19, 2014 8:27:50 PM org.apache.catalina.core.StandardWrapperValve invoke
SEVERE: Servlet.service() for servlet [dispatcher] in context with path [/derp] threw exception [Request processing failed; nested exception is java.lang.RuntimeException: Failed to invoke public com.derp.procedure.model.SkeletonElement() with no args] with root cause
java.lang.InstantiationException
    at sun.reflect.InstantiationExceptionConstructorAccessorImpl.newInstance(InstantiationExceptionConstructorAccessorImpl.java:48)
    at java.lang.reflect.Constructor.newInstance(Constructor.java:408)
    at com.google.gson.internal.ConstructorConstructor$3.construct(ConstructorConstructor.java:104)
    at com.google.gson.internal.bind.ReflectiveTypeAdapterFactory$Adapter.read(ReflectiveTypeAdapterFactory.java:186)
    at com.google.gson.internal.bind.TypeAdapterRuntimeTypeWrapper.read(TypeAdapterRuntimeTypeWrapper.java:40)
    at com.google.gson.internal.bind.CollectionTypeAdapterFactory$Adapter.read(CollectionTypeAdapterFactory.java:81)
    at com.google.gson.internal.bind.CollectionTypeAdapterFactory$Adapter.read(CollectionTypeAdapterFactory.java:60)
    at com.google.gson.Gson.fromJson(Gson.java:810)
    at com.google.gson.Gson.fromJson(Gson.java:775)
    at com.google.gson.Gson.fromJson(Gson.java:724)
    at com.derp.procedure.model.SkeletonElement.toObject(SkeletonElement.java:38)
    at com.derp.procedure.model.Skeleton.setSkeletonElements(Skeleton.java:53)
    at com.derp.procedure.controller.ProcedureController.elementsAssignmentSubmit(ProcedureController.java:81)
    at com.derp.procedure.controller.ProcedureController$$FastClassBySpringCGLIB$$35de90ba.invoke(<generated>)
    at org.springframework.cglib.proxy.MethodProxy.invoke(MethodProxy.java:204)
    at org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.invokeJoinpoint(CglibAopProxy.java:717)
    at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:157)
    at org.springframework.transaction.interceptor.TransactionInterceptor$1.proceedWithInvocation(TransactionInterceptor.java:98)
    at org.springframework.transaction.interceptor.TransactionAspectSupport.invokeWithinTransaction(TransactionAspectSupport.java:266)
    at org.springframework.transaction.interceptor.TransactionInterceptor.invoke(TransactionInterceptor.java:95)
    at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:179)
    at org.springframework.aop.framework.CglibAopProxy$DynamicAdvisedInterceptor.intercept(CglibAopProxy.java:653)
    at com.derp.procedure.controller.ProcedureController$$EnhancerBySpringCGLIB$$fe2945ed.elementsAssignmentSubmit(<generated>)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:483)
    at org.springframework.web.method.support.InvocableHandlerMethod.invoke(InvocableHandlerMethod.java:215)
    at org.springframework.web.method.support.InvocableHandlerMethod.invokeForRequest(InvocableHandlerMethod.java:132)
    at org.springframework.web.servlet.mvc.method.annotation.ServletInvocableHandlerMethod.invokeAndHandle(ServletInvocableHandlerMethod.java:104)
    at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.invokeHandleMethod(RequestMappingHandlerAdapter.java:781)
    at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.handleInternal(RequestMappingHandlerAdapter.java:721)
    at org.springframework.web.servlet.mvc.method.AbstractHandlerMethodAdapter.handle(AbstractHandlerMethodAdapter.java:83)
    at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:943)
    at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:877)
    at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:966)
    at org.springframework.web.servlet.FrameworkServlet.doPut(FrameworkServlet.java:879)
    at javax.servlet.http.HttpServlet.service(HttpServlet.java:647)
    at org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:842)
    at javax.servlet.http.HttpServlet.service(HttpServlet.java:725)
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:291)
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206)
    at org.springframework.web.filter.HiddenHttpMethodFilter.doFilterInternal(HiddenHttpMethodFilter.java:77)
    at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107)
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:239)
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206)
    at org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:52)
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:239)
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206)
    at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:219)
    at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:106)
    at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:503)
    at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:136)
    at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:79)
    at org.apache.catalina.valves.AbstractAccessLogValve.invoke(AbstractAccessLogValve.java:610)
    at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:88)
    at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:526)
    at org.apache.coyote.http11.AbstractHttp11Processor.process(AbstractHttp11Processor.java:1078)
    at org.apache.coyote.AbstractProtocol$AbstractConnectionHandler.process(AbstractProtocol.java:655)
    at org.apache.coyote.http11.Http11Protocol$Http11ConnectionHandler.process(Http11Protocol.java:146)
    at org.apache.tomcat.util.net.JIoEndpoint$SocketProcessor.run(JIoEndpoint.java:279)
    at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142)
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)
    at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61)
    at java.lang.Thread.run(Thread.java:745)

My java classes:

Generic model class that is extended:

package com.derp.generic.model;

import java.io.IOException;

import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.MappedSuperclass;
import javax.persistence.Transient;

import org.apache.commons.lang.builder.ToStringBuilder;
import org.apache.commons.lang.builder.ToStringStyle;
import org.codehaus.jackson.JsonGenerationException;
import org.codehaus.jackson.annotate.JsonMethod;
import org.codehaus.jackson.annotate.JsonAutoDetect.Visibility;
import org.codehaus.jackson.map.JsonMappingException;
import org.codehaus.jackson.map.ObjectMapper;

@MappedSuperclass
public abstract class GenericModel<T extends GenericModel<?>> {
    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    private Long id;


    public long getId() {return id;}
    public void setId(long id) {this.id = id;}

    public GenericModel() {
    }
    // a toString method that can be used in any class.
    // uses reflection to dynamically print java class field
    // values one line at a time.
    @Override
    public String toString() {
      return ToStringBuilder.reflectionToString(this, ToStringStyle.MULTI_LINE_STYLE);
    }
    public String toJson() {
        ObjectMapper jsonMapper = new ObjectMapper();
        try {
            return jsonMapper.writerWithDefaultPrettyPrinter().writeValueAsString(this);
        } catch (JsonGenerationException e) {
            e.printStackTrace();
            return null;
        } catch (JsonMappingException e) {
            e.printStackTrace();
            return null;
        } catch (IOException e) {
            e.printStackTrace();
            return null;
        }
    }
    //public GenericModel<T> toObject(String jsonObject) {
        //Suggested by stackOverflowComunity at:
        //https://stackoverflow.com/questions/27532206/java-create-list-of-objects-from-json-string-with-jackson
        public <T> T toObject(String jsonObject) {
        ObjectMapper jsonMapper = new ObjectMapper();
        try {
            //GenericModel<T> t = jsonMapper.readValue(jsonObject, GenericModel.class);
            T t = (T) jsonMapper.readValue(jsonObject, GenericModel.class);
            //return t;
            return t;
        } catch (JsonGenerationException e) {
            e.printStackTrace();
            return null;
        } catch (JsonMappingException e) {
            e.printStackTrace();
            return null;
        } catch (IOException e) {
            e.printStackTrace();
            return null;
        }
    }

}   

Generic hierarchical class that extends generic model:

package com.derp.generic.model;

import java.io.IOException;
import java.util.LinkedList;
import java.util.List;

import javax.persistence.CascadeType;
import javax.persistence.FetchType;
import javax.persistence.ManyToOne;
import javax.persistence.MappedSuperclass;
import javax.persistence.OneToMany;

import org.codehaus.jackson.JsonGenerationException;
import org.codehaus.jackson.map.JsonMappingException;
import org.codehaus.jackson.map.ObjectMapper;



@MappedSuperclass
public abstract class GenericHierarchicalModel<T extends GenericHierarchicalModel<T>> extends GenericModel<T> {
    private String name;
    @ManyToOne(fetch = FetchType.LAZY, cascade = CascadeType.ALL)
    private T parent;
    @OneToMany(mappedBy = "parent")
    private List<T> children;

    public String getName() {return name;}
    public void setName(String name) {this.name = name;}
    public T getParent() {return parent;}
    public void setParent(T parent) {this.parent = parent;}
    public List<T> getChildren() {return children;}
    public void setChildren(List<T> children) {this.children = children;}

    public GenericHierarchicalModel() {
        super();
    }
    @Override
    public String toJson() {
        return "{\"title\":\"" + this.name + "\", \"id\":\"" + this.getId() + "\", \"children\": [" + listToJson(this.getChildren()) + "]}";
    }
    public String listToJson(List<T> children) {
        String json = "";
        for(int i=0; i<children.size(); i++) {
            json = json + children.get(i).toJson();
            if(children.size()!=i+1) {
                json = json + ", ";
            }
        }
        return json;
    }
//  @Override
//  public GenericHierarchicalModel<T> toObject(String jsonObject) {
//      int start = 0; // '(' position in string
//      int end = 0; // ')' position in string
//      for(int i = 0; i < jsonObject.length(); i++) { 
//          if(jsonObject.charAt(i) == '{') // Looking for '{' position in string
//             start = i;
//          else if(jsonObject.charAt(i) == '}') // Looking for '}' position in  string
//             end = i;
//      }
//      String number = jsonObject.substring(start+1, end); // you take value between start and end
//      System.out.println(number);
//      return null;
//  }
}

Model class that I am trying to deserialize from json list of objects:

package com.derp.procedure.model;

import java.io.IOException;
import java.util.List;

import javax.persistence.DiscriminatorColumn;
import javax.persistence.Entity;
import javax.persistence.Inheritance;
import javax.persistence.InheritanceType;
import javax.persistence.Table;
import javax.persistence.Transient;

import org.codehaus.jackson.JsonGenerationException;
import org.codehaus.jackson.map.JsonMappingException;
import org.codehaus.jackson.map.ObjectMapper;

import com.derp.generic.model.GenericHierarchicalModel;
import com.derp.generic.model.GenericModel;
import com.google.gson.Gson;
import com.google.gson.reflect.TypeToken;

@Entity
@Table(name="procedure__SkeletonElement")
@Inheritance(strategy=InheritanceType.JOINED)
@DiscriminatorColumn(name="type")
public abstract class SkeletonElement extends GenericHierarchicalModel<SkeletonElement> {
    @Transient
    public String getDecriminatorValue() {
        return this.getClass().getSimpleName();
    }
    @Override
    public String toJson() {
        return "{\"title\":\"" + this.getName() + "\", \"id\":\"" + this.getId() + "\", \"type\":\"" + this.getDecriminatorValue() + "\", \"children\": [" + listToJson(this.getChildren()) + "]}";
    }
    public List<SkeletonElement> toObject(String jsonObject) {
        Gson gson = new Gson(); // Or use new GsonBuilder().create();
        //SkeletonElement[] target2 = gson.fromJson(jsonObject, SkeletonElement[].class);
        List<SkeletonElement> target2 = gson.fromJson(jsonObject, new TypeToken<List<SkeletonElement>>(){}.getType());

        return target2;
    }
    public SkeletonElement() {
        super();
    }
}

And the class that contain collection of object that I am trying to deserialize back to java list of objects:

package com.derp.procedure.model;

import java.util.LinkedList;
import java.util.List;

import javax.persistence.CascadeType;
import javax.persistence.Entity;
import javax.persistence.FetchType;
import javax.persistence.ManyToMany;
import javax.persistence.Table;

import com.derp.generic.model.GenericDictionaryModel;

@Entity
@Table(name="procedure__Skeleton")
public class Skeleton extends GenericDictionaryModel<Skeleton> {

    @ManyToMany(fetch = FetchType.EAGER, cascade = CascadeType.ALL)
    private List<SkeletonElement> skeletonElements;

    public void setSkeletonElements(List<SkeletonElement> skeletonElements) {this.skeletonElements = skeletonElements;}
    public List<SkeletonElement> getSkeletonElements() {return skeletonElements;}
    public List<SkeletonElement> getSkeletonParentsElements() {
        List<SkeletonElement> skeletonParentsElements = new LinkedList<SkeletonElement>();
        for(int i=0; i<this.skeletonElements.size(); i++) {
            if(this.skeletonElements.get(i).getParent()==null) {
                skeletonParentsElements.add(this.getSkeletonElements().get(i));
            }
        }
        return skeletonParentsElements;
    }

    public Skeleton(String name) {
        super(name);
    }

    public Skeleton() {
        // TODO Auto-generated constructor stub
    }

    public String getSkeletonElementsJsonTree() {
        String jsonTreeString ="[";
        List<SkeletonElement> skeletonParentsElements = getSkeletonParentsElements();
        for(int i=0; i<skeletonParentsElements.size(); i++) {
            jsonTreeString = jsonTreeString + skeletonParentsElements.get(i).toJson();
            if((1+i) != skeletonParentsElements.size()) {
                jsonTreeString = jsonTreeString + ",";
            }
        }
        return jsonTreeString + "]";
    }
    public void setSkeletonElements(String skeletonElementsJson) {
        this.skeletonElements.get(0).toObject(skeletonElementsJson);
    }



}

And at least my json string that I wont to deserialize:

[
    {
        "name": "Title1",
        "id": "1",
        "type": "SkeletonJobElement",
        "parent_id": "null",
        "children": [
            {
                "name": "Title11",
                "id": "2",
                "type": "SkeletonJobElement",
                "parent_id": "1",
                "children": [
                    {
                        "name": "Title111",
                        "id": "5",
                        "type": "SkeletonFileElement",
                        "parent_id": "2",
                        "children": []
                    },
                    {
                        "name": "Title112",
                        "id": "6",
                        "type": "SkeletonFileElement",
                        "parent_id": "2",
                        "children": []
                    }
                ]
            }
        ]
    },
    {
        "name": "Title2",
        "id": "3",
        "type": "SkeletonJobElement",
        "parent_id": "null",
        "children": [
            {
                "name": "Title21",
                "id": "4",
                "type": "SkeletonJobElement",
                "parent_id": "3",
                "children": []
            }
        ]
    }
]

I know that is a lot of code to analize, but please help me figure it out. I struggle with it for week so long.

like image 701
masterdany88 Avatar asked Dec 19 '14 19:12

masterdany88


2 Answers

com.derp.procedure.model.SkeletonElement is an abstract class. Make this class concrete deleting the abstract modifier.

like image 51
Ansemo Abadía Avatar answered Nov 06 '22 12:11

Ansemo Abadía


If you want to keep class abstract, you need to write custom deserialization using Gson's JsonDeserializer and register it as type adapter. So let's say you have abstract class A and derived class B (B extends A):

JsonDeserializer<A> deserializer = ...; 
gsonBuilder.registerTypeAdapter(A.class, deserializer);

Now inside JsonDeserializer you have to specify that A should deserialize into B:

return context.deserialize(json, B.class);

That makes more sense if you have multiple classes that derive from abstract class A. Let's say that both B and C derive from A. In that scenario you would need to handle deserialization for both of them (inside JsonDeserializer<A>):

if (json is of class B) {
  return context.deserialize(json, B.class);
}
if (json is of class C) {
  return context.deserialize(json, C.class);
}
...
like image 2
nejckorasa Avatar answered Nov 06 '22 12:11

nejckorasa