2016-02-26 2 views
3

Я использую API Джерси для службы REST. Мой вопрос: есть ли более элегантный способ возврата исключений в форме JSON? Лучше ли я сам сам создать объект json и напрямую привязать его к ответу?Служба REST: правильный способ возврата исключения

Это упрощенный пример одного из методов службы. Как вы видите, я использую HashMap только потому, что метод может генерировать исключение, и в этом случае мне нужно вернуть информацию об этом.

@Path("/admin") 
public class AdminService { 

    @Context 
    HttpServletRequest request; 

    @POST 
    @Produces(MediaType.APPLICATION_JSON) 
    public Map<Integer, String> createCompany(Company company){ 

     Map<Integer, String> map = new HashMap<>(); 
     try{ 
      AdminFacade adminFacade = (AdminFacade)Utility.getFacade(request); 
      adminFacade.createCompany(company); 
      map.put(1,"success"); 
     } catch (ExceptionREST e) { 
      map.put(e.getErrorNumber(), e.getMessage()); 
     } finally { 
      return map; 
     } 
    } 
} 
+0

, что случилось с тем, что у вас есть сейчас? –

+2

Также ознакомьтесь со следующими ссылками: [RESTful API Design] (http://apigee.com/about/blog/technology/restful-api-design-what-about-errors), [обработка ошибок при обращении] (http://archive.oreilly.com/pub/post/restful_error_handling.html) –

+0

Ничего нехорошо. Я спрашиваю о написании условностей. Это то, что я придумал, но я уверен, что есть какое-то соглашение об этом, так как я не первый, кто это делает. – MaxG

ответ

7

Вы можете создать класс, как показано ниже, чтобы представить ошибку,

@JsonPropertyOrder({ "code", "field", "message" }) 
public class ErrorInfo { 

    private String code; 

    private String field; 

    private String message; 

    public String getCode() { 
     return code; 
    } 

    public void setCode(String code) { 
     this.code = code; 
    } 

    public String getField() { 
     return field; 
    } 

    public void setField(String field) { 
     this.field = field; 
    } 

    public String getMessage() { 
     return message; 
    } 

    public void setMessage(String message) { 
     this.message = message; 
    } 

} 

Вы можете создайте класс, который расширяет исключение, подобное этому,

public class InvalidInputException extends RuntimeException { 

    private static final long serialVersionUID = -5027121014723838738L; 

    private List<ErrorInfo> errors; 

    public List<ErrorInfo> getErrors() { 
     this.errors; 
    } 

    public InvalidInputException(List<ErrorInfo> errors) { 
     super(); 
     this.errors = errors; 
    } 

    public InvalidInputException(String message, List<ErrorInfo> errors) { 
     super(message); 
     this.errors = errors; 
    } 

} 

У меня есть блок отображения исключений, в котором вы можете преобразовать список в json и вернуться к пользователю с кодом статуса http 400 (Bad Request).

@Provider 
public class InvalidInputExceptionMapper implements ExceptionMapper<InvalidInputException> { 

    @Override 
    @Produces(MediaType.APPLICATION_JSON) 
    public Response toResponse(InvalidInputException e) { 

     ResponseBuilder rb = Response.status(Status.BAD_REQUEST); 

     rb.entity(e.getErrors()); 
     return rb.build(); 
    } 
} 

Http Ответ будет,

HTTP/1.1 400 BAD REQUEST 
{ 
"errors": [{ 
    "error": { 
     "code": "100", 
     "field": null, 
     "message": "Name is required" 
    }, 
    "error": { 
     "code": "100", 
     "field": null, 
     "message": "Age is required" 
    } 
}] 

}

+0

Спасибо! вот что я и сделал в конце концов. – MaxG

2

Я считаю, что довольно популярно, что люди используют код ответа HTTP-ответа для обработки ошибки. Например. Статус 404 не найден 5xx - внутренняя ошибка сервера e.t.c. Вы можете легко установить код ошибки с помощью объекта Response. Вместо того, чтобы возвращать карту, верните объект Response.

@Path("/admin")public class AdminService { 

@Context 
HttpServletRequest request; 

@POST 
@Produces(MediaType.APPLICATION_JSON) 
public Response createCompany(Company company){ 

    Map<Integer, String> map = new HashMap<>(); 
    try{ 
     AdminFacade adminFacade = (AdminFacade)Utility.getFacade(request); 
     Company commpany=adminFacade.createCompany(company);//this entity annotated by XmlRootElement 
     Response response=Response.ok().entity(company).build(); 
    } catch (ExceptionREST e) { 
     response=Response.status(404).build(); 
    } return response; 
}} 

Чтобы сделать RESTful API более надежным, некоторые из них будут возвращать ответ ОК, чтобы предотвратить «умный редирект» с сервера и вывода некоторые странные HTML. вы можете сослаться на here на список кода статуса http и что это значит. Для класса Java EE Response вы можете сослаться на official javadoc

1

Вы можете обернуть свою ошибку в класс, скажем, у меня есть класс ErrorData, который имеет статус, сообщение и стек. Каждый раз, когда возникает исключение, я бросаю исключение GeneralAppException с объектом errordata.

public class GeneralAppException extends WebApplicationException { 
public GeneralAppException(ErrorData er) { 

      super(Response.status(er.getStatusCode()). 
      entity(er).type(MediaType.APPLICATION_JSON).build()); 
      } 
} 

У меня есть другой класс, который имеет все известные ошибки, например.

public static final ErrorData NODATAFOUND = new ErrorData(Response.Status.NOT_FOUND.getStatusCode(),"No data was found for given query"); 

public static final ErrorData CODEERROR = new ErrorData(502,"CodeError"); 

Ваш улов может выглядеть

catch (ExceptionREST e) { 
     throw new GeneralAppException(ErrorData.NODATAFOUND); 
    } 

Reference используется: https://jersey.java.net/documentation/latest/representations.html#d0e6665

Смежные вопросы