Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Factoring try catch

Tags:

I have a Java EE application with dozens of web services using the same pattern:

public Response myWebService1() {     try {         // do something different depending on the web service called     } catch (MyCustomException e1) {         return Response.status(409).build();     } catch (UnauthorizedException e2) {         return Response.status(401).build();     } catch (Exception e3) {         return Response.status(500).build();     } } 

Is that possible to factorize this piece of code?

like image 347
cheb1k4 Avatar asked Jan 10 '17 09:01

cheb1k4


People also ask

Is try catch a good practice?

It is perfectly fine to use two try/catch blocks if the algorithm requires it. I have often used a new try/catch in a catch block to ensure a safe cleanup so a blanket statement is not possible.

What is try catch method?

The try-catch statement consists of a try block followed by one or more catch clauses, which specify handlers for different exceptions. When an exception is thrown, the common language runtime (CLR) looks for the catch statement that handles this exception.

Does Try Catch affect performance?

try/catch will only effect performance if an Exception is thrown (but that still isn't because of try/catch , it is because an Exception is being created). try/catch/finally does not add any additional overhead over try/catch .

Which is better try catch or throws?

From what I've read myself, the throws should be used when the caller has broken their end of the contract (passed object) and the try-catch should be used when an exception takes place during an operation that is being carried out inside the method.


2 Answers

If this is a JAX-RS environment, see Tunaki's answer, handling this is specifically catered for and wonderfully simple.

If not:

You can have a functional interface accepting a function that can throw exceptions and returns a Response:

@FunctionalInterface public interface Responder {     Response handleRequest() throws Exception; } 

(As Dici points out, you could make that a generic ThrowingSupplier or similar, since you're allowing it to throw Exception.)

Then have a helper method accepting an instance of it:

private static Response respond(Responder responder) {     try {         return responder.handleRequest();     } catch (MyCustomException e1) {         return Response.status(409).build();     } catch (UnauthorizedException e2) {         return Response.status(401).build();     } catch (Exception e3) {         return Response.status(500).build();     } } 

...and use it via a lambda:

public Response myWebService1() {     return respond(() -> {         // Do stuff here, return a Response or throw / allow throws on error     }); } 
like image 90
6 revs Avatar answered Nov 03 '22 19:11

6 revs


Since this is in a JAX-RS context, there is a much better way, that does not rely on catching a lot of different exceptions: use an ExceptionMapper. This is a built-in mechanism of JAX-RS 1.0 that translates an exception type into a proper Response object to send to the client.

In your case, you could have the following classes defined once in your application:

@Provider public class UnauthorizedExceptionMapper implements ExceptionMapper<UnauthorizedException> {    public Response toResponse(UnauthorizedException e) {       return Response.status(401).build();    } } 
@Provider public class MyCustomExceptionMapper implements ExceptionMapper<MyCustomException> {    public Response toResponse(MyCustomException e) {       return Response.status(409).build();    } } 
@Provider public class CatchAllExceptionMapper implements ExceptionMapper<Exception> {    public Response toResponse(Exception e) {       return Response.status(500).build();    } } 

The @Provider annotation tells the JAX-RS runtime to discover this class when scanning. This makes sure that, wherever in your code, if a MyCustomException is thrown (and not explicitly catched), a 409 response will be returned. The code in your application would simply become:

public Response myWebService1() {     // do something, and don't catch anything; just care about the happy path } 

The exception hierarchy is correctly taken into account. If the application code throws a MyCustomExceptionMapper, JAX-RS will look for an exception mapper registered with that type, and will go up the super class if it can't find one: this way, there can be a catch-all exception mapper handling every other case.

like image 20
Tunaki Avatar answered Nov 03 '22 20:11

Tunaki