|
|
|
Whoa ... I (and referenced mailing list discussion) got this all wrong .. I think. After more debugging:
The good news is that using XFire client to access e.g. that book example service positively does work offline on e.g. a laptop not connected to the Internet or any local network at all, at least in 1.1.2 (have not tested previous). The bad news is that the error handling for HTTP errors, e.g. miss-spelt service URLs that lead to an HTTP 404 is quite confusing, and probably the cause of what I was experiencing, and presumably 'sol myr' who initially posted the issue to the list. I did some tests, and here is what happens if you access a miss-spelt service URLs (with a correct/existing host/port) in different combinations:
Tomcat's HTML 404 error page is not valid XHTML; XFire asks StAX to parse it, which complains - Internet or not. However under Jetty (via XFireHttpServer-based test case) and most likely other servlet containers that return valid XHTML including DOCTYPE in case of 404-like errors, as well as Tomcat when returning a page like XFire's "Services:" page in XHTML, e.g. because a */services/ URI, without actually naming a service, make StAX retrieve the http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd So it actually does all make perfect sense: XFire does not retrieve "retrieve some of the standard WS schemas", only the XHTML DTD in case of error pages; I actually verified this with a custom XMLResolver as suggested by 'sol myr' in the "work around" (which now doesn't look like it's the needed approach). Wouldn't it be much clearer and avoid this confusion in the future if the exception would be something like XFireFault: Server returned 404 for [URI] in such cases? So I guess if an HTTP server returns a 404 or 500 or something else than 200, XFire client should never attempt to parse the HTTP body of the response as XML... or is this valid in SOAP? How does it work for SOAP Faults, is that still HTTP #200, or is that a #500? I found some code in SimpleMessageSender and assume there is something similar in the CommonsHttpMessageSender, but it should probably be changed to throw a more specific error as suggested above, and not parse XML. Actually, coming to think of it, even if the HTTP return code is 200, it could of course well be invalid XML, e.g. an HTML page, or binary, if you "miss-spelt" the URL. While above is being addressed, additional better error handling in that case, something like XFireFault: Server returned invalid SOAP response for {URI} instead of e.g. XFireFault: www.w3.org, Caused by: java.net.UnknownHostException: www.w3.org would make sense, too? PS: How to change JIRA issue summary & priority? PPS: Having said all this... I wonder if it is possible for a valid SOAP request / response to contain e.g. a schemaLocation, causing XFire / StAX to attempt to fetch a schema after all (again, not what happened here; just thinking aloud). Is that possible? Probably not in the outgoing SOAP request created by XFire.. but could it be in the incoming response? Completely disable schema validation by default in StAX so this doesn't cause problems in Internet-disconnected environments - IFF this is a potential issue at all? I think we definitely can add some other resolver. As you said, StAX is responsible for this somehow, but I don't know how to turn it off offhand. I agree it should be off by default and we'll have to do this for 1.2.
I added some code to check http error code, but no all cases can be handled this way. Soap fault ( very valid soap message ) is send with 500 error code, so we cannot find out if this a real server error or just fault returned.
( Dan, is this requried by any spec to send faults with server error code http error ? ) Hm... I see. I guess I would have done some "heuristics", e.g. along those lines: IFF the HTTP return code is NOT 200 or 500, then abort with an Exception like XFireFault: Server returned 404 for [URI]. Else, so if HTTP return code IS 200 or 500, attempt to parse XML and interpret as SOAP. If that fails "due to XML parsing or something similar" [I am thinking catch(TheXMLParsingSuperclassException), not catch(Exception)] then abort with an Exception like XFireFault: Server returned invalid XML/SOAP response for [URI]. What do you think?
Is your JIRA and Subversion linked - i.e. can I see the diff/patch (curiosity, mainly) and comment/help? BTW, on my PPS: I meanwhile realized, after discussion with a colleague, that schema validation ("add some other resolver") is an entirely different topic... nothing gets validated here, StAx does not, can not, validate the incoming or outgoing SOAP just like that (unless you already have dedicated code for that that I haven't seen?). But you could validate the incoming and outgoing because you do have the schema in the WSDL (the schemaLocation that I first wrote probably is never there). That could be an interesting additional new In- and OutHandler (if you don't have it already) that some people may be interested in using and (manually) adding to the chain. I wouldn't include it by default though, for speed. Again that's a completly separate story from this, and maybe a new possible Enhancement? (Of course, the WSDL could reference a schema via URL, in which case you could be back to what started this discussion, but this time the real meaning of that error, I mean not being able to download that schema when validating... you could probably offer to configure that Handler to use local copies, then.) Currently i'm doing only, lets say , research, so there is not much to show (only some hooks ). But i would like to have all error code handled in one way ( all code >= 400 + 301 which is used by http client for error 404 in some cases ), thats why i'm trying to solve error 500 problem in case of regular soap faults first.
I'm also adding ability to access XMLInputFactory properities via config/api, so you can disable e.g supportDTD, what may help solving one of the problem you reported. if you want to comment
I commited folowing code // IF 0 is return then no error occour, in other way return error code public int hasError(){ So all error codes except 500 willbe handled and message won't be parserd. As you see i exclued error code 500 becasue XFire send this code with every SOAP fault, but when Dan will be back, i plan to talk to him about this, so we can handle this error code also. You can give it a try, if this want solve every problem you reported, let me know, then i'll commit acces to stax properties code. I see the your in the condition, but personally I think I would have treated this the other way around, with a condition like:
if( statusCode !=500 && statusCode != 200 ){ or maybe if( statusCode !=500 && statusCode >= 300 ){ You probably think that's too risky? I'd argue that within that code you get e.g. an 300 that's still an indication of a problem, as any e.g. redirects would have to be resolved by the HTTP client library (JDK or commons) and that code can't do anything about it, so has to consider it an error? That's just my thinking... How do you handle if your hasError() returns 0 but there is an XML/SOAP Parsing issue? There is one particular case where I believe this is quite likely to happen: A #500 code due to a "real" internal server error, that is not returned as a SOAP Fault with proper XML in the Body, but as a Servlet Container (Exception Stacktracing showing) HTML Error page. That's why I would, even if hasError() == 0 do something like: catch(TheXMLParsingSuperclassException) [not catch(Exception)] then abort with an Exception like XFireFault: Server returned invalid XML/SOAP response for [URI]. (And log the received response (body) if in DEBUG, and/or maybe better include it in a special Exception, for the caller to decide.) Actually, maybe doing anything based on the HTTP response code is not very safe... how about ONLY doing the idea in the paragraph above, that is as long as there is a valid/parsable SOAP message in the response, handle it, otherwise throw a clearer Exception than is the case today? I'm closing this as I don't think its actually an issue (feel free to reoopen if it is). I know that we do require you to be online for a build at the moment which sucks, but getting the a list of services does work regardless - which I believe you've confirmed in this thread Michael.
Certainly. I saw some code from Tomasz in the 1.2 in SVN that should address this. (I actually haven't really had a chance yet to check it out though.)
PS: The Issue title is very misleading now, this isn't at all about being online anymore, but I was unable (or too dumb) to change the title... it should probably be something like "Improved error handling for HTTP errors like 404 etc." |
|||||||||||||||||||||||||||||||||||||||||||||||||||||
Whatever StAX is looking for (Schema for http://schemas.xmlsoap.org/soap/envelope/
, xmlns:xsd="http://www.w3.org/2001/XMLSchema or http://www.w3.org/2001/XMLSchema-instance
NS? I don't entirely understand, because validation is off by default isn't it?) should probably be included as a resource in the XFire (Core) JAR. Other frameworks included e.g. their DTD in their JAR and always use that fetching of a remote one.
By the way... not sure what all to include. E.g. if you use WSSecurity, more stuff is probably going to be fetched, so that all would have to be included I guess? Or somehow make it not go trying get any of this.
Will also attach the full error (stack trace) that occurs under this condition; makes it easier to find this.