简体   繁体   English

使用异常处理Java REST API的应用程序和业务失败方案

[英]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. 我正在开发Java应用程序,并且在资源类中定义了所有JAX-RS API方法。 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. 对于每个Service类中的每个失败方案,我都会为该失败方案创建一个特定的Exception,并将其抛出Service类中,并在API Resource类中处理所有这些异常。 I am using Exception as a signal to my Resource about failure scenario and return proper HTTP status code and message. 我正在使用Exception作为有关失败情况的资源信号,并返回正确的HTTP状态代码和消息。

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. 我收到的一个抱怨是,我正在创建许多Exception类,而Resource类却包含一长串针对不同故障情况的catch块。

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. 一个建议的解决方案是,例如,在我的validationService中,我返回一个错误的布尔值而不是异常,并且在我的资源中放入了一个if / else语句并返回正确的状态代码。 However I don't like this solution because it makes my api full of if/else statements and less linear. 但是我不喜欢这种解决方案,因为它使我的api充满了if / else语句,并且线性度降低了。

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. 您的服务层应该意识到的业务逻辑,所以做你的检查和验证,并用正确的错误信息会让你的业务异常,让异常映射器- https://docs.oracle.com/javaee/7/api/javax/ ws / rs / ext / ExceptionMapper.html捕获它们并创建相关响应。

This way you don't have lots of try catch block nor if else statements . 这样,您就不会有很多try catch块,也不会有其他语句

Example: 例:

PersonResource.java 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 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 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). 并让客户端处理响应错误状态和正文(错误消息)。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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