use of net.morimekta.providence.PApplicationException in project providence by morimekta.
the class WrappedProcessorTest method testWrapper.
@Test
public void testWrapper() throws IOException {
PProcessor processor = mock(PProcessor.class);
WrappedProcessor wrap = new WrappedProcessor(processor, (call, p) -> {
// before call
PServiceCall reply = p.handleCall(call, p.getDescriptor());
// after call
return reply;
});
PApplicationException c = new PApplicationException("call", PApplicationExceptionType.INTERNAL_ERROR);
PApplicationException r = new PApplicationException("call", PApplicationExceptionType.INTERNAL_ERROR);
AtomicReference<PService> service = new AtomicReference<>();
service.set(new PService("test", "Service", service::get, new PServiceMethod[] {}) {
@Nullable
@Override
public PServiceMethod getMethod(String name) {
for (PServiceMethod method : getMethods()) {
if (method.getName().equals(name)) {
return method;
}
}
return null;
}
});
PServiceCall call = new PServiceCall<>("test", PServiceCallType.CALL, 44, c);
PServiceCall reply = new PServiceCall<>("reply", PServiceCallType.REPLY, 44, r);
when(processor.getDescriptor()).thenReturn(service.get());
when(processor.handleCall(call, service.get())).thenReturn(reply);
assertThat(wrap.handleCall(call), sameInstance(reply));
verify(processor, atLeastOnce()).getDescriptor();
verify(processor).handleCall(call, service.get());
verifyNoMoreInteractions(processor);
}
use of net.morimekta.providence.PApplicationException in project providence by morimekta.
the class BinarySerializer method deserialize.
@Nonnull
@Override
@SuppressWarnings("unchecked")
public <Message extends PMessage<Message, Field>, Field extends PField> PServiceCall<Message, Field> deserialize(@Nonnull InputStream is, @Nonnull PService service) throws IOException {
BigEndianBinaryReader in = new BigEndianBinaryReader(is);
String methodName = null;
int sequence = 0;
PServiceCallType type = null;
try {
int methodNameLen = in.expectInt();
int typeKey;
// versioned
if (methodNameLen <= 0) {
int version = methodNameLen & VERSION_MASK;
if (version == VERSION_1) {
typeKey = methodNameLen & 0xFF;
methodNameLen = in.expectInt();
if (methodNameLen > MAX_METHOD_NAME_LEN) {
throw new SerializerException("Exceptionally long method name of %s bytes", methodNameLen).setExceptionType(PApplicationExceptionType.PROTOCOL_ERROR);
}
if (methodNameLen < 1) {
throw new SerializerException("Exceptionally short method name of %s bytes", methodNameLen).setExceptionType(PApplicationExceptionType.PROTOCOL_ERROR);
}
methodName = new String(in.expectBytes(methodNameLen), UTF_8);
} else {
throw new SerializerException("Bad protocol version: %08x", version >>> 16).setExceptionType(PApplicationExceptionType.INVALID_PROTOCOL);
}
} else {
if (strict && versioned) {
throw new SerializerException("Missing protocol version").setExceptionType(PApplicationExceptionType.INVALID_PROTOCOL);
}
if (methodNameLen > MAX_METHOD_NAME_LEN) {
if (methodNameLen >>> 24 == '<') {
throw new SerializerException("Received HTML in service call").setExceptionType(PApplicationExceptionType.PROTOCOL_ERROR);
}
if (methodNameLen >>> 24 == '{' || methodNameLen >>> 24 == '[') {
throw new SerializerException("Received JSON in service call").setExceptionType(PApplicationExceptionType.PROTOCOL_ERROR);
}
throw new SerializerException("Exceptionally long method name of %s bytes", methodNameLen).setExceptionType(PApplicationExceptionType.PROTOCOL_ERROR);
}
methodName = new String(in.expectBytes(methodNameLen), UTF_8);
typeKey = in.expectByte();
}
sequence = in.expectInt();
type = PServiceCallType.findById(typeKey);
PServiceMethod method = service.getMethod(methodName);
if (type == null) {
throw new SerializerException("Invalid call type " + typeKey).setExceptionType(PApplicationExceptionType.INVALID_MESSAGE_TYPE);
} else if (type == PServiceCallType.EXCEPTION) {
PApplicationException ex = readMessage(in, PApplicationException.kDescriptor, strict);
return (PServiceCall<Message, Field>) new PServiceCall<>(methodName, type, sequence, ex);
} else if (method == null) {
throw new SerializerException("No such method " + methodName + " on " + service.getQualifiedName()).setExceptionType(PApplicationExceptionType.UNKNOWN_METHOD);
}
@SuppressWarnings("unchecked") PMessageDescriptor<Message, Field> descriptor = isRequestCallType(type) ? method.getRequestType() : method.getResponseType();
Message message = readMessage(in, descriptor, strict);
return new PServiceCall<>(methodName, type, sequence, message);
} catch (SerializerException se) {
throw new SerializerException(se).setMethodName(methodName).setCallType(type).setSequenceNo(sequence);
} catch (IOException e) {
throw new SerializerException(e, e.getMessage()).setMethodName(methodName).setCallType(type).setSequenceNo(sequence);
}
}
use of net.morimekta.providence.PApplicationException in project providence by morimekta.
the class NonblockingSocketClientHandler method handleCall.
@Override
@SuppressWarnings("unchecked")
public <Request extends PMessage<Request, RequestField>, Response extends PMessage<Response, ResponseField>, RequestField extends PField, ResponseField extends PField> PServiceCall<Response, ResponseField> handleCall(PServiceCall<Request, RequestField> call, PService service) throws IOException {
if (call.getType() == PServiceCallType.EXCEPTION || call.getType() == PServiceCallType.REPLY) {
throw new PApplicationException("Request with invalid call type: " + call.getType(), PApplicationExceptionType.INVALID_MESSAGE_TYPE);
}
long startTime = System.nanoTime();
PServiceCall<Response, ResponseField> response = null;
CompletableFuture<PServiceCall> responseFuture = null;
if (call.getType() == PServiceCallType.CALL) {
responseFuture = new CompletableFuture<>();
// Each sequence No must be unique for the client, otherwise this will be messed up.
responseFutures.put(call.getSequence(), responseFuture);
}
try {
synchronized (this) {
try {
ensureConnected(service);
if (out == null) {
throw new IOException("Closed channel");
}
serializer.serialize(out, call);
out.flush();
} finally {
if (out != null) {
out.completeFrame();
}
}
}
if (responseFuture != null) {
try {
if (response_timeout > 0) {
response = (PServiceCall<Response, ResponseField>) responseFuture.get(response_timeout, TimeUnit.MILLISECONDS);
} else {
response = (PServiceCall<Response, ResponseField>) responseFuture.get();
}
long endTime = System.nanoTime();
double duration = ((double) (endTime - startTime)) / NS_IN_MILLIS;
try {
instrumentation.onComplete(duration, call, response);
} catch (Exception ignore) {
}
return response;
} catch (TimeoutException | InterruptedException e) {
responseFuture.completeExceptionally(e);
throw new IOException(e.getMessage(), e);
} catch (ExecutionException e) {
throw new IOException(e.getMessage(), e);
} finally {
responseFutures.remove(call.getSequence());
}
}
} catch (Exception e) {
long endTime = System.nanoTime();
double duration = ((double) (endTime - startTime)) / NS_IN_MILLIS;
try {
instrumentation.onTransportException(e, duration, call, response);
} catch (Exception ie) {
e.addSuppressed(ie);
}
throw e;
}
return null;
}
use of net.morimekta.providence.PApplicationException in project providence by morimekta.
the class SocketClientHandler method handleCall.
@Override
public <Request extends PMessage<Request, RequestField>, Response extends PMessage<Response, ResponseField>, RequestField extends PField, ResponseField extends PField> PServiceCall<Response, ResponseField> handleCall(PServiceCall<Request, RequestField> call, PService service) throws IOException {
if (call.getType() == PServiceCallType.EXCEPTION || call.getType() == PServiceCallType.REPLY) {
throw new PApplicationException("Request with invalid call type: " + call.getType(), PApplicationExceptionType.INVALID_MESSAGE_TYPE);
}
long startTime = System.nanoTime();
PServiceCall<Response, ResponseField> reply = null;
try (Socket socket = connect()) {
OutputStream out = new BufferedOutputStream(socket.getOutputStream());
serializer.serialize(out, call);
out.flush();
if (call.getType() == PServiceCallType.CALL) {
InputStream in = new BufferedInputStream(socket.getInputStream());
reply = serializer.deserialize(in, service);
if (reply.getType() == PServiceCallType.CALL || reply.getType() == PServiceCallType.ONEWAY) {
throw new PApplicationException("Reply with invalid call type: " + reply.getType(), PApplicationExceptionType.INVALID_MESSAGE_TYPE);
}
if (reply.getSequence() != call.getSequence()) {
throw new PApplicationException("Reply sequence out of order: call = " + call.getSequence() + ", reply = " + reply.getSequence(), PApplicationExceptionType.BAD_SEQUENCE_ID);
}
}
long endTime = System.nanoTime();
double duration = ((double) (endTime - startTime)) / NS_IN_MILLIS;
try {
instrumentation.onComplete(duration, call, reply);
} catch (Exception ignore) {
}
return reply;
} catch (Exception e) {
long endTime = System.nanoTime();
double duration = ((double) (endTime - startTime)) / NS_IN_MILLIS;
try {
instrumentation.onTransportException(e, duration, call, reply);
} catch (Exception ie) {
e.addSuppressed(ie);
}
throw e;
}
}
use of net.morimekta.providence.PApplicationException in project providence by morimekta.
the class NonblockingSocketClientHandlerTest method testSimpleRequest_wrongMethod.
@Test
public void testSimpleRequest_wrongMethod() throws IOException, TException, Failure {
when(impl.test(any(net.morimekta.test.thrift.thrift.service.Request.class))).thenThrow(new net.morimekta.test.thrift.thrift.service.Failure("failure"));
try (NonblockingSocketClientHandler handler = new NonblockingSocketClientHandler(serializer, address)) {
MyService2.Iface client = new MyService2.Client(handler);
try {
client.testing(new Request("test"));
fail("no exception");
} catch (PApplicationException e) {
assertThat(e.getId(), is(UNKNOWN_METHOD));
assertThat(e.getMessage(), is(equalTo("Invalid method name: 'testing'")));
}
verifyZeroInteractions(impl);
}
}
Aggregations