Greetings,

I'm working on a server app that currently uses Restlet 2.0.6 with the 
org.restlet.ext.jackson.jar to accept/return JSON which is modeled internally 
as simple java primitives (Map, List, String, Integer, etc...).

A trivial example of the types of Resources we use can be seen by modifying the 
hello world Server example from the restlet tutorial like so, and running it 
with the ext.jackson jars in the classpath...

  public class EchoServer extends ServerResource {  
    public static void main(String[] args) throws Exception {  
      new Server(Protocol.HTTP, 8182, EchoServer.class).start();  
    }
    @Post("json")
    public Map<String,Object> echo(Map<String,Object> data) {  
      return data;
    }
  }  

We've gotten more then a few requests from customers for better error messages 
when they POST/PUT malformed JSON since the only details they get from restlet 
at the moment is a 415 (Unsupported Media Type).  For instance, the above 
server responds as expected when the JSON is both well-formed and matches the 
expected structure (Map)...

hossman@bester:~/tmp$ curl -sSD - -X POST -H 'Content-Type: application/json' 
-d '{"foo":"bar","yak":"zad"}' http://localhost:8182/ && echo
HTTP/1.1 200 OK
Transfer-Encoding: chunked
Date: Thu, 18 Aug 2011 00:43:48 GMT
Server: Restlet-Framework/2.0.6
Vary: Accept-Charset, Accept-Encoding, Accept-Language, Accept
Content-Type: application/json; charset=UTF-8

{"foo":"bar","yak":"zad"}

...but it returns no useful error message when the JSON is mallformed, or does 
not parse into a Map...

hossman@bester:~/tmp$ curl -sSD - -X POST -H 'Content-Type: application/json' 
-d '{malformed]' http://localhost:8182/ && echoHTTP/1.1 415 Unsupported Media 
Type
Date: Thu, 18 Aug 2011 00:45:15 GMT
Server: Restlet-Framework/2.0.6
Vary: Accept-Charset, Accept-Encoding, Accept-Language, Accept
Content-Length: 0


hossman@bester:~/tmp$ curl -sSD - -X POST -H 'Content-Type: application/json' 
-d '"string not a map"' http://localhost:8182/ && echo
HTTP/1.1 415 Unsupported Media Type
Date: Thu, 18 Aug 2011 00:45:24 GMT
Server: Restlet-Framework/2.0.6
Vary: Accept-Charset, Accept-Encoding, Accept-Language, Accept
Content-Length: 0


...even though the JacksonConvertor is logging useful errors on the server...

Aug 17, 2011 5:45:15 PM org.restlet.ext.jackson.JacksonRepresentation getObject
WARNING: Unable to parse the object with Jackson.
org.codehaus.jackson.JsonParseException: Unexpected character ('m' (code 109)): 
was expecting double-quote to start field name
 at [Source: org.restlet.engine.http.io.SizedInputStream@61a116c9; line: 1, 
column: 3]
        at org.codehaus.jackson.JsonParser._constructError(JsonParser.java:929)
        at 
org.codehaus.jackson.impl.JsonParserBase._reportError(JsonParserBase.java:632)
        ...
Aug 17, 2011 5:45:24 PM org.restlet.ext.jackson.JacksonRepresentation getObject
WARNING: Unable to parse the object with Jackson.
org.codehaus.jackson.map.JsonMappingException: Can not deserialize instance of 
java.util.Map out of VALUE_STRING token
 at [Source: org.restlet.engine.http.io.SizedInputStream@30e3c624; line: 1, 
column: 1]
        at 
org.codehaus.jackson.map.JsonMappingException.from(JsonMappingException.java:159)
        at 
org.codehaus.jackson.map.deser.StdDeserializationContext.mappingException(StdDeserializationContext.java:131)

What we'd like to do when returning these 415 error responses is generate a 
JSON Represation of an error message that contains more details about the 
specifics of the parse error.

I know that we can register our own StatusService implementation to override 
the default getStatus and getRepresentation methods used to generate errors in 
restlet, but based on my testing StatusService.getStatus doesn't seem to be 
called when these types of parse errors happen in the Converters on client 
input, so we never see the JsonParseException or JsonMappingException from the 
jackson parser.  I do see my custom StatusService.getRepresentation method 
getting called, but at that point in the workflow, I don't see any indication 
of the cause of the error:  Status.getThrowable() is null, and nothing in the 
Request object seems to relate to accessing Conversion errors.

I briefly considered trying to reparse the Entity data myself using jackson to 
see what error I'd get, but in this type of situation the raw JSON doesn't seem 
to be available in the Request object passed to StatusService.getRepresentation 
(Request.getEntityAsText() and request.getEntity().getText() both return null).


Am I missing something?  Is there any programmatic way for Restlet apps to 
access error messages generated when Converters parse client input?  

I poked around in the trunk version of JacksonRepresentation.getObject() and it 
looks like (as implemented) JacksonRepresentation logs these errors and then 
immediately returns null (making me wonder how the restlet engine tells the 
difference between a 415 error because the Convertor couldn't parse the request 
vs. input that is genuinely null) but I've got my fingers crossed that an 
expert will chime in here and explain how the StatusService API is actually 
designed  to support giving server apps access to these types of errors, and 
that in this particular case the JacksonRepresentation class is buggy in how it 
deals with errors and there is a simple patch to fix it to report the errors 
correctly.

I hope.

-Hoss

------------------------------------------------------
http://restlet.tigris.org/ds/viewMessage.do?dsForumId=4447&dsMessageId=2823739

Reply via email to