Recover from ProtocolException in HttpClient - java

I sometimes get such stacktraces when downloading from HttpClient:
java.net.SocketTimeoutException: Read timed out, at java.net.SocketInputStream.socketRead0(Native Method),
...
at org.apache.commons.httpclient.ContentLengthInputStream.read(ContentLengthInputStream.java:170),
[wrapped]
org.apache.commons.httpclient.ProtocolException: The server example.com failed to respond with a valid HTTP response,
I've tried to recover from these errors by using a custom HttpMethodRetryHandler, but it seems I don't even enter the retryMethod(). It may be due to the fact the wrapped exception in SocketTimeoutException is a ProtocolException, which inherits from HttpException, and thus is not eligible to recovery, if I correctly understand the code of HttpMethodDirector class.
while (true) {
execCount++;
try {
...
} catch (HttpException e) {
// filter out protocol exceptions which cannot be recovered from
throw e;
} catch (IOException e) {
// test if this method should be retried
http://hc.apache.org/httpclient-3.x/exception-handling.html says
ProtocolException signals a violation of the HTTP specification. It is
important to note that HTTP proxies and HTTP servers can have
different level of HTTP specification compliance. It may be possible
to recover from some HTTP protocol exceptions by configuring
HttpClient to be more lenient about non-fatal protocol violations.
How can i achieve that? Is there an API allowing this or should I implement the mecanism to retry requests failing with HttpException?

There are a number of http.protocol.* configuration parameters that are defined here. You need to carefully look at each one of them and figure out what is the optimum leniency you need.

Related

Getting the original cause of a JschException

I need to do some handling for a JschException. It looks like "JschException" is thrown regardless of what the specific cause of the exception was (ie. SocketTimeoutException, UnknownHostKey, or AuthFail). What's the best way for me to go about determining the original specific cause? Is my only option to parse the e.getMessage() String?
Here is the basic structure.
try {
session = jSch.getSession(getUsername(), host);
session.setUserInfo(user);
session.connect();
} catch (JSchException e) {
e.printStackTrace();
// Here I need to identify the cause and handle accordingly.
}
As an example here is the top trace for a timeout and a authentication failure respectively.
com.jcraft.jsch.JSchException: Session.connect: java.net.SocketTimeoutException: Read timed out
com.jcraft.jsch.JSchException: Auth fail
If it matters, I want to initiate a retry of the try block for authentication errors, and fail out for timeouts errors.
Indeed, JSch throws exceptions is a way that makes it impossible to find the root cause (except for parsing the exception message).
JSch is full of code like this:
catch(Exception e) {
...
throw new JSchException("Session.connect: "+e);
}

Getting exception while connecting a server through SSH

I am trying to connect to an external server from my Solaris server using SSH in my Java application. Some how we are getting exception while authenticating the user but after 60min. How can we decrease the timing to get the exception to 5min or so.
There was a problem while connecting to IP:PORT
java.io.IOException: There was a problem while connecting to IP:PORT
The time difference between time2 and time3 are around 60min. I want to decrease this time.
Please find below the code snippet that we are using.
try
{
timeout = 1;
if (connection == null)
{
//time1
connection = new ch.ethz.ssh2.Connection(getIpAddress(), Integer.parseInt(getPort()));
if (connection == null)
{
System.out.println("connection is null");
}
else
{
//time2
connection.connect(null, timeout, 0);
}
}
}
catch (Exception t)
{
//time3
System.out.println(t.getLocalizedMessage());
System.out.println(t.toString());
}
Edit1: After checking SSH related configuration files I found KeyRegenerationInterval having a value of 3600s. Is this useful to resolve this issue. What might be the outcome if I decrease its value to some 30min or 5min.
Let me summarize your problem, please correct me if something wrong.
You can not connect to SSH server.
An exception raised after 60 mins.
According to below Throws section of method connect(ServerHostKeyVerifier, int, int), I guess you might be facing issue due to a buggy proxy which doesn't return proper HTTP response. Using direct internet connection to see whether the issue is gone.
Throws:
java.io.IOException - If any problem occurs, e.g., the server's host key is not accepted by the verifier or there is problem during
the initial crypto setup (e.g., the signature sent by the server is
wrong).
In case of a timeout (either connectTimeout or kexTimeout) a SocketTimeoutException is thrown.
An exception may also be thrown if the connection was already successfully connected (no matter if the connection broke in the mean
time) and you invoke connect() again without having called close()
first.
If a HTTP proxy is being used and the proxy refuses the connection, then a HTTPProxyException may be thrown, which contains
the details returned by the proxy. If the proxy is buggy and does not
return a proper HTTP response, then a normal IOException is thrown
instead.
Try setting the "kexTimeout" (Timeout for complete connection establishment (non-negative, in milliseconds). Zero means no timeout.) to non-zero
connection.connect(null, timeout, timeout);
Also, in your catch print the full stacktrace to verify where the timeout occurs
catch (Exception t) {
//time3
t.printStackTrace();
}

How to handle websocket #OnError

What's the correct way of handling a websocket error besides logging it?
Regarding onError(), the Endpoint documentation states that:
Developers may implement this method when the web socket session
creates some kind of error that is not modeled in the web socket
protocol. This may for example be a notification that an incoming
message is too big to handle, or that the incoming message could not
be encoded.
There are a number of categories of exception that this method is
(currently) defined to handle:
connection problems, for example, a socket failure that occurs before the web socket connection can be formally closed. These are modeled as SessionExceptions
runtime errors thrown by developer created message handlers calls.
conversion errors encoding incoming messages before any message handler has been called. These are modeled as DecodeExceptions
Are all of these types of exceptions fatal, causing the websocket to close?
Should the onError() method close the websocket (call Session.close()) if an error occurs?
So far, I assumed that it's my responsibility to cleanly close the session, informing the client about the close reason. This is why my onError() tried invoking session.close() if session.isOpen() returned true, but this caused tomcat (8.0.15) to throw a NullPointerException:
...
Caused by: java.lang.NullPointerException
at org.apache.tomcat.websocket.server.WsRemoteEndpointImplServer.onWritePossible(WsRemoteEndpointImplServer.java:96)
at org.apache.tomcat.websocket.server.WsRemoteEndpointImplServer.doWrite(WsRemoteEndpointImplServer.java:81)
at org.apache.tomcat.websocket.WsRemoteEndpointImplBase.writeMessagePart(WsRemoteEndpointImplBase.java:444)
at org.apache.tomcat.websocket.WsRemoteEndpointImplBase.startMessage(WsRemoteEndpointImplBase.java:335)
at org.apache.tomcat.websocket.WsRemoteEndpointImplBase.startMessageBlock(WsRemoteEndpointImplBase.java:264)
at org.apache.tomcat.websocket.WsSession.sendCloseMessage(WsSession.java:536)
at org.apache.tomcat.websocket.WsSession.doClose(WsSession.java:464)
at org.apache.tomcat.websocket.WsSession.close(WsSession.java:441)
at my.package.MyEndpoint.onWebSocketError(MyEndpoint.java:229)
... 18 more
Is this a tomcat bug, a misunderstanding on my part, or both?
Edit: It seems that the Java EE websocket example dukeeetf2 assumes that errors are fatal; and that there's no need to close the session. The errors are logged, and the session is removed:
#OnError
public void error(Session session, Throwable t) {
/* Remove this connection from the queue */
queue.remove(session);
logger.log(Level.INFO, t.toString());
logger.log(Level.INFO, "Connection error.");
}
#OnError method invocation does not mean that Session will be closed; You can do whatever you want, it depends in the contract specified by your application.
stacktrace from tomcat implementation seems like a bug.
ad dukeeetf2 sample - seems like this code contains other assumptions - Endpoints does not throw an exception, so everything caught here is from underlying WebSocket framework implementation. That does not really mean that there is an "Connection Error"; I would maybe do close right away (if this is how I wan't my application to handle errors); this implementation could result in opened connections without any messages.
I saw this is a bit dated but ended up here today when looking for this info.
Depending on how you rely on the state of the websocket, you need to close the session manually, at least for the javax.websocket implementation.
In my case, the error happening was causing a problem for the websession client administration implementation, so I closed the session as in the above example.
I think it depends on what you need, but it certainly does not do a close session in this implementation.

ClientAbortException at application deployed at jboss with IE8 browser

I am having following exception for application deployed at Jboss, Browser is IE8
2012-03-19 09:17:12,014 WARN [org.apache.catalina.core.ContainerBase.jboss.web]. [localhost]] Exception Processing ErrorPage[errorCode=404, location=/internalError.jsp]
ClientAbortException: java.net.SocketException: Broken pipe
at org.apache.catalina.connector.OutputBuffer.doFlush(OutputBuffer.java:327)
It seems that browser closed the socket before server writes internalError.jsp to it.
Please suggest how to solve it , or atleast how I can hide this exception.
Thanks
Hikumar
You cannot solve it. You cannot control whether the client will press Esc, or hastily click a different link, or close the browser, or have its machine crashed, etcetera, while your server is still handling the HTTP request/response.
You can "hide" it by a global filter (mapped on /*) which does something like this:
try {
chain.doFilter(request, response);
}
catch (ClientAbortException e) {
// Ignore.
}
This however brings a servletcontainer-specfic dependency in your code. The filter in question would result in NoClassDefFoundError on a servletcontainer of a different make which doesn't use Tomcat specific ClientAbortException. You might want to check the class simple name instead. Make use of the advantage that it's a subclass of IOException:
try {
chain.doFilter(request, response);
}
catch (IOException e) {
if (!e.getClass().getSimpleName().equals("ClientAbortException")) {
throw e;
}
}

java rmi server side exception handling

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.

Categories