I am trying to throw a timeout exception in the code below. I tried a simple condition but it's not the proper way.
My question is how can I distinct the timeout exception from SOAPException?
URL endpoint = new URL(null,
urlStr,
new URLStreamHandler() {
// The url is the parent of this stream handler, so must create clone
protected URLConnection openConnection(URL url) throws IOException {
URL cloneURL = new URL(url.toString());
HttpURLConnection cloneURLConnection = (HttpURLConnection) cloneURL.openConnection();
// TimeOut settings
cloneURLConnection.setConnectTimeout(10000);
cloneURLConnection.setReadTimeout(10000);
return cloneURLConnection;
}
});
try {
response = connection.call(request, endpoint);
} catch (SOAPException soapEx) {
if(soapEx.getMessage().contains("Message send failed")) {
throw new TimeoutExpirationException();
} else {
throw soapEx;
}
}
The following lines are from open jdk source code of call method. In the code they are only catching with Exception (also with chaining? comment). I don't think there is other way unless Oracle jdk handles this differently.
You can still try something like if(soapEx.getCause() instanceof SomeTimeoutException) (not sure if this will work)
try {
SOAPMessage response = post(message, (URL)endPoint);
return response;
} catch (Exception ex) {
// TBD -- chaining?
throw new SOAPExceptionImpl(ex);
}
If you want to check the source code HttpSoapConnection
After some hours of testing I found the proper way to distict the SOAPException from Timeout related exceptions. So the solution is to take the parent cause field of the exception and check if it's an instance of SocketTimeoutException.
try {
response = connection.call(request, endpoint);
} catch (SOAPException soapEx) {
if(soapEx.getCause().getCause() instanceof SocketTimeoutException) {
throw new TimeoutExpirationException(); //custom exception
} else {
throw soapEx;
}
}
Related
I have Jenkins plugin written in Java. I am capturing all the workflows of execution of plugin in a integer variable in three ways 0(2xx workflows), 1(4xx workflows), 2(5xx workflows) and sending them to SignalFX for metrics. Since this is not an API and errors will be mainly caught in try catch workflow.
I wanted to ask how to read error codes from exception class and categorize them in 2xx, 4xx or 5xx. Are there some rules which I can follow by?
try {
Thread.sleep(60 * 1000);
} catch (InterruptedException e) {
sendToSignalFX(0,data); // 0 means successful state
}
Some of the exceptions classes I will be using are -
Exception, IOException, InterruptedException, ParserConfigurationException, SAXException
I believe you may have to add a method to identify the failure reason from e.getMessage() for one OR have a custom exception to help with your case.
Also if it’s an HTTP request-related exception (from the error response code mentioned in the question details) or something, you may want to add a custom exception, instead of throwing the original exception. In the custom exception, you can add a custom field to get errorCode from the response code.
// MyCustomException.java
public class MyCustomException extends Exception {
String errorReason;
int errorCode;
public MyCustomException(Throwable throwable, String errorReason, int errorCode) {
super(errorReason, throwable);
this.errorReason = errorReason;
this.errorCode = errorCode;
}
}
And in your request handler code:
try {
// otherCode which might cause IOException
// ...
Response response = myHttpRequest();
if (!response.isSuccessful()) {
// identify the error code and set corresponding errorCode to MyCustomException. errorCode
int errorCode = 0;
// parse response.getStatusCode() or equivalent of the library and reassign the value of errorCode
throw new MyCustomException(e, e.getMessage(), errorCode);
}
// ...
// otherCode which might cause IOException
} catch (Exception | IOException e) {
throw new MyCustomException(e, e.getMessage(), 0);
}
I am using several layers of classes to fetch data from internet and display in Android app.
Activity - ViewModel - Repository - NetworkDataSource ----// Internet
I handle HTTP error messages in NetworkDataSource, where I have try/catch block. However, I would like to propagate this error message to Activity, where I would display a Toast.
How to fire an event in the Activity from NetworkDataSource class?
static String getResponseFromHttpUrl(URL url) throws IOException {
HttpURLConnection urlConnection = (HttpURLConnection) url.openConnection();
String response = "";
try {
urlConnection.setConnectTimeout(5000);
int responseCode = urlConnection.getResponseCode();
switch (responseCode) {
case HttpURLConnection.HTTP_OK:
response = getPayload(urlConnection);
break;
case HttpURLConnection.HTTP_UNAVAILABLE:
throw new IOException("HTTP_UNAVAILABLE");
case HttpURLConnection.HTTP_NOT_FOUND:
throw new IOException("HTTP_NOT_FOUND");
case HttpURLConnection.HTTP_GATEWAY_TIMEOUT:
throw new IOException("HTTP_GATEWAY_TIMEOUT");
}
} catch (IOException e) {
Log.v(TAG, e.getMessage());
throw new IOException(e.getMessage());
} finally {
urlConnection.disconnect();
}
return response;
}
You can use the eventbus. BY eventbus you can send event and can receive ay anyplace you want in the app on whichever thread you want.
https://github.com/greenrobot/EventBus
You can use Interface callbacks/RxJava in addition to EventBus as pointed out by Kirtan.
I have a feign client with this external call:
#RequestMapping(method = RequestMethod.GET, value = "GetResourceA", consumes = "application/json")
#Cacheable("ResourceA")
List<Stop> getResourceA() throws MyOwnException;
And in my application.yml I have this setting:
hystrix:
command:
default:
execution.isolation.thread.timeoutInMilliseconds: 1000
fallback.enabled: false
Now if getResourceA times out, i.e. it takes more than one second to complete, I either get this:
com.netflix.hystrix.exception.HystrixRuntimeException: getResourceA timed-out and no fallback available
Or, if I define a fallback from which I throw my own exception, I get this:
com.netflix.hystrix.exception.HystrixRuntimeException: getResourceA timed-out and fallback failed.
Can I not throw my own exception from the fallback?
What if I wish to throw my own exception when the service is down? I would like to not have a fallback (because I have no reasonable value to return from the fallback), but instead throw my own error that I can catch and let the program resume. Can someone help me out with this?
Update after the answer from Ben:
So I tried the approach with catching HysterixRuntimeException and checking what caused it, but ended up with this ugly code:
try {
getResourceA();
} catch (HystrixRuntimeException e) {
if (e.getFailureType().name().equals("TIMEOUT")) {
throw new MyOwnException("Service timed out");
}
throw e;
}
All that to be able to throw MyOwnException on a timeout. Surely there must be another way?
You should be able to get the exception you throw from your fallback by getting the cause of the HystrixRuntimeException
So, to handle your custom exception, you can do this:
try {
getResourceA();
} catch (HystrixRuntimeException e) {
if (e.getCause() instanceof MyException) {
handleException((MyException)e.getCause());
}
}
You can use an ErrorDecoder and return your own exception from there and then use an exception handler. I had a similar problem and solved it like this:
public class ExceptionHandlerControllerAdvice extends ResponseEntityExceptionHandler
...
#ResponseStatus(BAD_REQUEST)
#ExceptionHandler(HystrixRuntimeException.class)
public ExceptionResponse handleHystrixRuntimeException(HystrixRuntimeException exception) {
if(exception.getCause() instanceof MyException) {
return handleMyException((MyException) exception.getCause());
...
And then in my Configuration class for my FeignClient:
#Bean
public ErrorDecoder feignErrorDecoder() {
return new ErrorDecoder() {
#Override
public Exception decode(String methodKey, Response response) {
return new MyException("timeout");
}
};
}
That way you don't need multiple nested getCause()
If you want replace timeout exception throw by hystrix,you can write like this:
try {
testClient.timeoutTest();
} catch (HystrixRuntimeException e) {
Throwable fallbackException = e.getFallbackException();
if (fallbackException.getCause().getCause() instanceof CustomException) {
log.info("customer exception!");
}
}
(Seemingly) simple static method that invokes a known good web service.
Service returns HTTP 500 / Internal Server Error if a matching record is not found, but the recovery block of invokation is never executed.
Am I missing the obvious or doing something blatantly stupid?
public static Promise<Property> ByPhone(String phone) {
return WS.url("http://localhost:9000/data/property/" + phone)
.get ()
.map (
new Function<WS.Response, Property>() {
public Property apply (WS.Response response) {
System.out.println("got here: " + response.getStatusText());
Property property = null;
try {
property = _mapper.readValue(response.getBody(), Property.class);
} catch (Throwable t) {
t.printStackTrace();
}
return property;
}
}
).recover (
new Function<Throwable, Property>() {
public Property apply (Throwable t) {
System.out.println("never get here");
t.printStackTrace();
return null;
}
}
);
}
recover helps one recover from uncaught exceptions. In this case an HTTP 500 response doesn't result in an uncaught Throwable
Presumably, 500 means that the following block will throw an error
property = _mapper.readValue(response.getBody(), Property.class);
However, you have this wrapped in a try catch block already.
First off, I'm an experienced programmer, but have very little familiarity with Java. I have about two years of experience with it, eight years ago.
I'm getting a NullPointerException in the following code:
public static void handle(HttpServletRequest request,HttpServletResponse response)throws IOException,ServletException {
Response gfexResponse = null;
try {
ActionFactory actionFactory = ActionFactory.getInstance();
String requestURL = request.getRequestURI();
String actionId = actionFactory.getActionId(requestURL);
IAction action = actionFactory.createAction(actionId);
ActionEvent event = new ActionEvent(request, 0, actionId);
gfexResponse = action.execute(event);
} catch (Exception ex) {
gfexResponse = new Response();
gfexResponse.setError(ex.getMessage());
gfexResponse.setOutcome(IViewConstants.ERROR);
} finally {
if(request.getParameter("loginId") != null){
request.setAttribute("loginId", request.getParameter("loginId"));
}
if(gfexResponse.getMessage()!= null){
request.setAttribute("message", gfexResponse.getMessage());
}
if(gfexResponse.getError()!= null){
request.setAttribute("error", gfexResponse.getError());
}
if (gfexResponse.getContentType() != null) {
response.setContentType(gfexResponse.getContentType());
OutputStream outputStream = response.getOutputStream();
outputStream.write(gfexResponse.getOutputData());
outputStream.flush();
outputStream.close();
}
if(gfexResponse.getOutcome() != null){
RequestDispatcher dispatcher = request.getRequestDispatcher(gfexResponse.getOutcome());
dispatcher.forward(request, response);
}
}
}
Here's the StackTrace:
[6/18/13 17:10:04:518 GMT] 00000023 ServletWrappe E SRVE0068E: Uncaught exception thrown in one of the service methods of the servlet: GfexServlet. Exception thrown : java.lang.NullPointerException
at com.svl.gfex.handlers.RequestHandler.handle(RequestHandler.java:44)
at com.svl.gfex.servlets.GfexServlet.processRequest(GfexServlet.java:43)
at com.svl.gfex.servlets.GfexServlet.doPost(GfexServlet.java:39)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:763)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:856)
at com.ibm.ws.webcontainer.servlet.ServletWrapper.service(ServletWrapper.java:966)
at com.ibm.ws.webcontainer.servlet.ServletWrapper.service(ServletWrapper.java:907)
at com.ibm.ws.webcontainer.filter.WebAppFilterChain.doFilter(WebAppFilterChain.java:118)
at com.ibm.ws.webcontainer.filter.WebAppFilterChain._doFilter(WebAppFilterChain.java:87)
at com.ibm.ws.webcontainer.filter.WebAppFilterManager.doFilter(WebAppFilterManager.java:701)
at com.ibm.ws.webcontainer.filter.WebAppFilterManager.doFilter(WebAppFilterManager.java:646)
at com.ibm.ws.webcontainer.servlet.ServletWrapper.handleRequest(ServletWrapper.java:475)
at com.ibm.ws.wswebcontainer.servlet.ServletWrapper.handleRequest(ServletWrapper.java:463)
at com.ibm.ws.webcontainer.webapp.WebApp.handleRequest(WebApp.java:3129)
at com.ibm.ws.webcontainer.webapp.WebGroup.handleRequest(WebGroup.java:238)
at com.ibm.ws.webcontainer.WebContainer.handleRequest(WebContainer.java:811)
at com.ibm.ws.wswebcontainer.WebContainer.handleRequest(WebContainer.java:1433)
at com.ibm.ws.webcontainer.channel.WCChannelLink.ready(WCChannelLink.java:93)
at com.ibm.ws.http.channel.inbound.impl.HttpInboundLink.handleDiscrimination(HttpInboundLink.java:465)
at com.ibm.ws.http.channel.inbound.impl.HttpInboundLink.handleNewInformation(HttpInboundLink.java:394)
at com.ibm.ws.http.channel.inbound.impl.HttpICLReadCallback.complete(HttpICLReadCallback.java:102)
at com.ibm.ws.tcp.channel.impl.AioReadCompletionListener.futureCompleted(AioReadCompletionListener.java:152)
at com.ibm.io.async.AbstractAsyncFuture.invokeCallback(AbstractAsyncFuture.java:213)
at com.ibm.io.async.AbstractAsyncFuture.fireCompletionActions(AbstractAsyncFuture.java:195)
at com.ibm.io.async.AsyncFuture.completed(AsyncFuture.java:136)
at com.ibm.io.async.ResultHandler.complete(ResultHandler.java:194)
at com.ibm.io.async.ResultHandler.runEventProcessingLoop(ResultHandler.java:741)
at com.ibm.io.async.ResultHandler$2.run(ResultHandler.java:863)
at com.ibm.ws.util.ThreadPool$Worker.run(ThreadPool.java:1510)
The stacktrace points to this line:
if(gfexResponse.getMessage()!= null){ <-------- this line
request.setAttribute("message", gfexResponse.getMessage());
}
This code was being maintained by an offshore contractor, but the company laid off all the contractors. For my sins, I was given the job of fixing it.
If anyone can help me figure out why I'm getting this error, I would appreciate it.
That error indicates that the gfexResponse object itself is null (i.e. action.execute(event) is returning null in the code above, and no exception is being thrown)
Your basic outline is this:
public static void handle(HttpServletRequest request,HttpServletResponse response)throws IOException,ServletException {
Response gfexResponse = null;
try {
//Try to get your gfexResponse
} catch (Exception ex) {
//Provide a default gfexResponse
} finally {
//Do some stuff with gfexResponse
}
}
This is bad practice: you're attempting to use exception handling for flow control. Further, you assume that the method you use to get gfexResponse will throw an exception if it fails, which clearly it does not. (Some simple debugging/tracing will reveal this directly.)
What you should be doing is the following:
public static void handle(HttpServletRequest request,HttpServletResponse response)throws IOException,ServletException {
Response gfexResponse = null;
try {
//Try to get your gfexResponse
//Make sure you got your response object and throw SomeAppropriateException if not
//Do some stuff with gfexResponse
} catch (SomeAppropriateException e) {
//properly handle this case
} catch (Exception ex) {
//properly handle the general case that something else failed (But you should try to be more specific)
} finally {
//remove any resources that might not be properly cleaned up if an exception is thrown.
}
}
Are you sure that gfexResponse is getting an actual value from action.execute(event); (in the try {})? I'd guess that action.execute(event); is returning null.
To solve the immediate pain - your action.execute(event); call is likely returning null. However, this can be mitigated in several ways:
Null checking, or
Turning the try-catch block into its own separate method call, to return Response.
From there, the finally block becomes the main focus of your method, and you can check for null without having to worry about finally.
Actually problem lies at the line gfexResponse = action.execute(event);
only chance in the below line to get NPE here is gfexResponse is null
if(gfexResponse.getMessage()!= null){ <-------- this line
change it to
if(gfexResponse!=null && gfexResponse.getMessage()!= null){ <-------- this line