ResponseDeserializerByDeserializers implements ResponseDeserializer { public <T> T deserialize(Response response) throws Exception { MethodConfig mc = response.getRequest().getMethodConfig(); Deserializer[] deserializers = mc.getDeserializers(); isTrue(deserializers.length > 0, NO_DESERIALIZERS_ERROR, mc); InputStream pStream = response.asStream(); boolean isDumped; if (deserializers.length > 1) { pStream = new ByteArrayInputStream(toByteArray(pStream, true)); isDumped = true; }else{ isDumped = false; } Exception deserializationException = null; for (Deserializer deserializer : deserializers) { try { LOG.debug("Trying to deserialize response with user specified deserializer: %s.", deserializer); return deserializer.<T>deserialize( (Class<T>) response.getExpectedType(), response.getExpectedGenericType(), pStream, response.getCharset()); } catch (Exception e) { LOG.warn(e, "Failed to deserialize response with user specified deserializer: %s. Trying next.", deserializer); deserializationException = e; if(isDumped) { pStream.mark(0); pStream.reset(); } } } throw new CRestException("Could not deserialize response with given deserializers " + Arrays.toString(deserializers), deserializationException); }  T deserialize(Response response);  }
@Test(expected = IllegalArgumentException.class) public void shouldThrowExceptionWhenResponseDoesNotHaveAnyDeserializers() throws Exception { when(mockMethodConfig.getDeserializers()).thenReturn(new Deserializer[0]); try { toTest.deserialize(mockResponse); } catch (Exception e) { assertEquals("No deserializers have been configured for the method config ("+mockMethodConfig+"), cancelling deserialization.\n" + "This happens after both response's Content-Type and method's return type based deserializations have failed deserializing the response.\n" + "As a last attempt, CRest will try to use the predefined deserializer for the method, defined using @Consumes(\"some-mime-type\") or @Deserializer(MyDeserializer.class) annotations. If not present, then deserialization is not possible at this point.\n" + "To fix it, try one of the following:\n" + " - Ensure the response has a known Content-Type.\n" + " - If response Content-Type is unknown, bind it through CRestBuilder using either a common deserializer or providing your own.\n" + " - If response Content-Type cannot be changed, bind a deserializer either through @Consumes(\"some-mime-type\") or @Deserializer(MyDeserializer.class) annotation.", e.getMessage()); throw e; } }
@Test public void shouldUseResponseStreamWhenOneDeserializerIsGiven() throws Exception { Deserializer mockDeserializer1 = mock(Deserializer.class); when(mockMethodConfig.getDeserializers()).thenReturn(new Deserializer[]{mockDeserializer1}); when(mockDeserializer1.deserialize(String.class, String.class, mockStream, UTF8)).thenReturn("hi"); String actual = toTest.deserialize(mockResponse); assertEquals("hi", actual); }
@Test public void shouldDumpInputStreamInMemoryWhenMoreThanOneDeserializerIsGiven() throws Exception { Deserializer mockDeserializer1 = mock(Deserializer.class); Deserializer mockDeserializer2 = mock(Deserializer.class); when(mockMethodConfig.getDeserializers()).thenReturn(new Deserializer[]{mockDeserializer1, mockDeserializer2}); when(mockDeserializer1.deserialize(String.class, String.class, mockDumpStream, UTF8)).thenThrow(new Exception()); when(mockDeserializer2.deserialize(String.class, String.class, mockDumpStream, UTF8)).thenReturn("hi"); mockStatic(IOs.class); when(IOs.toByteArray(mockStream, true)).thenReturn(SOME_STRING_UTF8_BYTES); String actual = toTest.deserialize(mockResponse); assertEquals("hi", actual); verify(mockDumpStream).mark(0); verify(mockDumpStream).reset(); }
@Test(expected = CRestException.class) public void shouldShouleThrowLastExceptionWhenAllDeserializerHaveFailed() throws Exception { Exception e1 = new Exception(); Exception e2 = new Exception(); Deserializer mockDeserializer1 = mock(Deserializer.class); Deserializer mockDeserializer2 = mock(Deserializer.class); when(mockMethodConfig.getDeserializers()).thenReturn(new Deserializer[]{mockDeserializer1, mockDeserializer2}); when(mockDeserializer1.deserialize(String.class, String.class, mockDumpStream, UTF8)).thenThrow(e1); when(mockDeserializer2.deserialize(String.class, String.class, mockDumpStream, UTF8)).thenThrow(e2); mockStatic(IOs.class); when(IOs.toByteArray(mockStream, true)).thenReturn(SOME_STRING_UTF8_BYTES); try { toTest.deserialize(mockResponse); fail(); } catch (Exception e) { verify(mockDumpStream, times(2)).mark(0); verify(mockDumpStream, times(2)).reset(); assertSame(e2, e.getCause()); throw e; } }