private byte[] readyFully(ServletInputStream in, int totalSize) throws Exception { byte[] retval = new byte[totalSize]; int bytesRead = 0; while (bytesRead < totalSize) { try { int read = in.read(retval, bytesRead, totalSize - bytesRead); if (read == -1) { throw new RpcCallException(RpcCallException.Category.InternalServerError, "Unable to read complete request or response"); } bytesRead += read; } catch (IOException e) { throw new RpcCallException(RpcCallException.Category.InternalServerError, "IOException reading data: " + e); } } return retval; }
@Override public RpcEnvelope.Response handleRequest(RpcEnvelope.Request request, OrangeContext ctx) throws RpcCallException { throw new RpcCallException(RpcCallException.Category.InternalServerError, "no p4s5!"); } };
@Override public RpcCallException decodeException(ContentResponse response) throws RpcCallException { try { if (response != null) { JsonObject json = (JsonObject) new JsonParser().parse(response.getContentAsString()); JsonElement error = json.get("error"); if (error != null) { return RpcCallException.fromJson(error.toString()); } } } catch (Exception ex) { logger.warn("Caught exception decoding protobuf response exception", ex); throw new RpcCallException(RpcCallException.Category.InternalServerError, RpcCallExceptionDecoder.exceptionToString(ex)); } return null; }
@SuppressWarnings("unchecked") private Message convertJsonToProtobuf(ServiceMethodHandler handler, JsonRpcRequest rpcRequest) throws RpcCallException { try { Class<?> requestKlass = findSubClassParameterType(handler, 0); return ProtobufUtil.jsonToProtobuf(rpcRequest.getParams(), (Class<? extends Message>) requestKlass); } catch (ClassNotFoundException ex) { throw new IllegalStateException("Reflection for handler " + handler.getClass() + " failed"); } catch (RuntimeException ex) { throw new RpcCallException(RpcCallException.Category.BadRequest, "Invalid request"); } }
@Override public RpcCallException decodeException(ContentResponse response) throws RpcCallException { try { if (response != null) { byte[] data = response.getContent(); if (ArrayUtils.isEmpty(data)) { logger.warn("Unable to decode: empty response received"); return new RpcCallException(RpcCallException.Category.InternalServerError, "Empty response received"); } ProtobufRpcResponse pbResponse = new ProtobufRpcResponse(data); String error = pbResponse.getErrorMessage(); if (error != null) { return RpcCallException.fromJson(error); } } } catch (Exception ex) { logger.warn("Caught exception decoding protobuf response exception", ex); throw new RpcCallException(RpcCallException.Category.InternalServerError, RpcCallExceptionDecoder.exceptionToString(ex)); } return null; }
Category category = getCategory(object); String message = getMessage(object); RpcCallException retval = new RpcCallException(category, message); JsonElement element = object.get(SOURCE); if (element != null && !(element instanceof JsonNull)) {
public ProtobufRpcResponse(byte[] data) throws RpcCallException { //we may get a json error even though we make a protobuf call if (data[0] == '{' && data[data.length - 1] == '}') { readRpcError(new String(data)); return; } int headerLength = Ints.fromByteArray(data); if (headerLength < 0 || headerLength > MAX_HEADER_SIZE) { StringBuilder sb = new StringBuilder(); sb.append("Unexpected header length: ").append(headerLength). append(", data: ").append(ensurePrintable(data, 256)); String message = sb.toString(); logger.warn(message); throw new RpcCallException(RpcCallException.Category.InternalServerError, message); } logger.debug("headerLength = {}", headerLength); int offset = 4; byte headerData[] = Arrays.copyOfRange(data, offset, offset + headerLength); offset += headerLength; byte payloadLengthBuffer[] = Arrays.copyOfRange(data, offset, offset + 4); offset += 4; int payloadLength = Ints.fromByteArray(payloadLengthBuffer); payloadData = Arrays.copyOfRange(data, offset, offset + payloadLength); RpcEnvelope.Response responseHeader = ProtobufUtil. byteArrayToProtobuf(headerData, RpcEnvelope.Response.class); serviceMethod = responseHeader.getServiceMethod(); sequenceNumber = responseHeader.getSequenceNumber(); errorMessage = responseHeader.getError(); }
/** * Converts a byte array to a protobuf message * * @param data the byte array to convert * @param messageClass the protobuf message class to convert into * @return the converted protobuf message * @throws RpcCallException if something goes wrong during the deserialization */ public static <TYPE extends Message> TYPE byteArrayToProtobuf(byte data[], Class<TYPE> messageClass) throws RpcCallException { try { Message.Builder builder = getBuilder(messageClass); return (TYPE) builder.mergeFrom(data).build(); } catch (Exception e) { throw new RpcCallException(RpcCallException.Category.InternalServerError, "Error deserializing byte array to protobuf: " + e); } }
@Test public void testJsonToString() { RpcCallException ex = new RpcCallException(RpcCallException.Category.InternalServerError, "feckoff"); System.out.println(ex.toString()); }
public HttpRequestWrapper createHttpPost(RpcClient client) throws RpcCallException { this.client = client; ServiceEndpoint instance = loadBalancer.getHealthyInstance(); if (instance == null) { throw new RpcCallException(RpcCallException.Category.InternalServerError, "No available instance of " + loadBalancer.getServiceName()). withSource(serviceProps.getServiceName()); } return new HttpRequestWrapper("POST", instance); }
private void initialize() { httpResponse = mock(ContentResponse.class); when(httpResponse.getHeaders()).thenReturn(new HttpFields()); when(httpResponse.getStatus()).thenReturn(200); try { RpcEnvelope.Response.Builder responseBuilder = RpcEnvelope.Response.newBuilder(); responseBuilder.setServiceMethod("Test.test"); if (requestsFail) { RpcCallException callException = new RpcCallException( RpcCallException.Category.InternalServerError, "requests fail!"); responseBuilder.setError(callException.toJson().toString()); } RpcEnvelope.Response rpcResponse = responseBuilder.build(); byte[] responseHeader = rpcResponse.toByteArray(); byte[] payload = FrameworkTest.Foobar.newBuilder().build().toByteArray(); ByteArrayOutputStream out = new ByteArrayOutputStream(); out.write(Ints.toByteArray(responseHeader.length)); out.write(responseHeader); out.write(Ints.toByteArray(payload.length)); out.write(payload); out.flush(); when(httpResponse.getContent()).thenReturn(out.toByteArray()); } catch (Exception e) { e.printStackTrace(); } }
logger.warn("Error parsing request: " + postedContent, iaex); @SuppressWarnings("ThrowableNotThrown") RpcCallException callException = new RpcCallException(RpcCallException.Category.BadRequest, iaex.getMessage()); JsonObject jsonResponse = new JsonObject();
@Test public void testJsonEncodingDecoding() throws Exception { RpcCallException exception = new RpcCallException(RpcCallException.Category.BadRequest, "You fool!").withData("my data").withErrorCode("SERVICE_PROTOBUF_ENUM"). withRetriable(true).withSource("com.sixt.service.foobar"); String json = exception.toString(); assertThat(json).isEqualTo("{\"category\":400,\"message\":\"You fool!\"," + "\"source\":\"com.sixt.service.foobar\",\"code\":\"SERVICE_PROTOBUF_ENUM\"," + "\"data\":\"my data\",\"retriable\":true}"); RpcCallException.fromJson(json); }
private HttpRequestWrapper createHttpPost(HttpRequestWrapper previous, List<ServiceEndpoint> triedEndpoints) throws RpcCallException { ServiceEndpoint instance = loadBalancer.getHealthyInstanceExclude(triedEndpoints); if (instance == null) { throw new RpcCallException(RpcCallException.Category.InternalServerError, "RpcCallException calling " + loadBalancer.getServiceName() + ", no available instance"). withSource(serviceProps.getServiceName()); } //TODO: There may still be a problem where retries are setting chunked encoding // or the content-length gets munged HttpRequestWrapper retval = new HttpRequestWrapper("POST", instance); retval.setHeaders(previous.getHeaders()); retval.setContentProvider(previous.getContentProvider()); return retval; }
@Test public void retriableError() { //Create 2 servers and have both throw an exception that is retriable. //The exception should be thrown locally loadBalancer.addServiceEndpoint(new ServiceEndpoint(executor, "localhost:20001", "dc1", dependencyHealthCheck)); loadBalancer.addServiceEndpoint(new ServiceEndpoint(executor, "localhost:20002", "dc1", dependencyHealthCheck)); rpcClient = clientFactory.newClient(serviceName, "testing", FrameworkTest.Foobar.class). withRetries(1).build(); httpClient.setResponseException(new RpcCallException(RpcCallException.Category. InternalServerError, "test1234").withSource("testing567")); int failureCount = 0; try { rpcClient.callSynchronous(FrameworkTest.Foobar.newBuilder().build(), new OrangeContext()); } catch (RpcCallException ex) { failureCount++; assertThat(ex.getCategory()).isEqualTo(RpcCallException.Category.InternalServerError); assertThat(ex.getMessage()).isEqualTo("test1234"); assertThat(ex.getSource()).isEqualTo("testing567"); } assertThat(failureCount).isEqualTo(1); assertThat(httpClient.verifyRequestsProcessed(2)).isTrue(); }
@Test public void nonRetriableError() { //Create 2 servers and have the first throw an exception that is not retriable. //The exception should be thrown and not retried with the other node loadBalancer.addServiceEndpoint(new ServiceEndpoint(executor, "localhost:20001", "dc1", dependencyHealthCheck)); loadBalancer.addServiceEndpoint(new ServiceEndpoint(executor, "localhost:20002", "dc1", dependencyHealthCheck)); rpcClient = clientFactory.newClient(serviceName, "testing", FrameworkTest.Foobar.class). withRetries(1).build(); httpClient.setResponseException(new RpcCallException(RpcCallException.Category. InsufficientPermissions, "test").withSource("testing")); int failureCount = 0; try { rpcClient.callSynchronous(FrameworkTest.Foobar.newBuilder().build(), new OrangeContext()); } catch (RpcCallException ex) { failureCount++; assertThat(ex.getCategory()).isEqualTo(RpcCallException.Category.InsufficientPermissions); assertThat(ex.getMessage()).isEqualTo("test"); } assertThat(failureCount).isEqualTo(1); assertThat(httpClient.verifyRequestsProcessed(1)).isTrue(); }
} catch (TimeoutException timeout) { lastStatusCode = RpcCallException.Category.RequestTimedOut.getHttpStatus(); lastException = new RpcCallException(RpcCallException.Category.RequestTimedOut, "Http-client timeout"); throw new RpcCallException(RpcCallException.Category.fromStatus(lastStatusCode), "Null response in execute").withSource(serviceProps.getServiceName()); } else {