简体   繁体   中英

java.lang.StackOverflowError while converting BindingResult to JSON using Gson

Environment:
Spring boot- 1.2.3
Issue :

When BindingResult is added as next argument to @Valid argument for controller method like below, keep on getting java.lang.StackOverflowError

@RequestMapping(value = "/employees", method = RequestMethod.POST, consumes = "application/json")
public void createEmployee(HttpServletRequest request, @Valid @RequestBody Employee employee, BindingResult result){
    logger.debug("Creating Employee [" + employee.getForename() + " " + employee.getSurname() + "]");
}

If BindingResult method argument is removed, it works fine.
Update start
Found the issue, StackOverflowError occurred while converting BindingResult instance to JSON using below code:

//log all method arguments   
com.google.gson.Gson gson = new com.google.gson.Gson();
String json = gson.toJson(bindingResultArgFromControllerMethod);

Framework code uses Gson to convert method arguments to JSON for logging.

Is there way to avoid/handle this exception?
Update end

Relevant Stack trace :

    Servlet.service() for servlet [dispatcherServlet] in context with path [] threw exception [Handler processing failed; nested exception is java.lang.StackOverflowError] with root cause

java.lang.StackOverflowError: null
//Repeatattive block start 
at com.google.gson.internal.$Gson$Types.resolve($Gson$Types.java:383)
at com.google.gson.internal.$Gson$Types.resolve($Gson$Types.java:378)
//Repeatattive block end 
at com.google.gson.internal.bind.ReflectiveTypeAdapterFactory.getBoundFields(ReflectiveTypeAdapterFactory.java:155)
at com.google.gson.internal.bind.ReflectiveTypeAdapterFactory.create(ReflectiveTypeAdapterFactory.java:97)
at com.google.gson.Gson.getAdapter(Gson.java:407)
at com.google.gson.internal.bind.ReflectiveTypeAdapterFactory.getFieldAdapter(ReflectiveTypeAdapterFactory.java:136)
at com.google.gson.internal.bind.ReflectiveTypeAdapterFactory.access$100(ReflectiveTypeAdapterFactory.java:49)
at com.google.gson.internal.bind.ReflectiveTypeAdapterFactory$1.<init>(ReflectiveTypeAdapterFactory.java:106)
at com.google.gson.internal.bind.ReflectiveTypeAdapterFactory.createBoundField(ReflectiveTypeAdapterFactory.java:105)
at com.google.gson.internal.bind.ReflectiveTypeAdapterFactory.getBoundFields(ReflectiveTypeAdapterFactory.java:161)
at com.google.gson.internal.bind.ReflectiveTypeAdapterFactory.create(ReflectiveTypeAdapterFactory.java:97)
at com.google.gson.Gson.getAdapter(Gson.java:407)

According to the API docs of BindingResult , this is only a holder of the data that the user entered to the browser. Moreover, the implementation of BindingResult can contain all sort of references to other helper objects. Based on the stack trace, there's a circular reference on the current implementation of BindingResult .

I think you want to jsonify the data the user entered. Then all you need to do is to jsonify the target of the BindingResult :

com.google.gson.Gson gson = new com.google.gson.Gson();
String json = gson.toJson(bindingResultArgFromControllerMethod.getTarget());

This target is, according to the method docs : the wrapped target object, which may be a bean, an object with public fields, a Map - depending on the concrete binding strategy .

Hope this helps.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM