2013-02-27 4 views
4

Каков наилучший способ вернуть исключения Джерси в формате JSON? Вот мой пример кода.Возврат Джерси исключает из JSON

public static class CompoThngExceptionMapper implements ExceptionMapper<Exception> { 
    @Override 
    public Response toResponse(Exception exception) { 
     if (exception instanceof WebApplicationException) { 
      WebApplicationException e = (WebApplicationException) exception; 
      Response r = e.getResponse(); 
      return Response.status(r.getStatus()).entity(**HERE JSON**).build(); 
    } else { 
      return null; 

     } 
    } 

Заранее благодарен!

ответ

7

Зависит от того, что вы хотите, чтобы вернуться, но лично у меня есть ErrorInfo объекта, который выглядит примерно так:

public class ErrorInfo { 
    final transient String developerMessage; 
    final transient String userMessage; 

    // Getters/setters/initializer 
} 

который я огибаю как часть моих Exception с, то я просто использовать Джексон ObjectMapper для создайте строку JSON из объекта ErrorInfo в ExceptionMapper. Хорошая вещь с этим подходом заключается в том, что вы можете расширить его очень легко, поэтому добавление информации о состоянии, времени ошибки, как бы то ни было, - это просто случай добавления другого поля.

Имейте в виду, что добавление таких вещей, как состояние ответа, является немного ненужным, так как это все равно будет возвращаться в HTTP-заголовке.

Update

Полный пример следующим образом (в данном случае ErrorInfo имеет несколько полей в нем, но вы получите общее представление):

import javax.ws.rs.core.MediaType; 
import javax.ws.rs.core.Response; 
import javax.ws.rs.core.Response.ResponseBuilder; 
import javax.ws.rs.core.Response.Status; 
import javax.ws.rs.ext.ExceptionMapper; 
import javax.ws.rs.ext.Provider; 

import com.fasterxml.jackson.core.JsonProcessingException; 
import com.fasterxml.jackson.databind.ObjectMapper; 

@Provider 
public class UnexpectedExceptionMapper implements ExceptionMapper<Exception> 
{ 
    private static final transient ObjectMapper MAPPER = new ObjectMapper(); 

    @Override 
    public Response toResponse(final Exception exception) 
    { 
    ResponseBuilder builder = Response.status(Status.BAD_REQUEST) 
             .entity(defaultJSON(exception)) 
             .type(MediaType.APPLICATION_JSON); 
    return builder.build(); 
    } 

    private String defaultJSON(final Exception exception) 
    { 
    ErrorInfo errorInfo = new ErrorInfo(null, exception.getMessage(), exception.getMessage(), (String)null); 

    try 
    { 
     return MAPPER.writeValueAsString(errorInfo); 
    } 
    catch (JsonProcessingException e) 
    { 
     return "{\"message\":\"An internal error occurred\"}"; 
    } 
    } 
} 
+0

Thanks jgm. Сожалею. Как вы кодируете «ObjectMapper» Jacson для создания строки JSON из объекта 'ErrorInfo' в' ExceptionMapper' ???. Заранее спасибо –

+0

Добавлен полный пример. – jgm

+0

Только последний вопрос jgm. Я в среде Jetty - Jersey, и я всегда получаю null в exception.getMessage(). Я хочу только вернуть описание статуса. Заранее спасибо. –

3

избежать импорта классов Джексона, но только придерживаться чистые классы JAX-RS Я создаю подобные оболочки json как это.

Создать оболочку ExceptionInfo и подклассы различных типов статуса исключения.

import javax.xml.bind.annotation.XmlAccessType; 
import javax.xml.bind.annotation.XmlAccessorType; 
import javax.xml.bind.annotation.XmlElement; 
import javax.xml.bind.annotation.XmlRootElement; 

@XmlAccessorType(XmlAccessType.PUBLIC_MEMBER) 
@XmlRootElement 
public class ExceptionInfo { 
    private int status; 
    private String msg, desc; 
    public ExceptionInfo(int status, String msg, String desc) { 
     this.status=status; 
     this.msg=msg; 
     this.desc=desc; 
    } 

    @XmlElement public int getStatus() { return status; } 
    @XmlElement public String getMessage() { return msg; } 
    @XmlElement public String getDescription() { return desc; } 
} 

- - - - 

import javax.ws.rs.core.Response; 
import javax.ws.rs.core.Response.Status; 
import javax.ws.rs.WebApplicationException; 

/** 
* Create 404 NOT FOUND exception 
*/ 
public class NotFoundException extends WebApplicationException { 
    private static final long serialVersionUID = 1L; 

    public NotFoundException() { 
     this("Resource not found", null); 
    } 

    /** 
    * Create a HTTP 404 (Not Found) exception. 
    * @param message the String that is the entity of the 404 response. 
    */ 
    public NotFoundException(String msg, String desc) { 
     super(Response.status(Status.NOT_FOUND).entity(
       new ExceptionInfo(Status.NOT_FOUND.getStatusCode(), msg, desc) 
     ).type("application/json").build()); 
    } 

} 

Затем исключение исключений в реализации ресурсов и клиент получает красивый обработанный json шаблон тела ошибки http.

@Path("/properties") 
public class PropertyService { 
    ... 
    @GET @Path("/{key}") 
    @Produces({"application/json;charset=UTF-8"}) 
    public Property getProperty(@PathParam("key") String key) { 
     // 200=OK(json obj), 404=NotFound 
     Property bean = DBUtil.getProperty(key); 
     if (bean==null) throw new NotFoundException(); 
     return bean; 
    } 
    ... 
} 

- - - - 
Content-Type: application/json 
{"status":404,"message":"Resource not found","description":null} 
+0

Я не понимаю. Где используется этот 'ExceptionInfo'? Или вы, мужчины, что «NotFoundException» должен расширять «ExceptionInfo»? – sja

+0

@sja: см. Конструктор 'NotFoundException (String msg, String desc)'. – Whome

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