Search in sources :

Example 11 with PApplicationException

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);
}
Also used : PProcessor(net.morimekta.providence.PProcessor) PServiceCall(net.morimekta.providence.PServiceCall) PApplicationException(net.morimekta.providence.PApplicationException) AtomicReference(java.util.concurrent.atomic.AtomicReference) PServiceMethod(net.morimekta.providence.descriptor.PServiceMethod) Nullable(javax.annotation.Nullable) PService(net.morimekta.providence.descriptor.PService) Test(org.junit.Test)

Example 12 with PApplicationException

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);
    }
}
Also used : BinaryFormatUtils.writeMessage(net.morimekta.providence.serializer.binary.BinaryFormatUtils.writeMessage) BinaryFormatUtils.readMessage(net.morimekta.providence.serializer.binary.BinaryFormatUtils.readMessage) PMessage(net.morimekta.providence.PMessage) PServiceCallType(net.morimekta.providence.PServiceCallType) BigEndianBinaryReader(net.morimekta.util.io.BigEndianBinaryReader) IOException(java.io.IOException) PField(net.morimekta.providence.descriptor.PField) PApplicationException(net.morimekta.providence.PApplicationException) PServiceCall(net.morimekta.providence.PServiceCall) PServiceMethod(net.morimekta.providence.descriptor.PServiceMethod) Nonnull(javax.annotation.Nonnull)

Example 13 with PApplicationException

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;
}
Also used : IOException(java.io.IOException) PApplicationException(net.morimekta.providence.PApplicationException) TimeoutException(java.util.concurrent.TimeoutException) IOException(java.io.IOException) ExecutionException(java.util.concurrent.ExecutionException) PApplicationException(net.morimekta.providence.PApplicationException) PServiceCall(net.morimekta.providence.PServiceCall) ExecutionException(java.util.concurrent.ExecutionException) TimeoutException(java.util.concurrent.TimeoutException)

Example 14 with PApplicationException

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;
    }
}
Also used : BufferedInputStream(java.io.BufferedInputStream) BufferedInputStream(java.io.BufferedInputStream) InputStream(java.io.InputStream) PApplicationException(net.morimekta.providence.PApplicationException) OutputStream(java.io.OutputStream) BufferedOutputStream(java.io.BufferedOutputStream) BufferedOutputStream(java.io.BufferedOutputStream) Socket(java.net.Socket) PApplicationException(net.morimekta.providence.PApplicationException) IOException(java.io.IOException)

Example 15 with PApplicationException

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);
    }
}
Also used : MyService2(net.morimekta.test.providence.thrift.service.MyService2) PApplicationException(net.morimekta.providence.PApplicationException) Request(net.morimekta.test.providence.thrift.service.Request) Test(org.junit.Test)

Aggregations

PApplicationException (net.morimekta.providence.PApplicationException)17 PServiceCall (net.morimekta.providence.PServiceCall)11 IOException (java.io.IOException)8 Test (org.junit.Test)7 PServiceCallType (net.morimekta.providence.PServiceCallType)6 PServiceMethod (net.morimekta.providence.descriptor.PServiceMethod)6 Nonnull (javax.annotation.Nonnull)5 PMessage (net.morimekta.providence.PMessage)5 PField (net.morimekta.providence.descriptor.PField)5 SerializerException (net.morimekta.providence.serializer.SerializerException)4 ByteArrayOutputStream (java.io.ByteArrayOutputStream)3 ByteArrayInputStream (java.io.ByteArrayInputStream)2 InputStream (java.io.InputStream)2 ExecutionException (java.util.concurrent.ExecutionException)2 TimeoutException (java.util.concurrent.TimeoutException)2 Nullable (javax.annotation.Nullable)2 PProcessor (net.morimekta.providence.PProcessor)2 PService (net.morimekta.providence.descriptor.PService)2 TException (org.apache.thrift.TException)2 TMessage (org.apache.thrift.protocol.TMessage)2