returning json response in #ResponseBody spring annotation - json

i have a method returning json object. I have used annotation based configuration and annotated the method as #ResponseBody. I get the correct output if i return the object as a string. But i need the json formatted object to be returned. Since I'm new to spring I'm stuck fixing this error
HTTP Status 500 – Internal Server Error Type Exception Report
Message No converter found for return value of type: class
org.json.simple.JSONObject
Description The server encountered an unexpected condition that
prevented it from fulfilling the request.
Exception
org.springframework.http.converter.HttpMessageNotWritableException: No
converter found for return value of type: class
org.json.simple.JSONObject
org.springframework.web.servlet.mvc.method.annotation.AbstractMessageConverterMethodProcessor.writeWithMessageConverters(AbstractMessageConverterMethodProcessor.java:218)
org.springframework.web.servlet.mvc.method.annotation.RequestResponseBodyMethodProcessor.handleReturnValue(RequestResponseBodyMethodProcessor.java:182)
org.springframework.web.method.support.HandlerMethodReturnValueHandlerComposite.handleReturnValue(HandlerMethodReturnValueHandlerComposite.java:82)
org.springframework.web.servlet.mvc.method.annotation.ServletInvocableHandlerMethod.invokeAndHandle(ServletInvocableHandlerMethod.java:119)
org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.invokeHandlerMethod(RequestMappingHandlerAdapter.java:871)
org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.handleInternal(RequestMappingHandlerAdapter.java:777)
org.springframework.web.servlet.mvc.method.AbstractHandlerMethodAdapter.handle(AbstractHandlerMethodAdapter.java:87)
org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:991)
org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:925)
org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:978)
org.springframework.web.servlet.FrameworkServlet.doGet(FrameworkServlet.java:870)
javax.servlet.http.HttpServlet.service(HttpServlet.java:634)
org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:855)
javax.servlet.http.HttpServlet.service(HttpServlet.java:741)
org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:53)
Note The full stack trace of the root cause is available in the server
logs.
Apache Tomcat/9.0.10
How do i fix this?

Related

Grails: How to exclude ApplicationHttpRequest field in converting a domain class to JSON

I want to convert my domain classes to JSON format. But during the conversion, I've encountered this issue below:
java.lang.RuntimeException: org.codehaus.groovy.grails.web.converters.exceptions.ConverterException: Error converting Bean with class org.apache.catalina.core.ApplicationHttpRequest
at grails.plugin.cache.web.filter.PageFragmentCachingFilter.doFilter(PageFragmentCachingFilter.java:198)
at grails.plugin.cache.web.filter.AbstractFilter.doFilter(AbstractFilter.java:63)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)
at java.lang.Thread.run(Thread.java:745)
Caused by: org.codehaus.groovy.grails.web.converters.exceptions.ConverterException: Error converting Bean with class org.apache.catalina.core.ApplicationHttpRequest
at grails.converters.JSON.value(JSON.java:202)
at grails.converters.JSON.convertAnother(JSON.java:162)
at grails.converters.JSON.value(JSON.java:202)
at grails.converters.JSON.convertAnother(JSON.java:162)
at grails.converters.JSON.value(JSON.java:202)
at grails.converters.JSON.render(JSON.java:134)
Caused by: java.lang.IllegalAccessException: Class org.codehaus.groovy.grails.web.converters.marshaller.json.GenericJavaBeanMarshaller can not access a member of class org.apache.catalina.core.ApplicationHttpRequest with modifiers "public"
I used JSON converters to convert Object to JSON format.
render myDomain as JSON
These are the domain classes of my app.
MyDomain {
String username
String password
ApplicationHttpRequest request
OtherDomain otherDomain
}
OtherDomain {
String otherField1
String otherFiled2
ApplicationHttpRequest request
}
I really wanted to convert objects to json excluding the request field above. How can I do it? Thanks.

maxJsonLength exceeded logging with log4net ElasticSearch appender

We are using the log4net.ElasticSearch appender, to send application log messages to ElasticSearch.
We frequently log service requests and responses as context objects to log events, for debugging/support purposes - and it seems that sometimes responses when serialized can be too large, which results in the following exception:
System.InvalidOperationException occurred
HResult=-2146233079
Message=Error during serialization or deserialization using the JSON JavaScriptSerializer. The length of the string exceeds the value set on the maxJsonLength property.
Source=System.Web.Extensions
StackTrace:
at System.Web.Script.Serialization.JavaScriptSerializer.Serialize(Object obj, StringBuilder output, SerializationFormat serializationFormat)
at System.Web.Script.Serialization.JavaScriptSerializer.Serialize(Object obj, SerializationFormat serializationFormat)
at log4net.ElasticSearch.ExtensionMethods.ToJson[T](T self)
InnerException:
Is there any way to increase this limit?
You can make a pull request for the appender:
https://github.com/jptoto/log4net.ElasticSearch/blob/f5d122526f410d1294bc8d3aeb5a94379800f552/src/log4net.ElasticSearch/ExtensionMethods.cs
public static string ToJson<T>(this T self)
{
JavaScriptSerializer serializer = new JavaScriptSerializer();
serializer.MaxJsonLength = Int32.MaxValue;
return serializer.Serialize(self);
}

Spring MVC controller Json response, hibernate proxy error

I have a Spring controller annotated class which implements this method:
#RequestMapping(value = "/event/eventList", method = RequestMethod.GET)
public #ResponseBody List<Event> listEvents() {
System.out.println("############ LIST EVENTS ############");
List<Event> events = eventService.listAllEvents();
for(Event event : events) {
Hibernate.getClass(event);
System.out.println(event);
}
return events;
}
when I call the page (localhost:8080/myapp/event/eventList) from browser, the method will be called correctly i see all the logs and the events are printed correctly meaning the event list is not empty and valid, but I get the error:
GRAVE: Servlet.service() for servlet [dispatcher] in context with path [/myapp] threw exception [Request processing failed; nested exception is java.lang.UnsupportedOperationException: Attempted to serialize java.lang.Class: org.hibernate.proxy.HibernateProxy. Forgot to register a type adapter?] with root cause
java.lang.UnsupportedOperationException: Attempted to serialize java.lang.Class: org.hibernate.proxy.HibernateProxy. Forgot to register a type adapter?
It does not return any Json representation.
I changed the method to return a string like:
#RequestMapping(value = "/event/eventList", method = RequestMethod.GET)
public #ResponseBody String listEvents() {
return "{'pippo':1}";
}
In this case the browser show the string correctly.
did I miss something?
The exception is thrown by com.google.gson.internal.bind.TypeAdapters when GSON is trying to serialize variable 'events' to Json.
This happens, cause
eventService.listAllEvents()
returns not a list already containing all events, but hibernate proxy that will do that lazy, when the list is actually used.
GSON does not know how to serialize that proxy.
Hibernate.getClass should initialize the underlying object as a side effect.
You need to call it also for the List 'events' itself, not only for every single event. The List can be a hibernate proxy also.
You may find more info on that topic at
Could not serialize object cause of HibernateProxy

Consuming JSON with Jersey 2.3 throws XML exception

I'm trying to make Jersey 2.3 + Moxy work with my custom objects. Everything is ok when I'm producing JSON from those objects, but refuses to work when I want to consume them by POST. Code first:
Custom object:
#XmlRootElement
public class ContentAction extends Action {
private String contentType;
private Integer contentLength;
public ContentAction() {
setType(ActionType.CONTENT);
}
public String getContentType() {
return contentType;
}
public void setContentType(String contentType) {
this.contentType = contentType;
}
public Integer getContentLength() {
return contentLength;
}
public void setContentLength(Integer contentLength) {
this.contentLength = contentLength;
}
}
Resource fragment (path is declared on the class):
#POST
#Produces(JsonHelper.JSON_UTF8)
public Action saveAction(#QueryParam("action") ContentAction action) throws IOException {
ActionEntity entity = actionConverter.toEntity(action);
entity.setBeacon(beaconService.findById(action.getBeacon().getId()));
return actionConverter.convert(actionService.save(entity));
}
API caller (class responsible for sending requests):
URI uri = buildUri(path, params);
HttpPost httpPost = new HttpPost(uri);
httpClient.execute(httpPost);
buildUri simply creates URI from address & parameters
The action is converted to JSON as follows: mapper.writeValueAsString(action)
And the exception:
org.glassfish.jersey.server.internal.inject.ExtractorException: Error unmarshalling JAXB object of type "class com.kontakt.platform.apicommon.model.ContentAction".
at org.glassfish.jersey.server.internal.inject.JaxbStringReaderProvider$RootElementProvider$1.fromString(JaxbStringReaderProvider.java:195)
at org.glassfish.jersey.server.internal.inject.AbstractParamValueExtractor.convert(AbstractParamValueExtractor.java:138)
at org.glassfish.jersey.server.internal.inject.AbstractParamValueExtractor.fromString(AbstractParamValueExtractor.java:129)
at org.glassfish.jersey.server.internal.inject.SingleValueExtractor.extract(SingleValueExtractor.java:83)
at org.glassfish.jersey.server.internal.inject.QueryParamValueFactoryProvider$QueryParamValueFactory.provide(QueryParamValueFactoryProvider.java:88)
at org.glassfish.jersey.server.spi.internal.ParameterValueHelper.getParameterValues(ParameterValueHelper.java:81)
at org.glassfish.jersey.server.model.internal.JavaResourceMethodDispatcherProvider$AbstractMethodParamInvoker.getParamValues(JavaResourceMethodDispatcherProvider.java:121)
at org.glassfish.jersey.server.model.internal.JavaResourceMethodDispatcherProvider$TypeOutInvoker.doDispatch(JavaResourceMethodDispatcherProvider.java:195)
at org.glassfish.jersey.server.model.internal.AbstractJavaResourceMethodDispatcher.dispatch(AbstractJavaResourceMethodDispatcher.java:104)
at org.glassfish.jersey.server.model.ResourceMethodInvoker.invoke(ResourceMethodInvoker.java:353)
at org.glassfish.jersey.server.model.ResourceMethodInvoker.apply(ResourceMethodInvoker.java:343)
at org.glassfish.jersey.server.model.ResourceMethodInvoker.apply(ResourceMethodInvoker.java:102)
at org.glassfish.jersey.server.ServerRuntime$1.run(ServerRuntime.java:255)
at org.glassfish.jersey.internal.Errors$1.call(Errors.java:271)
at org.glassfish.jersey.internal.Errors$1.call(Errors.java:267)
at org.glassfish.jersey.internal.Errors.process(Errors.java:315)
at org.glassfish.jersey.internal.Errors.process(Errors.java:297)
at org.glassfish.jersey.internal.Errors.process(Errors.java:267)
at org.glassfish.jersey.process.internal.RequestScope.runInScope(RequestScope.java:318)
at org.glassfish.jersey.server.ServerRuntime.process(ServerRuntime.java:235)
at org.glassfish.jersey.server.ApplicationHandler.handle(ApplicationHandler.java:983)
at org.glassfish.jersey.servlet.WebComponent.service(WebComponent.java:359)
at org.glassfish.jersey.servlet.ServletContainer.service(ServletContainer.java:372)
at org.glassfish.jersey.servlet.ServletContainer.service(ServletContainer.java:335)
at org.glassfish.jersey.servlet.ServletContainer.service(ServletContainer.java:218)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:305)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:210)
at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:222)
at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:123)
at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:472)
at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:171)
at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:99)
at org.apache.catalina.valves.AccessLogValve.invoke(AccessLogValve.java:953)
at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:118)
at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:408)
at org.apache.coyote.http11.AbstractHttp11Processor.process(AbstractHttp11Processor.java:1008)
at org.apache.coyote.AbstractProtocol$AbstractConnectionHandler.process(AbstractProtocol.java:589)
at org.apache.tomcat.util.net.AprEndpoint$SocketProcessor.run(AprEndpoint.java:1852)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1145)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:615)
at java.lang.Thread.run(Thread.java:722)
Caused by: javax.xml.bind.UnmarshalException
- with linked exception:
[org.xml.sax.SAXParseException; lineNumber: 1; columnNumber: 1; Content is not allowed in prolog.]
at javax.xml.bind.helpers.AbstractUnmarshallerImpl.createUnmarshalException(AbstractUnmarshallerImpl.java:335)
at com.sun.xml.internal.bind.v2.runtime.unmarshaller.UnmarshallerImpl.createUnmarshalException(UnmarshallerImpl.java:512)
at com.sun.xml.internal.bind.v2.runtime.unmarshaller.UnmarshallerImpl.unmarshal0(UnmarshallerImpl.java:209)
at com.sun.xml.internal.bind.v2.runtime.unmarshaller.UnmarshallerImpl.unmarshal(UnmarshallerImpl.java:175)
at javax.xml.bind.helpers.AbstractUnmarshallerImpl.unmarshal(AbstractUnmarshallerImpl.java:140)
at javax.xml.bind.helpers.AbstractUnmarshallerImpl.unmarshal(AbstractUnmarshallerImpl.java:123)
at org.glassfish.jersey.server.internal.inject.JaxbStringReaderProvider$RootElementProvider$1.fromString(JaxbStringReaderProvider.java:190)
... 40 more
Caused by: org.xml.sax.SAXParseException; lineNumber: 1; columnNumber: 1; Content is not allowed in prolog.
at com.sun.org.apache.xerces.internal.util.ErrorHandlerWrapper.createSAXParseException(ErrorHandlerWrapper.java:198)
at com.sun.org.apache.xerces.internal.util.ErrorHandlerWrapper.fatalError(ErrorHandlerWrapper.java:177)
at com.sun.org.apache.xerces.internal.impl.XMLErrorReporter.reportError(XMLErrorReporter.java:441)
at com.sun.org.apache.xerces.internal.impl.XMLErrorReporter.reportError(XMLErrorReporter.java:368)
at com.sun.org.apache.xerces.internal.impl.XMLScanner.reportFatalError(XMLScanner.java:1388)
at com.sun.org.apache.xerces.internal.impl.XMLDocumentScannerImpl$PrologDriver.next(XMLDocumentScannerImpl.java:998)
at com.sun.org.apache.xerces.internal.impl.XMLDocumentScannerImpl.next(XMLDocumentScannerImpl.java:607)
at com.sun.org.apache.xerces.internal.impl.XMLNSDocumentScannerImpl.next(XMLNSDocumentScannerImpl.java:116)
at com.sun.org.apache.xerces.internal.impl.XMLDocumentFragmentScannerImpl.scanDocument(XMLDocumentFragmentScannerImpl.java:489)
at com.sun.org.apache.xerces.internal.parsers.XML11Configuration.parse(XML11Configuration.java:835)
at com.sun.org.apache.xerces.internal.parsers.XML11Configuration.parse(XML11Configuration.java:764)
at com.sun.org.apache.xerces.internal.parsers.XMLParser.parse(XMLParser.java:123)
at com.sun.org.apache.xerces.internal.parsers.AbstractSAXParser.parse(AbstractSAXParser.java:1210)
at com.sun.org.apache.xerces.internal.jaxp.SAXParserImpl$JAXPSAXParser.parse(SAXParserImpl.java:568)
at com.sun.xml.internal.bind.v2.runtime.unmarshaller.UnmarshallerImpl.unmarshal0(UnmarshallerImpl.java:203)
... 44 more
When I remove #XmlRootElement, Jersey tries to create object from constructor with string parameter (if added) = no automatic bean creation.
I've been stuck with this for two days and I'd be very grateful for any help.
I think the problem is that you need to set the content type. Since you are not specifying the content type, jersey is assuming it is reciving xml but it is in fact json. The error message is from jaxb trying to read the xml header and finding invalid characters. Try using the jersey client instead of an http post. Also I think you might what to change your #Produces(MediaType.APPLICATION_JSON) for consistency.
#Produces(MediaType.APPLICATION_JSON)
Example POST CODE
The most important part is that I am setting the type (type(MediaType.Application_JSON) that I am going to post.
WebResource webResource = createRestClient(true).resource(
REST_BASE_PATH + "/service");
ClientResponse response = webResource.type(MediaType.APPLICATION_JSON)
.accept(MediaType.APPLICATION_JSON)
.post(ClientResponse.class, contentActionObject);
Assert.assertTrue(response.getStatus() == 200);
If you do need to use the HttpPost object then there should be a configuration option to set http headers. I have done this using the the HttpUrlConnection. You would have to set your content type to be application/json instead of xml.
HttpURLConnection connection = null;
connection = (HttpURLConnection) new URL(requestUrl).openConnection();
connection.setRequestMethod("GET");
connection.setRequestProperty("Accept", "application/xml");
connection.setRequestProperty("Content-Type", "application/xml");
EclipseLink MOXy will be picked up as the JSON-binding provder by Jersey for media types that follow the following pattern.
*/json (i.e. application/json and text/json)
/+json
Based on your exception it appears as though the media type have have represented with JsonHelper.JSON_UTF8 does not match this pattern.
I know this is a little old, but I have been encountering the essentially the identical issue using Jersey 2.3 + Moxy. Same scenario and the identical exception is occurring. The only difference is that my POST method is annotated with:
#Produces(MediaType.APPLICATION_JSON)
#Consumes(MediaType.APPLICATION_JSON)
I did find that when if I passed the same JSON representation in the request body instead of as a query parameter that it was unmarshalled successfully. This would require changing your POST method declaration to:
public Action saveAction(ContentAction action)
Not sure if this would be a work around for you. If you found a resolution I would be interested in hearing what it was.

Error in Deserializing json string comming through a rest webservice call

Having a webservise which returns an appfuse User instance in the form of json, where this user model contains a property roles which is a set of role objects.
My problem is that when this roles property contains no role object or more than one role objects it work fine, but when it contains single role element, it is not working
Exception::
com.google.gson.JsonSyntaxException: java.lang.IllegalStateException: Expected BEGIN_ARRAY but was BEGIN_OBJECT at line 1 column 218
at com.google.gson.internal.bind.ReflectiveTypeAdapterFactory$Adapter.read(ReflectiveTypeAdapterFactory.java:180)
at com.google.gson.Gson.fromJson(Gson.java:755)
at com.google.gson.Gson.fromJson(Gson.java:721)
at com.google.gson.Gson.fromJson(Gson.java:670)
at com.google.gson.Gson.fromJson(Gson.java:642)
at com.steriamobile.ws.smfserver.service.SMFUserServiceImpl.getUser(SMFUserServiceImpl.java:44)
at com.steriamobile.ws.smfserver.service.SMFUserManagerImpl.getUser(SMFUserManagerImpl.java:19)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
at java.lang.reflect.Method.invoke(Method.java:597)
at org.springframework.aop.support.AopUtils.invokeJoinpointUsingReflection(AopUtils.java:307)
at org.springframework.aop.framework.ReflectiveMethodInvocation.invokeJoinpoint(ReflectiveMethodInvocation.java:182)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:149)
at org.springframework.transaction.interceptor.TransactionInterceptor.invoke(TransactionInterceptor.java:106)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:171)
at org.springframework.aop.interceptor.ExposeInvocationInterceptor.invoke(ExposeInvocationInterceptor.java:89)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:171)
at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:204)
at $Proxy32.getUser(Unknown Source)
REST Service::
#GET
#Path("/getUser/{id}")
public User get(#PathParam("id") Long id) {
return userManager.get(id);
}
Deserializing Code:
Gson gson = new Gson();
User user = gson.fromJson(json,new TypeToken<User>() {}.getType());
As I understand the problem description, custom deserialization is necessary to handle the situation where the JSON is sometimes an array and sometimes an object.
Using Gson to handle this specific issue has been covered in previous StackOverflow threads, such as Parsing JSON with GSON, object sometimes contains list sometimes contains object and Gson handle object or array.