currently, need send large json object ajax request. purpose using following controller method works fine.
@requestmapping(method = requestmethod.post,params = {"dynamicscenario"}) @responsebody public string getdynamicscenariodata(@requestparam map<string, string> map) throws jsonparseexception, jsonmappingexception, ioexception { objectmapper mapper = new objectmapper(); @suppresswarnings("unchecked") map<string,object> queryparameters = mapper.readvalue(map.get("parameters") , map.class); map<string, object> getdata = service.rundynamicscenario(queryparameters, map.get("querystring")); return writer.writevalueasstring(getdata); //here java throws java.lang.outofmemoryerror: java heap space memory } update: ajax is:
$.ajax({ type: "post", url: "dynamicscenario.htm", data : tags, datatype: "json", success: function(data){}); my dispatcherservlet settings:
public class applicationinitializer implements webapplicationinitializer { public void onstartup(servletcontext servletcontext) throws servletexception { annotationconfigwebapplicationcontext context = new annotationconfigwebapplicationcontext(); context.register(applicationconfig.class); servletcontext.addlistener(new contextloaderlistener(context)); servletregistration.dynamic servletregistration = servletcontext.addservlet("dispatcher", new dispatcherservlet(context)); servletregistration.setloadonstartup(1); servletregistration.addmapping("*.htmlx"); } } i using jackson serialize map of different objects , send ajax. however, if size of json large java throws out of memory. know jackson method writer.writevalueasstring inefficient because writing string there other alternative? can't use plain java pojo because don't know objects map have serialize contain can't map java object. ideas? thanks
the issue want solve is
return writer.writevalueasstring(getdata); creating big of string , causing outofmemoryerror. jackson supports streaming api, spring makes use of in mappingjackson2httpmessageconverter, handles serializing pojos json in response body (and request body).
there few ways handle this. easiest change return type map<string, object , return corresponding object directly.
@requestmapping(method = requestmethod.post,params = {"dynamicscenario"}) @responsebody public map<string, object> getdynamicscenariodata(@requestparam map<string, string> map) throws jsonparseexception, jsonmappingexception, ioexception { objectmapper mapper = new objectmapper(); @suppresswarnings("unchecked") map<string,object> queryparameters = mapper.readvalue(map.get("parameters") , map.class); map<string, object> getdata = service.rundynamicscenario(queryparameters, map.get("querystring")); return getdata; } spring take care of serializing getdata streaming results directly response outputstream.
this won't work on own. one, url using access service
/dynamicscenario.htm is causing spring's content negotiation kick in. sees .htm , thinks expecting text/html content. either turn off content negotiation or use url without extension
/dynamicscenario spring then, instead, @ accept headers figuring out client expecting. since
datatype: "json" it's going write application/json mappingjackson2httpmessageconverter.
here more things fix
annotationconfigwebapplicationcontext context = new annotationconfigwebapplicationcontext(); context.register(applicationconfig.class); servletcontext.addlistener(new contextloaderlistener(context)); servletregistration.dynamic servletregistration = servletcontext.addservlet("dispatcher", new dispatcherservlet(context)); servletregistration.setloadonstartup(1); servletregistration.addmapping("*.htmlx"); you're making both contextloaderlistener , dispatcherservlet load same applicationcontext. unnecessary , potentially harmful. dispatcherservlet uses contextloaderlistener context parent context. can read more here:
if applicationconfig contains mvc configuration elements, have dispatcherservlet load it. won't need contextloaderlistener.
if has other types of config elements unrelated mvc stack, split 2 @configuration classes. pass mvc 1 dispatcherservlet , other contextloaderlistener.
don't pass json form parameters. pass directly request body , use @requestbody deserialize directly expected type.
@requestmapping(method = requestmethod.post) @responsebody public map<string, object> getdynamicscenariodata(@requestbody map<string,object> queryparameters) throws jsonparseexception, jsonmappingexception, ioexception { map<string, object> getdata = service.rundynamicscenario(queryparameters, /* find better way pass map.get("querystring") */); return getdata; } you save objectmapper object on each request (it's heavy object) , let spring take care of deserializing (again streaming). you'll have find way pass querystring (you can still pass single query parameter , `@requestparam).
Comments
Post a Comment