public static ErrorResponseBodySerializer asErrorResponseBodySerializer(ObjectMapper objectMapper) { return errorResponseBody -> { try { Object bodyToSerialize = (errorResponseBody == null) ? null : errorResponseBody.bodyToSerialize(); if (bodyToSerialize == null) { // errorResponseBody itself is null, or errorResponseBody.bodyToSerialize() is null. Either case // indicates empty response body payload, so we should return null. return null; } if(bodyToSerialize instanceof CharSequence) { return bodyToSerialize.toString(); } else { return objectMapper.writeValueAsString(bodyToSerialize); } } catch (JsonProcessingException e) { throw new RuntimeException("An error occurred while serializing an ErrorResponseBody to a string", e); } }; } }
/** * Sets an error_uid header based on the given error response's {@link ErrorResponseBody#errorId()} and replaces the * {@link ErrorResponseBody} found in the {@link ResponseInfo#getContentForFullResponse()} with the String result of * calling {@link ErrorResponseBodySerializer#serializeErrorResponseBodyToString(ErrorResponseBody)} on {@link * #errorResponseBodySerializer}. The modified {@link ResponseInfo} is then sent to {@link * #sendFullResponse(io.netty.channel.ChannelHandlerContext, RequestInfo, ResponseInfo, ObjectMapper)} for passing * back to the client. * <p/> * NOTE: This assumes a full (not chunked) response, and uses {@link ResponseInfo#getContentForFullResponse()} to * retrieve the {@link ErrorResponseBody} object. Therefore this method will throw an {@link * IllegalArgumentException} if you pass in a response object that returns true for {@link * ResponseInfo#isChunkedResponse()}. */ public void sendErrorResponse(ChannelHandlerContext ctx, RequestInfo requestInfo, ResponseInfo<ErrorResponseBody> responseInfo) throws JsonProcessingException { if (responseInfo.isChunkedResponse()) { throw new IllegalArgumentException("The responseInfo argument is marked as being a chunked response, but " + "sendErrorResponse(...) only works with full responses"); } responseInfo.getHeaders().set("error_uid", responseInfo.getContentForFullResponse().errorId()); @SuppressWarnings("UnnecessaryLocalVariable") ErrorResponseBody bodyToSerialize = responseInfo.getContentForFullResponse(); if (bodyToSerialize != null) { String errorBodyAsString = errorResponseBodySerializer.serializeErrorResponseBodyToString(bodyToSerialize); //noinspection unchecked ((ResponseInfo) responseInfo).setContentForFullResponse(errorBodyAsString); } sendFullResponse(ctx, requestInfo, responseInfo, defaultResponseContentSerializer); }
/** * Sets an error_uid header based on the given error response's {@link ErrorResponseBody#errorId()} and replaces the * {@link ErrorResponseBody} found in the {@link ResponseInfo#getContentForFullResponse()} with the String result of * calling {@link ErrorResponseBodySerializer#serializeErrorResponseBodyToString(ErrorResponseBody)} on {@link * #errorResponseBodySerializer}. The modified {@link ResponseInfo} is then sent to {@link * #sendFullResponse(io.netty.channel.ChannelHandlerContext, RequestInfo, ResponseInfo, ObjectMapper)} for passing * back to the client. * <p/> * NOTE: This assumes a full (not chunked) response, and uses {@link ResponseInfo#getContentForFullResponse()} to * retrieve the {@link ErrorResponseBody} object. Therefore this method will throw an {@link * IllegalArgumentException} if you pass in a response object that returns true for {@link * ResponseInfo#isChunkedResponse()}. */ public void sendErrorResponse(ChannelHandlerContext ctx, RequestInfo requestInfo, ResponseInfo<ErrorResponseBody> responseInfo) throws JsonProcessingException { if (responseInfo.isChunkedResponse()) { throw new IllegalArgumentException("The responseInfo argument is marked as being a chunked response, but " + "sendErrorResponse(...) only works with full responses"); } responseInfo.getHeaders().set("error_uid", responseInfo.getContentForFullResponse().errorId()); @SuppressWarnings("UnnecessaryLocalVariable") ErrorResponseBody bodyToSerialize = responseInfo.getContentForFullResponse(); if (bodyToSerialize != null) { String errorBodyAsString = errorResponseBodySerializer.serializeErrorResponseBodyToString(bodyToSerialize); //noinspection unchecked ((ResponseInfo) responseInfo).setContentForFullResponse(errorBodyAsString); } sendFullResponse(ctx, requestInfo, responseInfo, defaultResponseContentSerializer); }
public static ErrorResponseBodySerializer asErrorResponseBodySerializer(ObjectMapper objectMapper) { return errorResponseBody -> { try { Object bodyToSerialize = (errorResponseBody == null) ? null : errorResponseBody.bodyToSerialize(); if (bodyToSerialize == null) { // errorResponseBody itself is null, or errorResponseBody.bodyToSerialize() is null. Either case // indicates empty response body payload, so we should return null. return null; } if(bodyToSerialize instanceof CharSequence) { return bodyToSerialize.toString(); } else { return objectMapper.writeValueAsString(bodyToSerialize); } } catch (JsonProcessingException e) { throw new RuntimeException("An error occurred while serializing an ErrorResponseBody to a string", e); } }; } }
@Test public void bodyToSerialize_returns_same_instance_by_default() { ErrorResponseBody instance = () -> "someErrorId"; assertThat(instance.bodyToSerialize()).isSameAs(instance); } }
@Test public void asErrorResponseBodySerializer_returns_serializer_that_serializes_as_expected( ) throws JsonProcessingException { // given ObjectMapper objectMapperMock = mock(ObjectMapper.class); ErrorResponseBodySerializer serializer = asErrorResponseBodySerializer(objectMapperMock); String objectMapperResult = UUID.randomUUID().toString(); doReturn(objectMapperResult).when(objectMapperMock).writeValueAsString(anyObject()); Object objectToSerialize = new Object(); ErrorResponseBody errorResponseBodyMock = mock(ErrorResponseBody.class); doReturn(objectToSerialize).when(errorResponseBodyMock).bodyToSerialize(); // when String result = serializer.serializeErrorResponseBodyToString(errorResponseBodyMock); // then assertThat(result).isEqualTo(objectMapperResult); verify(objectMapperMock).writeValueAsString(objectToSerialize); }
@Test public void asErrorResponseBodySerializer_returns_serializer_that_propagates_JsonProcessingException_as_RuntimeException( ) throws JsonProcessingException { // given ObjectMapper objectMapperMock = mock(ObjectMapper.class); ErrorResponseBodySerializer serializer = asErrorResponseBodySerializer(objectMapperMock); ErrorResponseBody errorResponseBodyMock = mock(ErrorResponseBody.class); doReturn(new Object()).when(errorResponseBodyMock).bodyToSerialize(); JsonProcessingException jsonProcessingExceptionMock = mock(JsonProcessingException.class); doThrow(jsonProcessingExceptionMock).when(objectMapperMock).writeValueAsString(anyObject()); // when Throwable ex = catchThrowable(() -> serializer.serializeErrorResponseBodyToString(errorResponseBodyMock)); // then assertThat(ex) .isNotNull() .isExactlyInstanceOf(RuntimeException.class) .hasCause(jsonProcessingExceptionMock); }