添加链接
link管理
链接快照平台
  • 输入网页链接,自动生成快照
  • 标签化管理网页链接

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement . We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Receiving the following error when going to this WebAPI service:
http://localhost:8084/WebAPI/vocabulary/concept/-1

javax.servlet.ServletException: org.springframework.dao.EmptyResultDataAccessException: Incorrect result size: expected 1, actual 0

Expected Result:
No error should be returned, and an empty object should return, or a HTTP 404 returned? Not sure how the restAPI should report the not found...can it return null?

Currently, a 404 is returned and the exception is logged as ERROR. With that said, I can add code to catch the exception or query for a list and get the first. The queryForObject method that is used expects a single result.

http://localhost:8080/WebAPI:> get vocabulary/concept/-1

GET http://localhost:8080/WebAPI/vocabulary/concept/-1

< 404 NOT_FOUND
< Server: Apache-Coyote/1.1
< Access-Control-Allow-Origin: *
< Access-Control-Allow-Headers: origin, content-type, accept, authorization
< Access-Control-Allow-Credentials: true
< Access-Control-Allow-Methods: GET, POST
< Access-Control-Max-Age: 1209600
< Content-Length: 0
< Date: Wed, 04 Feb 2015 16:38:08 GMT

This issue would apply to any WebAPI call that now uses getJdbcTemplate()
I believe this is a change in behavior from the previous release of WebAPI, before the change to spring , in the way no data found is handled.

This might be a useful background reference:

http://stackoverflow.com/questions/10606229/jdbctemplate-query-for-string-emptyresultdataaccessexception-incorrect-result

We need to broaden the scope of this issue. It is a change in behavior for ALL WebAPI methods that now call getJdbcTemplate() when no rows are found.

Another example: vocabulary search:
old behavior:
CALL: http://54.84.95.238:2020/WebAPI/vocabulary/search/notgoingtobefoundkeyword
RESPONSE: "[]"
returns empty JSON array string.

new behavior
returns http 404.

I recommend including Frank in the review/discussion of this issue because I expect he would need to update Hermes to handle any changes in the behavior of this latest version of the WebAPI. Perhaps those Hermes updates would be trivial to implement but we should give Frank a heads-up.

Agreed we need to come up with conventions regarding what to return.
With that said, your example returns a response of 200 and an empty body, for me. JdbcTemplate.query() should not throw the exception as JdbcTemplate.queryForObject does. Do you see an exception?

http://localhost:8080/WebAPI:> get vocabulary/search/notgoingtobefoundkeyword

GET http://localhost:8080/WebAPI/vocabulary/search/notgoingtobefoundkeyword

< 200 OK
< Server: Apache-Coyote/1.1
< Access-Control-Allow-Origin: *
< Access-Control-Allow-Headers: origin, content-type, accept, authorization
< Access-Control-Allow-Credentials: true
< Access-Control-Allow-Methods: GET, POST
< Access-Control-Max-Age: 1209600
< Content-Type: application/json;charset=UTF-8
< Content-Length: 2
< Date: Wed, 04 Feb 2015 18:35:45 GMT
http://localhost:8080/WebAPI:>

Given that it's only queryForObject() that has the different behavior for no rows returned then the impact is minimal.

queryForObject() is only called in the following routes:

/cohortdefinition/id
/vocabulary/concept/id
/vocabulary/info

/cohostdefinition/id (I think only CIRCE would depend on this call)

/vocabulary/concept/id (as discussed in the above thread)

vocabulary/info should always return a single row because it just has the following SQL query - so not a problem:

select VOCABULARY_VERSION
from @CDM_schema.VOCABULARY
where VOCABULARY_ID = 'None'

I think the distinction between the 404 that we're seeing above is an important one:

if you give it a bad url, 404 is expected. You asked for a resource, you didn't find it. I know that 404 is exactly what not found is, but i think this is where we're having a difference in philosophy around general RESTful services and their use in verbs and response codes....

In the case where where we have the correct URL, but we found no results, I don't think I'd like to see a 404 message because then i'd immediately expect that my url was malformed and it would send me on the wrong path.

I think this is again raising the question about what these URLs represent: path to resource, or path to service. If you think of the URL as a path to a service, the case of /someconceptid, the path to service is correct, it just didn't find anything, so don't return a 404.

I'm on the fence about returning an error for 'no content'...i don't consider looking for a concept that doesn't exist as an error....any more than if I try to get data for an analysis and there is no data, that I should not receive an error in that case either.

I guess we need to decide as a group what constitutes an 'error' and stick with it.

-Chris

Not sure. I need to check how the ajax libraries will interpret 204 vs 200; whether the async returns to the success or error handler, etc...

Update: The entire 2xx range will return to success in our handlers which means a 204 with empty returns would work for "no data" whereas a 404 is route not found.

No. Zero length array ends up having a body in the response (I.e. []) and a 200 OK response status. An example of this is the current /vocabulary/search endpoint. When returning null, you will get a 204 NO CONTENT. I guess we could have a convention that says collections will never be null (204) but all other singular return types (note I didn't say resources :)) return 204. Or we could return 204 across the board.

I'm reading up on 204, and it's problematic. In some cases, a 204 means that the display should not change, but if you are currently looking at some concept where you see a chart (chart is the object being returned from a service), if you pick another concept in that list that doesn't have a chart, 204 means that you should not change the display, and therefore you continue showing the chart for the original concept? That seems wrong. In other cases, (I think i read this in Jersey) returning a null sets a response status to the 204, but does not set content headers (the response type being applcation/json) and without that the javascript library can't determine how to handle the result. So you get some odd results in that case. Odd results also seems wrong...

The main complaint with returning a 404 is that you get the same message if you go to /vocabulary/concpt/1 or /vocabulary/concept/-1. In one case, you are going to an invalid service url, in the other, you are looking for a concept that is not found. The client can't tell the difference.

However, I found that you can build a response message with actual text that can give some information as to the url not going to a service vs. you got to the service, but the item is not found:

throw new WebApplicationException(Response.status(Status.NOT_FOUND)
                .entity("The requested concept was not found.").build());

Now, at least we can say the service was properly invoked, but the concept requested was not located.

Let me work with Frank and look at our client code to determine if dealing with these error statuses is a real headache when operating in the normal flow of an operation. (Exceptions should be used for exceptions, right?). Maybe it should be an error when accessing an invalid concept. Should it be an error when not finding Achilles data for a given concept? Or is that just something that just happens sometimes?

Trying something slightly different with the latest version of WebAPI. After reading through the list of available HTTP status codes (great read; if you are ever done reading everything else ever published you might want to consider this next) it appears that a 205 might be most appropriate.

205 Reset Content
The server successfully processed the request, but is not returning any content. Unlike a 204 response, this response requires that the requester reset the document view.

I've confirmed that when using jQuery's $.ajax method that this in fact does fall through to the success function as anticipated. When consuming data returned from the WebAPI where there is a possibility that an entity you request might not be found the client will need to interrogate the xhr.status property that is passed to the success handler as demonstrated here:

    var concept_promise = $.ajax({
        url: api_root + 'vocabulary/concept/' + concept_id,
        method: 'GET',
        contentType: 'application/json',
        success: function (c,status,xhr) {
                   var status = xhr.status;
    });

I suspect we will have to wait and see if this approach works as anticipated in more cases.

4xx codes indicate client error and 5xx codes server error (rfc7231 section 6). If we hold that requests for /vocabulary/concept/-1 are improperly-formed because the domain of concept IDs is non-negative-integers, 400 Bad Request may be suitable (rfc7231 section 6.5.1). One might also argue for 404 Not Found, but this does not preclude the resource being available sometime in the future (rfc7231 section 6.5.4) whereas 400 Bad Request seems to. My experience is that server-side frameworks that do validation of client input typically respond with 400 Bad Request upon failure.