How to handle read timeout exception in jersey client 1.8 - java

I am using jersey 1.8
to call an external service.
Here is my code.
try{
ClientResponse response = webResource.header(HttpHeaders.AUTHORIZATION, encodedHashString).type(MediaType.APPLICATION_FORM_URLENCODED_TYPE).post(ClientResponse.class, formData);
}catch(ClientHandlerException che){
//handelling code here
{
when read timeout exception occurs it gives ClientHandlerException and underlying exception is SocketTimeoutException. But question here is I can not just say that since its ClientHandlerException it is a timeout exception because this exception can happen for other client related errors.
what can be the exact code to handle it, I need to do some handeling if its a read timeout exception.

Try something like this:
try {
ClientResponse response = webResource.header(HttpHeaders.AUTHORIZATION, encodedHashString).type(MediaType.APPLICATION_FORM_URLENCODED_TYPE).post(ClientResponse.class, formData);
} catch(ClientHandlerException ex) {
handleClientHandlerException(ex);
}
private void handleClientHandlerException(ClientHandlerException ex) throws ClientHandlerException {
if (ex.getCause() instanceof SocketTimeoutException) {
// handelling SocketTimeoutException code here
}
throw ex;
}
In handleClientHandlerException you also can try something like ExceptionUtils#getRootCause from apache commons lang if cause isn't SocketTimeoutException to get the root cause.

You can use the Throwables.getRootCause method from guava!

Related

Spring framework springframework.cloud.netflix.feign.FeignClient connection error handling

I am trying to handle exceptions when a POST is done via #FeignClient
What I would like to do is to catch and log if there is a connection problem, for example if a provider that I am connecting is down and cannot reachable. I tried to catch it with java.net.ConnectException
but I got this compilation error which makes sense
Error:(113, 11) java: exception java.net.ConnectException is never thrown in body of corresponding try statement
So my question is, is there any way to handle this specific exception when the feign client is not reachable, so I can log it as connection problem.
My FeignClient interface
public interface PluginFeignClient {
#RequestMapping(path = "/prepare", method = RequestMethod.POST, consumes = APPLICATION_JSON_VALUE)
Map<String, Object> createPrepare(#RequestBody CreatePluginPrepareRequest request);
}
Service that calls feign client
try {
PluginFeignClient resource = commsService.buildServicerPluginClient(servicer.getName(), PluginFeignClient.class, applicationId, originatingIpAddress);
Map<String, Object> response = resource.createPrepare(pluginRequest);
prepareResponse = new PrepareResponse(response);
} catch (WpbCommunicationException e) {
LOGGER.warn("ComId={}, PayId={}: Exception building Stripe resource", storedPayment.getCompanyId(),
storedPayment.getPaymentId(), e);
throw e;
} catch (FeignException e) {
LOGGER.warn("ComId={}, PayId={}: Got FeignException calling plugin", storedPayment.getCompanyId(),
storedPayment.getPaymentId(), e);
if (e.status() == 400) {
throw new InvalidDataException(e.getMessage());
}
throw e;
} catch (Exception e) {
LOGGER.warn("ComId={}, PayId={}: Unknown error calling plugin", storedPayment.getCompanyId(),
storedPayment.getPaymentId(), e);
throw e;
}
So the question is I would like to add another catch to the service to handle connection exceptions. Any idea about what kind of exception feign client is throwing?
Thanks
This is easy to do implementing your own errorDecoder class and creating a custom exception for the feignClient.
Here is a little example to achieve it:
Feign Error Handling
In case of error errorDecoder will be triggered before finishing the transaction and you can handle the exception the way you like.

Handle REST Service in SpringBoot

I have below code use to POST JSON object to the following URL
HttpEntity messageEntity = new HttpEntity(message, buildHttpHeaders(getTerminalId()));
String theUrl = "http://123.433.234.12/receive";
try {
System.out.println("In try block");
ResponseEntity<Dto> responseEntity= restTemplate.exchange(theUrl, HttpMethod.POST, messageEntity, Dto.class);
} catch (HttpStatusCodeException ex) {
// get http status code
}
If the URL is invalid or service unavailable, I want it throw error status code like 404 or 503. Unfortunatelly it will always stop at the try block..Is there a way to solve that ?
Output
In try block
Edit
String theUrl = "http://123.433.234.12/receive" + transactionId; //invalid Id
try {
System.out.println("=========start=========");
ResponseEntity<Dto> responseEntity= restTemplate.exchange(theUrl, HttpMethod.POST, messageEntity, Dto.class);
System.out.println("=========end=========");
} catch (HttpStatusCodeException ex) {
String a = ex.getStatusCode().toString();
System.out.println(a);
}
Output
=========start=========
2017-09-22 14:54:54 [xles-server-ThreadPool.PooledThread-0-running] ERROR c.r.abc.jpos.JposRequestListener - Error HttpStatusCode 500org.springframework.web.client.HttpServerErrorException: 500 null
It stop and not display ========end ======== or any status code in catch block
Valid url
http://abc0/receive/hello
If I change to
http://abc0/recei/hello
I will get 404 in catch block, it look fine. But when I change to another url that not exits,example
http://123.433.234.12/receive
it is in try block .Why ????
With reference to this doc, you should catch RestClientException instead of just HttpStatusCodeException.
If you want to throw exception in specific scenarios you can do it like this
try {
restTemplate.exchange(...);
}
catch (RestClientException e) {
// implies error is related to i/o.
if (e instanceof ResourceAccessException) {
// java.net.ConnectException will be wrapped in e with message "Connection timed out".
if (e.contains(ConnectException.class)) {
// handle connection timeout excp
}
} else if (e instanceof HttpClientErrorException) {
// Handle all HTTP 4xx error codes here;
} else if (e instanceof HttpServerErrorException) {
// Handle all HTTP 5xx error codes here
}
}
for HttpClientErrorException you can get error code from excption as shown below
HttpClientErrorException clientExcp = (HttpClientErrorException) e;
HttpStatus statusCode = clientExcp.getStatusCode();
like wise, you could get error code for HttpServerErrorException.
As far as I remember RestTemplate.exchange method throws RestClientException. You have HttpStatusCodeException in your catch clause, which is only one of RestClientException subclasses.
The address you're trying to reach (http://123.433.234.12/receive) is not valid address, therefore you can't get ANY response from it (no 200s but no 500s or 400s too). Try to catch RestClientException and print its message to see what is going on. Then you can write some code to manage such situations.
Moreover if that does not work, try to go step by step and check wether ResponseEntity is null and what it has in its body. That's what I'm doing when I try to understand some method ;=)

Catch all Exceptions and also return custom Errors in Jersey

I want to catch all unexpected Exceptions in a jersey rest service.
Therefore i wrote an ExceptionMapper:
#Provider
public class ExceptionMapper implements javax.ws.rs.ext.ExceptionMapper<Exception> {
private static Logger logger = LogManager.getLogManager().getLogger(ExceptionMapper.class.getName());
#Override
public Response toResponse(Exception e) {
logger.log(Level.SEVERE, e.getMessage(), e);
return Response.status(Response.Status.INTERNAL_SERVER_ERROR).entity("Internal error").type("text/plain").build();
}
}
The mapper catches really all exceptions. Therefore i can't write:
public MyResult getById(#PathParam("id")) {
if (checkAnyThing) {
return new MyResult();
}
else {
throw new WebApplicationException(Response.Status.NOT_FOUND);
}
}
This is catched by the Mapper. Now i have to write:
public Response getById(#PathParam("id") {
if (checkAnyThing) { {
return Response.ok().entity(new MyResult()).build();
}
else {
return Response.status(Response.Status.NOT_FOUND).build();
}
}
Is this the correct way to catch all unexpected exceptions and also return errors (error codes) in jersey? Or is there any other (more correct) way?
WebApplicationException has a getResponse from which we can get the Response. So you can check for a WebApplicationException in your mapper. Maybe something like
#Override
public Response toResponse(Throwable error) {
Response response;
if (error instanceof WebApplicationException) {
WebApplicationException webEx = (WebApplicationException)error;
response = webEx.getResponse();
} else {
response = Response.status(Response.Status.INTERNAL_SERVER_ERROR)
.entity("Internal error").type("text/plain").build();
}
return response;
}
That way an instance of WebApplicationException thrown will just return the default response. This will actually handle some other exceptions also, not thrown explictly by your application. WebApplicationException has a few other exception under its hierarchy that are thrown by JAX-RS, for which predefined response/status codes are wrapped.
Exception Status code Description
-------------------------------------------------------------------------------
BadRequestException 400 Malformed message
NotAuthorizedException 401 Authentication failure
ForbiddenException 403 Not permitted to access
NotFoundException 404 Couldn’t find resource
NotAllowedException 405 HTTP method not supported
NotAcceptableException 406 Client media type requested
not supported
NotSupportedException 415 Client posted media type
not supported
InternalServerErrorException 500 General server error
ServiceUnavailableException 503 Server is temporarily unavailable
or busy
That being said, we could explicitly throw any of these exceptions in our code, just to give it more semantic value.
Generally speaking though, the example above may be unnecessary, unless you want to alter the response message/status code, as one can from the table above, the hierarchy of exceptions already have some general mapping. And in most cases, unexpected exceptions will already be mapped to InternalServerErrorException

Rest service throws exception : Best way to handle

I have a rest service which will throw an exception and I want to know what will be the best way to handle this.
So I have a rest service which can throw a userdefined exception and I am catching that inside the catch block and throwing that exception again ! and using rest framework to catch that. Similarly for non-user defined exceptions. I thought this will be good as I have number of rest services and all userdefinedexception code handling will be at a same place.
I would like to know is this the proper way of handling exception in rest service ?
I am using jersey.
// rest service
#POST
public void doSomething() {
try {
// ... some piece of code that can throw user defined exception as well as runtime exception
} catch(UserDefinedException e) {
throws new UserDefinedException(e);
} catch(Exception e) {
throws new ServiceException(e);
}
// Now I have a #Provider to catch this thrown exception
#Provider
public class UserDefinedExceptionHandler implements
ExceptionMapper {
public Response toResponse(UserDefinedException exception) {
ClientResponse clientResponse = new ClientResponse();
ResponseStatus status = new ResponseStatus();
clientResponse = handleUserDefinedException(exception, status, clientResponse);
return Response.ok(clientResponse).build();
}
// similarly for the ServiceException
Just raising error 500 at the server don't give much details on the error, one way to gracefully handle errors, is to wrap the response data in a structure with status and data, if the status is error, show the correct message.
something like this in json format :
{
"status": "error",
"data": {
"message": "detailed error message"
}
}
Handling exceptions in a REST service is not much different from handling exceptions in any other piece of code.
The only "convention" is to throw back an HTTP 400 if the exception is triggered by the client sending incorrect data and a 500 when your service is failing unexpectedly.

Handling Exception on Asynchronous Webservice Request

I am still new to implement web service request using Play!Framework 2.1 WS library. Now, I have problem on understanding the WS library behaviour.
Firstly, I have code like this :
public static Result espnRss() {
try {
// do request
return async(
WS.url("http://espnfc.com/rss/news?section=premierleague").get().map(
new F.Function<WS.Response, Result>() {
#Override
public Result apply(WS.Response response) throws Throwable {
return ok("Success!"); // success request
}
}
)
);
} catch (Exception e) {
// exception occured
return internalServerError("Oops, connect exception occured!");
}
}
When I try to request the espnRss action, I got SUCCESS response.
Then, I want to set WS timeout on the request. So, I changed my previous code like this :
public static Result espnRss() {
try {
// set request timeout for 1000 ms and do request
return async(
WS.url("http://espnfc.com/rss/news?section=premierleague").setTimeout(1000).get().map(
... // same as previous
)
);
} catch (Exception e) {
// exception occured
return internalServerError("Oops, connect exception occured!");
}
}
My internet connection is not fast (Download speed is about 40 KB/s) and I do that on purpose (set request time out for 1 second) to make exception handling code is executed.
But, I get default response from framework, not internalServerError response the code provided.
Execution Exception
[TimeoutException: No response received after 1000]
Can anyone explain me why the exception on WS request cannot be caught using my code above? How is the best way to handle exception using Play!Framework WS library?
To handle exception that occur on asynchronous request such as WS request with Play!Framework 2.1.0, there is method on Promise named recover(F.Function<java.lang.Throwable,A> function).
The method should be called when we want to handle all exception occured while requesting using WS library. So, I solved the problem using code that looked like following:
public static Result espnRss() {
// do request
return async(
WS.url("http://espnfc.com/rss/news?section=premierleague").setTimeout(100).get().map(
new F.Function<WS.Response, Result>() {
#Override
public Result apply(WS.Response response) throws Throwable {
return ok("Success!"); // success request
}
}
).recover( // to handle error occured on redeemed PROMISE
new F.Function<Throwable, Result>() {
#Override
public Result apply(Throwable throwable) throws Throwable {
// option to distinguish exception
if (throwable instanceof TimeoutException) {
return internalServerError("Oops, time out exception occured!");
} else {
return internalServerError("Oops, other exception occured!");
}
}
}
)
);
}
I am not familiar with the Play framework but async must be returning/using some kind of future. The request is actually performed in a separate Thread which Exceptions are obviously not caught by your try..catch handler.
There must be some function/method like onComplete that you can apply to async allowing you to test the result of running the request.

Categories

Resources