The ZF implementation of the JSON-RPC 2.0 protocol only allows error codes:
const ERROR_PARSE = -32768;
const ERROR_INVALID_REQUEST = -32600;
const ERROR_INVALID_METHOD = -32601;
const ERROR_INVALID_PARAMS = -32602;
const ERROR_INTERNAL = -32603;
const ERROR_OTHER = -32000;
plus, range(-32099, -32000)
These are defined in the JSON-RPC spec as pre-defined and/or reserved. At least this is what get out of the spec:
The error codes from and including -32768 to -32000 are reserved for pre-defined errors. Any code within this range, but not defined explicitly below is reserved for future use. The error codes are nearly the same as those suggested for XML-RPC at the following url: http://xmlrpc-epi.sourceforge.net/specs/rfc.fault_codes.php
code message meaning
-32700 Parse error Invalid JSON was received by the server.
An error occurred on the server while parsing the JSON text.
-32600 Invalid Request The JSON sent is not a valid Request object.
-32601 Method not found The method does not exist / is not available.
-32602 Invalid params Invalid method parameter(s).
-32603 Internal error Internal JSON-RPC error.
-32000 to -32099 Server error Reserved for implementation-defined server-errors.
The remainder of the space is available for application defined errors.
Nowhere does it say that you cannot, for example use -100 or 100. Am I missing something?
Somewhere I think that "server error" and "application error" have been confused by ZF as the same thing, while when reading the sourcefourge link above, clearly the authors of the protocol had something different in mind, allowing the application developers A LOT of space:
In addition, the range -32099 .. -32000, inclusive is reserved for implementation defined server errors. Server errors which do not cleanly map to a specific error defined by this spec should be assigned to a number in this range. This leaves the remainder of the space available for application defined errors.
I use the JSON-RPC component of ZF for a few projects. It works pretty well - but I would hardly consider it an exemplar of the JSON-RPC spec. As far as I know, only a couple clients out there actually test their implementations against Zend_Json_Server, so it's hardly a widely adopted implementation. At one point, I actually had to patch Zend_Json_Server to make it work with one client, as it was not following the spec properly (that's since been fixed).
So basically what I'm saying is "good point, you're probably right." If it itches enough, just fork zf2 and submit a pull request with a better implementation of the spec - much easier to get positive / negative feedback when you're looking at a diff.
If they accept it, submit a patch for zf1 to merge in downstream.
Related
I'm frustrated by unintelligible stacktraces when my Scala.js code throws an exception. I thought I had a solution using a Javascript library (see Getting a scala stacktrace) but it breaks too often.
How do you extract meaning (where the program broke; how it got there -- in terms of the Scala code) from a stacktrace like the following. Or am I doing something wrong to even get an untranslated stacktrace?
Take a look at this code I wrote a while back in my youi framework: https://github.com/outr/youi/tree/e66dc36a12780fa8941152d07de9c3a52d28fc10/app/js/src/main/scala/io/youi/app/sourceMap
It is used to reverse JS stack traces to Scala stack traces. In youi I send the errors to the server so I can monitor browser errors that occur with the complete traceback.
Brief Overview
source-map.js
You need source-map.js to parse the js.map file that Scala.js
generated when it compiled your code. See:
https://github.com/mozilla/source-map
Load the js.map file via Ajax
The SourceMapConsumer needs a js.Object (JSON) of the js.map file. See https://github.com/outr/youi/blob/e66dc36a12780fa8941152d07de9c3a52d28fc10/app/js/src/main/scala/io/youi/app/sourceMap/ErrorTrace.scala#L58 for an example of loading via youi's Ajax features.
Process the Throwable
The trace represents line and columns in the JS file and you can pass
that information to SourceMapConsumer to get the original Scala line
numbers back (see SourceMapConsumer.originalPositionFor). See
ErrorTrace.toCause
(https://github.com/outr/youi/blob/e66dc36a12780fa8941152d07de9c3a52d28fc10/app/js/src/main/scala/io/youi/app/sourceMap/ErrorTrace.scala#L98)
for an example iterating over the Throwable's trace elements.
Handling Errors
Now that you have the capacity to process JavaScript errors and
convert them back to Scala traces, you need to actually receive the
errors. If you want to globally handle uncaught errors set a function
to window.onerror to capture errors. As of this writing, the
function signature in Scala.js isn't ideal for handling all
information, so in youi I use js.Dynamic to set it to what I need
(see:
https://github.com/outr/youi/blob/e66dc36a12780fa8941152d07de9c3a52d28fc10/app/js/src/main/scala/io/youi/app/ClientApplication.scala#L35).
Also, notice that in ErrorTrace it supports multiple incoming types
of errors (ErrorEvent, Throwable, and a more generic scenario).
This is because in JavaScript the errors come in different ways based
on what's happening. This is a fairly complex topic, and why I
created this functionality in youi to simplify things.
Not nearly as brief an overview as I would have liked, but this isn't a simple problem to solve. The source-map GitHub project (https://github.com/mozilla/source-map) has decent documentation and is what I used originally to write my solution (with some added trial and error). If the information I've provided is incomplete I'd recommend reading more there as it should provide the majority of information, and probably better explained.
I am creating HTTP request using Apache HTTP Client version 4.3.4. I see there are some classes like HttpGet,... and there is also a class BasicHttpRequest. I am not sure which one to use.
Whats the difference and which one should be used in which condition ?
BasicHttpRequest is provided by the core library. As its name suggests it is pretty basic: it enforces no particular method name or type, nor does it attempt to validate the request URI. The URI parameter can be any arbitrary garbage. HttpClient will dutifully transmit it to server as is, if it is unable to parse it to a valid URI.
HttpUriRequest variety on the other hand will enforce specific method type and will require a valid URI. Another important feature is that HttpUriRequest can be aborted at any point of their execution.
You should always be using classes that implement HttpUriRequest per default.
I was just browsing the 4.3.6 javadoc attempting to locate your BasicHttpRequest and was unable to find it. Do you have a reference to the javadoc of this class?
I would be under the impression that BasicHttpRequest would be a base class providing operations and attributes common to more than one HttpRequest. It may be extremely generic for extension purposes.
To the first part of your question, use HttpGet, HttpPost etc for their specific operations. If you only need to HTTP/GET information then use HttpGet, if you need to post a form or document body, then use HttpPost. If you are attempting to use things like the Head, Put, Delete method, then use the correspoding HttpXXX class.
There are many ways to handle errors in RESTful api:s. Simplifying a solution is sometimes a need becase of system requirements and domain policys.
Stack Overflow is doing a simplification with their own api using the http status code 400 for all errors (https://api.stackexchange.com/docs/errors) and then embedding their own error codes in the respons.
This is a solution that does follow the REST pattern but probably have other advantages. One advantage I can think of is that error codes within the response can be more system specific than using only errors available in the http protocol. Is there any more advantages of using the Stackoverflow pattern for handling REST errors?
I think that you must leverage the HTTP status codes to notify the REST client what happens (if processing is successful, if an error occurs) but this corresponds to high-level hints.
You generally need to associate an error payload that provides a thinnest description(s) of the error(s) and something structured so programmatic REST client can understand and handle them. You are free to choose the structure of such payload.
Here are what I commonly use (described using the JSON format but it's not linked to a particular format):
{
errors: [
{
"message": "my message",
"code": "ERR12",
},
{
"message": "my message",
"code": "ERR13",
"field": "fieldName"
}
]
}
Some errors can be general but also linked to a particular field of the request representation.
Moreover I think that we can leverage than other 4xx codes since the code 400 is a bit general. Here are some than could be used:
400: a general error telling the request isn't correct
405: if you try to use an HTTP method that isn't supported by the resource
409: error with optimistic locking
412: if the preconditions fail before executing the processing of the resource method
415: if the format of the provided representation isn't correct or the requested media type isn't supported
422: error when validating the input representation. Whereas it comes from WebDAV, you could use it (see for example the Github API).
You can notice that some of these methods (405, 415) are natively supported by REST frameworks (for example Restlet).
In the context of Restlet, the error management can be done like described in this answer: JSON Representation of a HTTP 400 for Restlet Client. This can give you some hints for your implementation even without this framework.
Hope it helps,
Thierry
I have a Java client that calls a RESTEasy (JAX-RS) Java server. It is possible that some of my users may have a newer version of the client than the server.
That client may call a resource on the server that contains query parameters that the server does not know about. Is it possible to detect this on the server side and return an error?
I understand that if the client calls a URL that has not been implemented yet on the server, the client will get a 404 error, but what happens if the client passes in a query parameter that is not implemented (e.g.: ?sort_by=last_name)?
Is it possible to detect this on the server side and return an error?
Yes, you can do it. I think the easiest way is to use #Context UriInfo. You can obtain all query parameters by calling getQueryParameters() method. So you know if there are any unknown parameters and you can return error.
but what happens if the client passes in a query parameter that is not implemented
If you implement no special support of handling "unknown" parameters, the resource will be called and the parameter will be silently ignored.
Personally I think that it's better to ignore the unknown parameters. If you just ignore them, it may help to make the API backward compatible.
You should definitely check out the JAX-RS filters (org.apache.cxf.jaxrs.ext.RequestHandler) to intercept, validate, manipulate request, e.g. for security or validatng query parameters.
If you declared all your parameters using annotations you can parse the web.xml file for the resource class names (see possible regex below) and use the full qualified class names to access the declared annotations for methods (like javax.ws.rs.GET) and method parameters (like javax.ws.rs.QueryParam) to scan all available web service resources - this way you don't have to manually add all resource classes to your filter.
Store this information in static variables so you just have to parse this stuff the first time you hit your filter.
In your filter you can access the org.apache.cxf.message.Message for the incoming request. The query string is easy to access - if you also want to validate form parameters and multipart names, you have to reas the message content and write it back to the message (this gets a bit nasty since you have to deal with multipart boundaries etc).
To 'index' the resources I just take the HTTP method and append the path (which is then used as key to access the declared parameters.
You can use the ServletContext to read the web.xml file. For extracting the resource classes this regex might be helpful
String webxml = readInputStreamAsString(context.getResourceAsStream("WEB-INF/web.xml"));
Pattern serviceClassesPattern = Pattern.compile("<param-name>jaxrs.serviceClasses</param-name>.*?<param-value>(.*?)</param-value>", Pattern.DOTALL | Pattern.MULTILINE);
I am desperately searching for an ASN.1 compiler that will successfully parse a predefined ASN.1 definition I got from a customer.
None of the products (free or commercial) so far was able to parse the definition, which is XER based and has some transient RXER dependency - when I specify the relevant ASN.1-definitions manually (taken from the RFCs), the compiler also emits parser errors.
The relevant code line is (simplified):
MYMSG ::= SEQUENCE
{
msgID [ATTRIBUTE] [250] UTF8String OPTIONAL,
msgType UTF8String
}
Every compiler complains about the [ATTRIBUTE] token, so I found this is part of the ASN.X specification defined in RFC 4912 and also depends on support for RXER in RFC 4910, see also X.680-1.
Problem is every compiler I tried does not seem to support these encoding schemas out of the box and fails to parse the definitions mentioned in the RFCs, e.g. for RXER and all definitions that use this encoding I get:
"RXER.asn", line 20
(AdditionalBasicDefinitions): A1139W:
The default encoding reference 'RXER'
for the module
'AdditionalBasicDefinitions' is
unknown and all encoding instructions
within the module identified by this
encoding reference will be ignored.
RXER INSTRUCTIONS
(Note: all dependent modules like ASN.X include the instruction "RXER INSTRUCTIONS" immediately after the "DEFINITIONS"-tag, which is not understood by any compiler I tried).
I tried openasn1 (www.openasn1.org) - funny thing is that I have some old and partially functional Java mapping objects in the code I got that was generated by openasn1! - the online compiler at http://lionet.info/asn1c/asn1c.cgi and various commercial tools like Objective Systems ASN1C v6.4.1 at http://www.obj-sys.com/Cnge641Dwld/acv64kits.php (they even have a current Eclipse plugin), Marben http://www.marben-products.com/asn.1/tce_java.html and unigone http://www.unigone.com/en/products/Asn1Compiler/description
I always get an error similar to this:
ASN.1 grammar parse error near line 13 (token "ATTRIBUTE"): parse error, unexpected TOK_capitalreference, expecting TOK_number
Am I missing something obvious like IMPORTs or other definitions/compiler flags?
I managed to compile the schema and generate the needed Java mapping classes. I had to use the commercial OSS Nokalva compiler, as all free tools I tried failed on (E)XER encoded schemata.
There were also some errors in the schema I received, so here is what I had to do:
first I added the XER-instructions in the DEFINITIONS-line along with the usual Tags
directive:
DEFINITIONS XER INSTRUCTIONS AUTOMATIC TAGS ::=
in the footer, I added the XER encoding directive:
ENCODING-CONTROL XER GLOBAL-DEFAULTS
MODIFIED-ENCODINGS
when using XER encoding, you have to explicitly specify tags to avoid ambiguities in syntax:
[ATTRIBUTE] [TAG: 0]
instead of the ambiguous definition
[ATTRIBUTE] [0]
All these problems were resolved by consulting this nice writeup on EXER-encoding, definitely a good read and thanks to Nokalva for this helpful documentation!