First time using websockets. I have two machines that need to communicate using them. The server works fine, if I send a message with Postman, it replies correctly.
For the client I used one of the examples I found, like this. But in the client, when I create the WebsocketClientEndpoint :
final WebsocketClientEndpoint clientEndPoint =
new WebsocketClientEndpoint(new URI("ws://myserver.com/endpoint"));
it calls the onOpen and immediately after the onClose, returning a 1011 close reason, that I read is an unexpected condition in the server.
I would need some clue to analyse what can be happening, because as I said, the server replies well in Postman. The url is the same, of course. The examples I find are quite identical, and I am not doing anything different. Any idea?
My fault. As indicated by user207421, I should have checked what was really arriving to the server. The client was not sending hardcoded data. I was sending a JSON to it and it was forwarding it to the server. That server replied well to the same JSON if sent directly. The thing was that the client, in the deserialization and serialization, was sending the final reconstructed JSON with a missing field, and that made the server fail to reply. As dumb as that. The risk of assuming things.
First, I would recommend not to try to instantiate an instance of WebsocketClientEndpoint() as the only implementation of the class I can find uses static connect() methods, which require either an existing instance of WebSocketClient() or WebSocketContainer() - See this example. Instead, I would recommend creating a class that extends WebSocketClient and work with that instead - see an implementation of that here.
Also, another thing that might cause a different sort of problem is the possibility of an Unhandled Exception causing code execution to prematurely abort. The URI class throws a URISyntaxException, and if you are not wrapping your new URI object instantiation in a try/catch block or denoting the current scope method/class as throws URISyntaxException (or throws Exception to handle the other exceptions that might be thrown by WebsocketClient() as well) and have the thrown Exception(s) handled in a try/catch block in outer calling context, your code may be crashing due to that.
Related
Apologies: I don't have a simple test case that reproduces this problem, as it happens very intermittently. However, I would greatly appreciate some help regarding how to even begin diagnosing the issue.
I have a Jersey server running on Tomcat.
When the client makes a request, sometimes a response from a totally different request is mixed in with the correct response.
The "correct" request can be of any kind, but the "bad" response which gets mixed in is always from an SSE stream (EventOutput) or an AsyncResponse.
For example, this is the output received by a client through a normal request:
event: message_sent
id: 1
data: {"value":"hello world"}
{"event-id":"13"}event: message_sent
id: 2
data: {"value":"hello world"}
The genuine response {"event-id":"13"} is present... but surrounding that there are two erroneous SSE events.
The method to handle this request returns simply:
return Response.created(uri).entity(eventId).build();
So I don't understand at which point the unwanted data gets sent (unless Response.created() is returning a response object which had already been used for an SSE stream).
The server logs always show the correct output. We know the client is not at fault, however, as we used a packet sniffer to confirm the responses are malformed.
Notes:
For SSE streams, I always check that the EventOutput is not closed before writing to them
When writing to AsyncResponse objects, I always check isSuspended() first (and they are injected with the #Suspended annotation)
Again, any hints or pointers would be such a great help. I've run out of ideas!
After a lot of research, I've concluded that my problem must be (of course) a user error even though I couldn't reproduce the error when I removed the apache proxy from the equation. In my case, I had to be more careful about when considering EventOutputs as closed -- since you can only tell if the connection is open when trying to write to it. In general though, my findings are:
A bug of this kind occurs when you keep references to response objects around, and then write to them after Tomcat has re-used them for another request. This could be a list of e.g. AsyncResponse or EventOutput objects which you need to keep around to resume or write to at a later time.
However, if it's a bug which is difficult to track down and you need a solution, there is a Tomcat setting which will disable the re-use of these objects at the cost of performance, as it says here: https://tomcat.apache.org/tomcat-8.0-doc/security-howto.html
Setting org.apache.catalina.connector.RECYCLE_FACADES system property
to true will cause a new facade object to be created for each request.
This reduces the chances of a bug in an application exposing data from
one request to another.
(Don't be confused by the name; RECYCLE_FACADES=true means that the facades will not get reused, and new ones will get created as they are needed).
There are examples of application bugs like this only manifesting when behind an apache proxy, so if the bug disappears if you access Tomcat directly it doesn't necessarily mean that apache is at fault.
As I say, it's unlikely for this to be caused by a bug in Tomcat, Apache or the mod_proxy_ajp... but if you are an unlucky one, you can try using another connector (mod_jk, for example).
I know a lot has been discussed around exception handling, however I need some advice specific to my situation.
I am currently working on a Spring MVC application with Controller->Services->DAO layers. The service classes catch mainly two kinds of exceptions HibernateException and IOException.
HibernateException because service needs to perform rollback if a transaction did not succeed and IOException since it is an unchecked exception and needs to be caught or thrown and I prefer the first option.
Now what would be a better way of handling these further up in the stack :
Should I rethrow these exceptions to the controller and in the
ExceptionHandler of the controller send a HTTP error-code 500
Or in the catch block create the normal JSON response object, setting status=failure and the appropriate error message and return this to the Controller?
Exception Handling convensions:
There is a saying that, best way of handling Exception is not to handle it!
For Spring's convention of controller<->service<->dao layers, Exception handling mechanism is known as Bubble up. Any exception occurs in the dao or service layer, you should pop it up to the controller layer (by adding throws XXXException in dao and service layer's method signature, is the most common way). Only controller layer should handle Exceptions.
Here is a nice tutorial of how you can handle exceptions for REST with spring.
Send HTTP Status code 500 or JSON object with status:
Sounds like you are writing API with Spring MVC. Look, when you are writing API's you should follow the proper conventions. It is Globally accepted that for internal server errors you send HTTP response with code 500, that means internal server errors.
There are number of causes for what you should not send JSON response in this case. One of the main cause is the implicit assumption of your API client. That is HTTP response with code 200 with a JSON object means every thing went normal. And thus the client side business logic may reflect that assumption which is wrong eventually.
Here you can see some API error code conventions for some well-known organizations:
twitter
LinkedIn
Facebook Graph API
I assume that you have not come so far yet as to create a client and therefor can pick 100% for yourself.
If so I would also recommend to use 1, for the main reason that using the correct status codes can go a long way in your API, as well as it's a very easy solution to your problem. You can write some neat code for your error handling.
Another major reason why you should use your first point is because you can easily re-use the error handling for other APIs, resources or webapps.
For example an enum with all your errors, and what status code you consider them to be, and you can also include what log level you want them to be.
public enum ExceptionMapping {
IllegalArgumentException(IllegalArgumentException.class, 400, LogLevel.ERROR),
If your goal is to build a neat API for unknown clients I would recommend reading more about REST level 3 (http://martinfowler.com/articles/richardsonMaturityModel.html) where you includes hypermedia links to create an API which allows the client to "browse" your full API. It's more work for the client since they have to be smarter but it can provide you with very nice features such as breaking a large part of your API without the client even noticing.
I have a binder service and a client that live in different processes. Using AIDL, when the client calls into my remote binder service, there are times that I need to relay an error (exception) back to the client.
However, from my understanding, this is not possible. I tried throwing a "RemoteException" from my binder service to see what will happen, and I get
Uncaught remote exception! (Exceptions are not yet supported across processes.)
in my logcat.
Since it looks like this is not possible, what is the best approach for informing the client of an error? I was thinking I can just convert my AIDLs to use C-style interfaces in which I just return an error code (and 0 on success), but this looks ugly.
Is there a better approach?
Your remote method can return a Parcel that contains the result data or an Exception if there is an error. See the Parcel#writeException method. I believe that this is how Android exceptions make it back when performing actions on a ContentProvider that lives in another process. There are many ways to return the result data including using the Bundle class.
Your manager class can hide the implementation details by unparcelling and returning the data or throwing the unparcelled exception so users never interact with the Parcel.
Here is a link to the source for Parcel#writeException.
I have a a misbehaving calling application which I dont have the source for, which confronted with a non 200 http status- quietly logs an error/information message...
I need to be able to make it actually exit with some kind of error message. happen to know that it does catch some exceptions.... so this is my strategy
replace some part of the http client code with one that throws an exception and then let the exception bubble up to this app, where upon I expect it to exit...
Is there any other way/better to do this ? if not better simply suggestions of alternatives also welcome.
Thanks
That seems like a reasonable approach. You could also try using an aspect - if you use load-time weaving, you can add aspects to the client application at the point where you want it to throw an exception (though without the source code it will be tricky to work out the exact pointcut).
I was using the java.net.URL.openStream() method to retrieve content from the server. I recently ran into an issue where the HTTP Response code indicated an error, but instead of throwing an exception, the stream still was read anyway. This caused the error to appear much later in the execution and proved to be a red herring. As far as I can see, when you have opened a stream using this method, there is no way to check the HTTP response code.
The only way I could find to handle this properly was to obtain a connection before opening the stream:
HttpURLConnection conn=(HttpURLConnection) url.openConnection()
#Code updated with scotth's suggestion
if(!String.valueOf(conn.getResponseCode()).startsWith('2'))
throw new IOException("Incorrect response code "+conn.getResponseCode()+" Message: " +getResponseMessage());
rawIn=conn.getInputStream()
InputStream in=conn.getInputStream()
So do you agree? Are there any good circumstances for using openStream safely, or should its use be discouraged. It is worth noting that Sun uses the method in their tutorial code for reading directly from a URL. Then again, the code throws Exception so it isn't exactly a bastion of good coding practices.
openStream() works just fine if you want your class to be shielded from changes in the type of url - to change between, for example, absolute file paths (file:///), jar-contained resources, and potentially other protocols maybe even with custom protocol handlers (scotth://foo.bar).
However, as you've found its abstraction is quite high, so if you desire to know any details whatsoever about the nature of the interaction with the resource you'll need to openConnection() and cast as you see fit.
Re: other status codes - you probably want to glance at RFC2616 - if all you care about is "successful" you can just check that String.valueOf(conn.getResponseCode()).startsWith('2').