I wonder how to handle exceptions correctly within a client server application. My client sends an information to the server(thread) which receives it within its run method.
I have already read something about uncaught exception handling when dealing with exceptions in the run method but want to know if this is the correct way to do it in my case.
I want to catch the exception on the client side.
I have in mind to do the following:
//Server
run(){
try{
...
}
catch(Exception e){
clientoutputstream.write(...); //transmitting the error
}
}
Any other suggestions?
You should put a try { } catch (IOException) around your read() call so you know if the other end has closed the connection. The other thing you might want to do is to put a try { } catch(Throwable) { } around the processing code so you can manually close the socket (Be very careful about catching Throwable) But if you just let the thread die the Socket will be closed when the object is garbage collected or when it times out
Related
I ran in to a problem using a Jetty Websocket when connecting to an endpoint and sending Strings to it.
First off, the websocket is used to connect to a Sonos speaker using a Jetty websocket. Jetty version is 9.4.48 .
These connections can of course be interrupted by a loss of power, connection issues, ...
The problem occurs when trying to clean up the threads when a the connection is interrupted. The HTTPclient is able to end all it's threads succesfully, except for 1 thread. This is a thread that is created when the Jetty
session.getRemote().sendString(message);
is called.
I think the problem lies with the fact that I keep sending websocket strings but they never get answered. I found this thread-leak with JProfiler.
Things I've tried already:
Using a SendStringByFuture or SendString with a new WriteCallback:
session.getRemote().sendString(message, new WriteCallback() {
#Override
public void writeFailed(Throwable throwable) {
log.info(LOG_TAG + " -- Write Failed!");
log.info(throwable.getMessage());
log.info(throwable.getCause().getMessage());
try {
session.getRemote().flush();
} catch (IOException e) {
throw new RuntimeException(e);
}
}
#Override
public void writeSuccess() {
log.info(LOG_TAG + " -- Write Success!");
}
});
Any ideas what is causing this thread to stick around?
I've had test cases that caused OutOfMemroyExceptions because of this thread leak.
Thanks in advance
I expected the thread to get removed by the garbage collector since it isn't used anymore, but instead the threads stay alive and can cause outofmemoryexceptions when JVM is unable to start a new thread.
I have a class that wraps socketChannel and has a close() method as follows:
public void close() {
// ... logic ...
try {
socketChannel.close();
} catch (IOException e) {
// ???
}
this.isConnected = false;
}
I want in the end of this operation that socketChannel will be closed and not registered to its selector. I read and found that the above code is sufficient for that, but what happens if I got an IOException?
My feeling is that "swallowing" it is enough, but am i missing something?
The answer will depend on whether it matters that the close threw an exception. And if it matters, the next question is whether you need to do something about it ... other than reporting it.
Scenario #1.
A web server gets an exception when closing the output stream it sent the response on. A typical cause is that the user closed his web browser or lost his network connection at the wrong moment. The server-side exception doesn't matter (to the server / server admin) and is not even worth logging.
Scenario #2.
You are doing something that involves talking to multiple servers, and it is important to know that they all "got the message". If an exception occurs in the close, that may be an indication that that didn't happen. Probably you need to log this. Maybe you need to tell the servers. Maybe you need to cause some enclosing transaction to rollback.
For years I've been wondering what the correct way to close a listening ServerSocket in Java is. My implementations always work like this, they:
Create a new ServerSocket(int).
Start a thread that calls its accept() method in a while (true) loop.
Start another thread when accept() returns (client connects) that reads from the client until it disconnects. The accept thread then continues with another accept() call.
But when I want to close the ServerSocket because my application is exiting, I've never found another way of doing so other than calling it's close() method (after I've closed all client Sockets), which causes accept() to throw a SocketException, I catch that and break from the while (true) loop in the accept thread, causing all my threads to exit.
I think this is ugly, strictly speaking there is no exception occurring, closing my ServerSocket is part of my programs normal operation.
Is there really no other way of doing this without causing an Exception to be thrown?
Thanks.
I've never found another way of doing so other than calling it's close() method (after I've closed all client Sockets),
You can set a flag closed = true; and open a dummy connection to wake up the accept()ing thread which checks the flag before continuing.
which causes accept() to throw a SocketException,
A SocketClosedException which is expected behaviour here.
I catch that and break from the while (true) loop in the accept thread,
If you catch it outside the loop, you don't need to also break out of the loop. If the exception is thrown and you have set closed = true you can discard the exception.
BTW I would do
while(!serverSocket.isClosed()) {
causing all my threads to exit.
There is no particular reason you need to have this, but you can choose to do this if you want.
I think this is ugly, strictly speaking there is no exception occurring,
An exceptional condition is happening. What is not happening is an Error.
closing my ServerSocket is part of my programs normal operation.
Or you could say it is operating normally when it is running and not shutting down.
Thanks for your comment.
You can set a flag closed = true; and open a dummy connection to wake up the accept()ing thread which checks the flag before continuing.
Opening a new Socket to close an existing one? IMO that is one of the worst sins ever.
A SocketClosedException which is expected behaviour here.
Actually it doesn't throw a SocketClosedException but a SocketException, the following code:
try {
final ServerSocket ss = new ServerSocket(1234);
new Thread(new Runnable() {
#Override
public void run() {
try {
ss.accept();
} catch (Exception ex) {
ex.printStackTrace();
}
}
}).start();
ss.close();
} catch (Exception ex) {
ex.printStackTrace();
}
Produced the following output:
java.net.SocketException: Socket is closed
at java.net.ServerSocket.accept(ServerSocket.java:494)
at Main$1.run(Main.java:12)
at java.lang.Thread.run(Thread.java:744)
If you catch it outside the loop, you don't need to also break out of the loop. If the exception is thrown and you have set closed = true you can discard the exception.
BTW I would do
while(!serverSocket.isClosed()) {
That would work, but I think this should work without setting flags and catching Exceptions.
An exceptional condition is happening. What is not happening is an Error.
Or you could say it is operating normally when it is running and not shutting down.
I don't agree. It is normal behaviour for applications to be exiting. They may always do so.
Why doesn't the accept() method just returns null when close() is called? That would be so much easier.
i have a jar file: myServerSide.jar,
this jar takes request from client apps, processes them, each one ina thread and renders a response
i've put my jar on linux, but i want it to be ALWAYS running
if i do java -jar myServerSide.jar & for no reason it stops after a while
i also tried deamon -- java -jar myServerSide.jar & it also stops
do you know the reason why?
what should i do,so that it stays always running, and never exit.(is it necessary to make it a service)
thanks for your help
(i'm hosting my jar on linode (a VPS) if it is related)
this is the code for my server
try
{
FTLogger.getInstance().logMessage(Level.FINE, "S: Connecting...");
ServerSocket serverSocket = new ServerSocket(SERVERPORT);
while (true)
{
Socket client = serverSocket.accept();
Thread serverThread = new Thread(new ServerThread(client));
serverThread.start();
}
}
catch (Exception e)
{
FTLogger.getInstance().logMessage(Level.SEVERE, "S: Error getting connection", e);
}
in my logs, i don't see any error, and when working the jar works as it should.
(if you're sure that it's smthg from my code, should i open another question, and discard this?)
if i do java -jar myServerSide.jar & for no reason it stops after a while
The reason it stops could be (probably is) in your code.
Debugging it should tell you why it stops.
Assuming you don't have access to screen you can try nohup java -jar myServerSide.jar > log.out &
If an java.lang.Error occurs it wouldn't be catched by
catch (Exception e) {
...
}
only
catch( Throwable t ) {
...
}
would do it.
I think that you should ensure this programatically by something like infinite loop waiting for requests from client and delegating them to separate threads for processing:
// this is very high-level and obviously a exit point from this loop should be provided
while (true) {
Request r = waitForRequest();
processRequestInNewThread(r);
}
Or is there something more you need that I'm missing? Maybe a sample code from your implementation of request handling will help.
You should give us some code. The first thing that pops into my mind is that you need to make sure your method that accepts the connections from clients need to run in an infinite loop. For example:
while (true) {
acceptAndParseRequest();
}
If you launch a java application, and you embed your code into a loop:
while(true){
...
}
It will never stop, the only reason why it should stop it's because an exception is launched (do you consume resources inside the while) ?
In case it really stops, try to understand what is the problem in this way:
while(true){
try{
... your code ....
}catch(Throwable t){
system.out.println("This is my problem:" + t.printStackTrace);
}
}
Sure it helps
Do you see any possibility to log server side exceptions?Consider such code on the server side:
catch (Exception ex) {
throw new IllegalStateException (ex);
}
The exception is caused by the client-side call. Of course, exception will be noticed on the client-side. Is there any way to somehow handle it on the server side, without catch runtime exceptions? Some kind of handler that would allow me for example to log the stacktrace of the exception?
Any ideas?
you can wrap your server instance in a java.lang.reflect.Proxy and implement your server-side logging in the proxy. just make sure the proxy is exported, not the server implementation.
Commonly, the top level server method will have throws Exception.
If you wrap your "do it" code in this method with a try-catch Exception, and you can log it there as still throw it.
public Response myServerTopLevelMethod() throws Exception {
try {
myImplCode();
catch (Exception e) {
Log.error(e);
throw e;
}
}
Now you have some options about what to do. The basic options are:
You can just re-throw the Exception (as above)
You can play nice and return a "something bad happened" response - like many web servers do
Here's an example of option 2:
public Response myServerTopLevelMethod() throws Exception {
try {
myImplCode();
catch (Exception e) {
Log.error(e);
return new Response("Yikes! Something exploded... we'll look into it.");
}
}
Incidentally, the "Log + throw" of option 1 is one of the few times that you ever want to do this; at the top level method. At other times you should generally either log or throw, not both.
There are RMI system properties that will automatically log server-side exceptions for you. See the links on the RMI Home Page.