如果在处理请求主体时发生异常,则不使用Jersey自定义ExceptionMapper

时间:2015-06-29 11:50:33

标签: java rest exception-handling enums jersey

我的REST资源面临着棘手的行为。 期望的方法是期望一个复杂的json对象:

@Path(RestURIConstant.NOTIFICATION_ROOT_URI)
@Component
@Scope("request")
public class NotificationResource implements RestURIConstant {

    /** Notification service. */
    @Autowired
    private INotificationService notificationService;

    @Path(RestURIConstant.COMPLEMENT_URI)
    @POST
    @Consumes(MediaType.APPLICATION_JSON)
    @Produces(MediaType.APPLICATION_JSON)
    public Response processNotification(final EventDTO event)
        throws BusinessException, TechnicalException {
        checkParameters(event);

        notificationService.processEvent(event);

        return Response.ok().build();
    }
}

EventDTO有两个枚举字段:notificationType和eventType:

public class EventDTO {
    private ENotificationType notificationType;    
    private EEventType eventType;
    private String eventDate;
    private String userName;

    //... getters, setters
}

我想要的是从任何类型的数据验证错误中映射异常,以获得带有错误代码和错误消息的json响应。在关注jax-rs jersey: Exception Mapping for Enum bound FormParam之后:

所以对于我写的ENoticationType:

public enum ENotificationEventType {
    RULE,
    ALARM,
    ACK,
    INFO;

    @JsonCreator
    public static ENotificationEventType fromString(final String typeCode)
        throws BusinessException {
        if (typeCode == null) {
            throw new BusinessException(ValidationCode.VALUE_REQUIRED, "type");
        }
        try {
            return valueOf(typeCode);
        } catch (final IllegalArgumentException iae) {
            throw new BusinessException(ValidationCode.UNSUPPORTED_VALUE, "type", typeCode, Arrays.toString(values()));
        }
    }
}

对于我写的Mapper:

@Provider
@Singleton
public class BusinessExceptionMapper implements ExceptionMapper<BusinessException> {

    @Override
    public Response toResponse(final BusinessException exception) {

        Status status = Status.INTERNAL_SERVER_ERROR;

        // If a validationCode error = unsupported version => CODE 410
        if (exception.getErrorCode().equals(ValidationCode.UNSUPPORTED_API_VERSION)) {
            status = Status.GONE;
        } else if (exception.getErrorCode().getClass().isAssignableFrom(ValidationCode.class)) {
            // If a validationCode error then BAD_REQUEST (400) HTTP
            status = Status.BAD_REQUEST;
        } else if (exception.getErrorCode().getClass().isAssignableFrom(NotFoundCode.class)) { // CODE 404
            status = Status.NOT_FOUND;
        } else if (exception.getErrorCode().getClass().isAssignableFrom(SecurityCode.class)) { // CODE 401
            status = Status.UNAUTHORIZED;
        } else if (exception.getErrorCode().getClass().isAssignableFrom(AdminSecurityCode.class)) { // CODE 401
            status = Status.UNAUTHORIZED;
        }

        return Response.status(status).type(MediaType.APPLICATION_JSON)
            .entity(ErrorMessageHelper.createErrorMessageHelper(
                    exception.getErrorCode(), exception.getMessage()))
                    .build();
}

我的应用程序上下文包含<context:component-scan base-package=" com.technicolor.hovis.backend.rest, com.technicolor.hovis.admin.rest" />

我已经阅读了几个与球衣中的异常映射相关的问题的答案,但在我的情况下,并不是因为映射无法识别,而是在所有情况下都没有应用:

  1. 映射checkParameters引发的异常并且结果符合预期
  2. 但如果发送了无效的枚举,则会调用@JsonCreator方法,抛出相同类型的异常,但不会按预期映射此异常。
  3. 所以回复如下:

     <data contentType="text/plain;charset=UTF-8" contentLength="176">
          <![CDATA[Unsupported type value : 'ALARN'. Expected values are [RULE, ALARM, ACK, INFO] (through reference chain: EventDTO["type"])]]>
    </data>

    而不是预期的:

    {
       "code": 6,
       "message": "Unsupported type value : 'ALARN'. Expected values are [RULE, ALARM, ACK, INFO]"
    }
    

    有什么想法吗?

    西里尔

2 个答案:

答案 0 :(得分:0)

我会尝试将BusinessExceptionMapper更改为:

public class BusinessExceptionMapper implements ExceptionMapper<Exception>

如果我理解正确,问题是当你对除了你的参数进行反序列化时,在这种情况下会抛出IOException,而不是BusinessException,我猜是你的自定义通知。因此,您可以延长ExceptionMapper<Exception>ExceptionMapper<IOException>

答案 1 :(得分:0)

我注意到当我在JSONCreator中抛出一个已检查的异常时(就像你一样),杰克逊抓住它并将其包裹在IllegalArgumentException中,因此IllegalArgumentException最终会在ExceptionMapper。< / p>

也许这是你问题的原因?