简体   繁体   中英

handling application and business failure scenarios for a java REST API using exceptions

I am developing a Java application and in my resource class I have all JAX-RS API methods defined. Also I am using dependency injection in my resource class to delegate each task to its own service class:

class Resource {

    // Services are injected.
    // Each service has a couple of failure scenarios.
    // Exp. Request Not valid, Id not valid, Database internal error, etc.
    DBService dbService;
    validationService validationService;
    searchService searchService;

    @GET(user/:id)
    public User getUser(int id) {
        try {
            validationService.validate(request);
            dbService.getUser(id);
            searchService.index(request);
            ...
        } catch (UserNotFoundException e) {
            // return proper http response code and message
        } catch (UserBannedException e) {
            ...
        } catch (DBInternalError e) {
            ...
        } ... 

    }
}

For each of failure scenarios in each Service class I am creating a specific Exception for that failure scenario and throwing it in Service class and handling all of these exceptions in API Resource class. I am using Exception as a signal to my Resource about failure scenario and return proper HTTP status code and message.

A complain I am getting is that I am creating a lot of Exception classes and my Resource class has a long list of catch blocks for different failure scenarios.

One suggested solution was that for example in my validationService I return a false boolean instead of exception and in my resource I put an if/else statement and return proper status code. However I don't like this solution because it makes my api full of if/else statements and less linear.

My question is , is it OK to have many exception classes for my use case and is there any better architecture for my use?

I suggest not catching them in your Resource layer.

Your service layer should be aware of the business logic, so do your checking and validation and throw your business exceptions with a proper error message and let Exception Mappers - https://docs.oracle.com/javaee/7/api/javax/ws/rs/ext/ExceptionMapper.html catch them and create correlated responses.

This way you don't have lots of try catch block nor if else statements .

Example:

PersonResource.java

@RequestScoped
@Path("/person")
@Produces({ "application/json" })
@Consumes({ "application/json" })
public class PersonResource {

    public PersonResource() {}

    @Inject
    PersonService personService;

    @POST
    @Path("/add")
    public void addPerson(Person person) throws MyValidationException{
        personService.add(person);
    }
...

PersonService.java

@RequestScoped
public class PersonServiceImpl implements PersonService {

    @Inject
    PersonDAO personDAO;

    @Transactional
    @Override
    public Long add(Person person) throws MyValidationException {

    //checking for existing person
    List<Person> list = personDAO.find(person.getName(), person.getDob());

    //if not found, save new person
    if(list == null || list.isEmpty()){
        Long id = personDAO.save(person);
        return id;
    }

    //otherwise throw exception
    String message = "Person already exists: '" + person.getName + "'";
    throw new MyValidationException(message);
}
...

ValidationExceptionMapper.java

@Provider
public class ValidationExceptionMapper implements ExceptionMapper<MyValidationException>{

    @Override
    public Response toResponse(MyValidationException e) {
        e.printStackTrace();
        String errorMessage = e.getMessage();
        return Response.status(Response.Status.BAD_REQUEST)//or whatever other status is more appropriate
                .entity(errorMessage)
                .build();
    }
}

So this way you can have as many Exception Mappers as you have business exceptions created, so your business or resource layer don't get polluted with all the exception handling.

The exception mappers know how to deal with the exceptions hierarchy too.

And let the client deal with the response error status and body (error message).

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM