Tipok
Tipok

Reputation: 695

Java generics api architecture

I'm implementing a strategy pattern for exceptions handling

 public class GlobalExceptionHandler {

    private interface Strategy<T extends Exception> {
        ErrorResponse extract(T e);
    }

    private static class ResponseStatusStrategy implements Strategy<ResponseStatusException> {
        @Override
        public ErrorResponse extract(ResponseStatusException e) {
            return ErrorResponse.builder()
                    .status(e.getStatus())
                    .message(e.getReason())
                    .description(e.getReason())
                    .build();
        }
    }

    private static class IllegalStateStrategy implements Strategy<IllegalStateException> {
        @Override
        public ErrorResponse extract(IllegalStateException e) {
            return ErrorResponse.builder()
                    .status(HttpStatus.INTERNAL_SERVER_ERROR)
                    .message(e.getMessage())
                    .description("")
                    .build();
        }
    }
    ....

I call this API like this:

Exception ex = ....; // function param
if (ex instanceof ResponseStatusException) {
    errorResponse = new ResponseStatusStrategy().extract((ResponseStatusException) ex);
} else if (ex instanceof IllegalStateException) {
    errorResponse = new IllegalStateStrategy().extract((IllegalStateException) ex);
} else {
    errorResponse = new EmptyStrategy().extract(ex);
}

Is there a more efficient and beautiful way to implement this? Idea gets me hint that I even didn't use interface method: "method extract(T e) is never used".

It would be great to have API like this:

    Strategy<???> strategy;
    if (ex instanceof ResponseStatusException) {
        strategy = new ResponseStatusStrategy();
    } else if (ex instanceof IllegalStateException) {
        strategy = new IllegalStateStrategy();
    } else {
        strategy = new EmptyStrategy();
    }
    errorResponse = strategy.extract(ex);

Upvotes: 0

Views: 119

Answers (1)

Jay Rajput
Jay Rajput

Reputation: 1898

You are trying to solve an object creational problem. You want a particular Strategy class object based on the StatusException class. Create a new class with a factory pattern to return you the correct object. Here is some dummy code inspired from your code.

private interface Factory {
    Strategy buildStrategy(Exception e);
}
private static class FactoryImpl implements Factory {
    public Strategy buildStrategy(Exception e) {
        if (e instanceof IOException) {
            return new Strategy1();
        } else {
            return new EmptyStrategy();
        }
    }
}

private interface Strategy<T extends Exception> {
    String extract();
}
private static class Strategy1 implements Strategy<IOException> {
    @Override public String extract() {
        return "Strategy1";
    }
}
private static class EmptyStrategy implements Strategy<NamingException> {
    @Override public String extract() {
        return "EmptyStrategy";
    }
}

public static void main(String[] args) {
    var f = new FactoryImpl();
    System.out.println(f.buildStrategy(new IOException()).extract());
    System.out.println(f.buildStrategy(new NamingException()).extract());
}

Upvotes: 2

Related Questions