Search in sources :

Example 1 with RandomAccessByteArrayOutputStream

use of org.apache.dubbo.rpc.protocol.thrift.io.RandomAccessByteArrayOutputStream in project dubbo by alibaba.

the class ThriftCodec method encodeResponse.

private void encodeResponse(Channel channel, ChannelBuffer buffer, Response response) throws IOException {
    AppResponse result = (AppResponse) response.getResult();
    RequestData rd = CACHED_REQUEST.get(response.getId());
    String resultClassName = ExtensionLoader.getExtensionLoader(ClassNameGenerator.class).getExtension(channel.getUrl().getParameter(ThriftConstants.CLASS_NAME_GENERATOR_KEY, ThriftClassNameGenerator.NAME)).generateResultClassName(rd.serviceName, rd.methodName);
    if (StringUtils.isEmpty(resultClassName)) {
        throw new RpcException(RpcException.SERIALIZATION_EXCEPTION, "Could not encode response, the specified interface may be incorrect.");
    }
    Class clazz = CACHED_CLASS.get(resultClassName);
    if (clazz == null) {
        try {
            clazz = ClassUtils.forNameWithThreadContextClassLoader(resultClassName);
            CACHED_CLASS.putIfAbsent(resultClassName, clazz);
        } catch (ClassNotFoundException e) {
            throw new RpcException(RpcException.SERIALIZATION_EXCEPTION, e.getMessage(), e);
        }
    }
    TBase resultObj;
    try {
        resultObj = (TBase) clazz.newInstance();
    } catch (InstantiationException | IllegalAccessException e) {
        throw new RpcException(RpcException.SERIALIZATION_EXCEPTION, e.getMessage(), e);
    }
    TApplicationException applicationException = null;
    TMessage message;
    if (result.hasException()) {
        Throwable throwable = result.getException();
        int index = 1;
        boolean found = false;
        while (true) {
            TFieldIdEnum fieldIdEnum = resultObj.fieldForId(index++);
            if (fieldIdEnum == null) {
                break;
            }
            String fieldName = fieldIdEnum.getFieldName();
            String getMethodName = ThriftUtils.generateGetMethodName(fieldName);
            String setMethodName = ThriftUtils.generateSetMethodName(fieldName);
            Method getMethod;
            Method setMethod;
            try {
                getMethod = clazz.getMethod(getMethodName);
                if (getMethod.getReturnType().equals(throwable.getClass())) {
                    found = true;
                    setMethod = clazz.getMethod(setMethodName, throwable.getClass());
                    setMethod.invoke(resultObj, throwable);
                }
            } catch (NoSuchMethodException | InvocationTargetException | IllegalAccessException e) {
                throw new RpcException(RpcException.SERIALIZATION_EXCEPTION, e.getMessage(), e);
            }
        }
        if (!found) {
            applicationException = new TApplicationException(throwable.getMessage());
        }
    } else {
        Object realResult = result.getValue();
        // result field id is 0
        String fieldName = resultObj.fieldForId(0).getFieldName();
        String setMethodName = ThriftUtils.generateSetMethodName(fieldName);
        String getMethodName = ThriftUtils.generateGetMethodName(fieldName);
        Method getMethod;
        Method setMethod;
        try {
            getMethod = clazz.getMethod(getMethodName);
            setMethod = clazz.getMethod(setMethodName, getMethod.getReturnType());
            setMethod.invoke(resultObj, realResult);
        } catch (NoSuchMethodException | InvocationTargetException | IllegalAccessException e) {
            throw new RpcException(RpcException.SERIALIZATION_EXCEPTION, e.getMessage(), e);
        }
    }
    if (applicationException != null) {
        message = new TMessage(rd.methodName, TMessageType.EXCEPTION, rd.id);
    } else {
        message = new TMessage(rd.methodName, TMessageType.REPLY, rd.id);
    }
    RandomAccessByteArrayOutputStream bos = new RandomAccessByteArrayOutputStream(1024);
    TIOStreamTransport transport = new TIOStreamTransport(bos);
    TBinaryProtocol protocol = new TBinaryProtocol(transport);
    int messageLength;
    int headerLength;
    byte[] bytes = new byte[4];
    try {
        // magic
        protocol.writeI16(MAGIC);
        // message length
        protocol.writeI32(Integer.MAX_VALUE);
        // message header length
        protocol.writeI16(Short.MAX_VALUE);
        // version
        protocol.writeByte(VERSION);
        // service name
        protocol.writeString(rd.serviceName);
        // id
        protocol.writeI64(response.getId());
        protocol.getTransport().flush();
        headerLength = bos.size();
        // message
        protocol.writeMessageBegin(message);
        switch(message.type) {
            case TMessageType.EXCEPTION:
                applicationException.write(protocol);
                break;
            case TMessageType.REPLY:
                resultObj.write(protocol);
                break;
            default:
        }
        protocol.writeMessageEnd();
        protocol.getTransport().flush();
        int oldIndex = messageLength = bos.size();
        try {
            TFramedTransport.encodeFrameSize(messageLength, bytes);
            bos.setWriteIndex(MESSAGE_LENGTH_INDEX);
            protocol.writeI32(messageLength);
            bos.setWriteIndex(MESSAGE_HEADER_LENGTH_INDEX);
            protocol.writeI16((short) (0xffff & headerLength));
        } finally {
            bos.setWriteIndex(oldIndex);
        }
    } catch (TException e) {
        throw new RpcException(RpcException.SERIALIZATION_EXCEPTION, e.getMessage(), e);
    }
    buffer.writeBytes(bytes);
    buffer.writeBytes(bos.toByteArray());
}
Also used : TException(org.apache.thrift.TException) TMessage(org.apache.thrift.protocol.TMessage) AppResponse(org.apache.dubbo.rpc.AppResponse) RpcException(org.apache.dubbo.rpc.RpcException) TIOStreamTransport(org.apache.thrift.transport.TIOStreamTransport) Method(java.lang.reflect.Method) InvocationTargetException(java.lang.reflect.InvocationTargetException) TApplicationException(org.apache.thrift.TApplicationException) RandomAccessByteArrayOutputStream(org.apache.dubbo.rpc.protocol.thrift.io.RandomAccessByteArrayOutputStream) TBinaryProtocol(org.apache.thrift.protocol.TBinaryProtocol) TFieldIdEnum(org.apache.thrift.TFieldIdEnum) TBase(org.apache.thrift.TBase)

Example 2 with RandomAccessByteArrayOutputStream

use of org.apache.dubbo.rpc.protocol.thrift.io.RandomAccessByteArrayOutputStream in project dubbo by alibaba.

the class ThriftCodecTest method testDecodeExceptionResponse.

@Test
public void testDecodeExceptionResponse() throws Exception {
    int port = NetUtils.getAvailablePort();
    URL url = URL.valueOf(ThriftProtocol.NAME + "://127.0.0.1:" + port + "/" + Demo.class.getName());
    Channel channel = new MockedChannel(url);
    RandomAccessByteArrayOutputStream bos = new RandomAccessByteArrayOutputStream(128);
    Request request = createRequest();
    DefaultFuture future = DefaultFuture.newFuture(channel, request, 10, null);
    TMessage message = new TMessage("echoString", TMessageType.EXCEPTION, ThriftCodec.getSeqId());
    TTransport transport = new TIOStreamTransport(bos);
    TBinaryProtocol protocol = new TBinaryProtocol(transport);
    TApplicationException exception = new TApplicationException();
    int messageLength, headerLength;
    // prepare
    protocol.writeI16(ThriftCodec.MAGIC);
    protocol.writeI32(Integer.MAX_VALUE);
    protocol.writeI16(Short.MAX_VALUE);
    protocol.writeByte(ThriftCodec.VERSION);
    protocol.writeString(Demo.class.getName());
    // path
    protocol.writeString(Demo.class.getName());
    protocol.writeI64(request.getId());
    protocol.getTransport().flush();
    headerLength = bos.size();
    protocol.writeMessageBegin(message);
    exception.write(protocol);
    protocol.writeMessageEnd();
    protocol.getTransport().flush();
    int oldIndex = messageLength = bos.size();
    try {
        bos.setWriteIndex(ThriftCodec.MESSAGE_LENGTH_INDEX);
        protocol.writeI32(messageLength);
        bos.setWriteIndex(ThriftCodec.MESSAGE_HEADER_LENGTH_INDEX);
        protocol.writeI16((short) (0xffff & headerLength));
    } finally {
        bos.setWriteIndex(oldIndex);
    }
    // prepare
    ChannelBuffer bis = ChannelBuffers.wrappedBuffer(encodeFrame(bos.toByteArray()));
    Object obj = codec.decode((Channel) null, bis);
    Assertions.assertNotNull(obj);
    Assertions.assertTrue(obj instanceof Response);
    Response response = (Response) obj;
    Assertions.assertTrue(response.getResult() instanceof AppResponse);
    AppResponse result = (AppResponse) response.getResult();
    Assertions.assertTrue(result.hasException());
    Assertions.assertTrue(result.getException() instanceof RpcException);
}
Also used : Demo(org.apache.dubbo.rpc.gen.thrift.Demo) Channel(org.apache.dubbo.remoting.Channel) Request(org.apache.dubbo.remoting.exchange.Request) TIOStreamTransport(org.apache.thrift.transport.TIOStreamTransport) URL(org.apache.dubbo.common.URL) DefaultFuture(org.apache.dubbo.remoting.exchange.support.DefaultFuture) TApplicationException(org.apache.thrift.TApplicationException) ChannelBuffer(org.apache.dubbo.remoting.buffer.ChannelBuffer) AppResponse(org.apache.dubbo.rpc.AppResponse) Response(org.apache.dubbo.remoting.exchange.Response) RandomAccessByteArrayOutputStream(org.apache.dubbo.rpc.protocol.thrift.io.RandomAccessByteArrayOutputStream) TBinaryProtocol(org.apache.thrift.protocol.TBinaryProtocol) TMessage(org.apache.thrift.protocol.TMessage) AppResponse(org.apache.dubbo.rpc.AppResponse) RpcException(org.apache.dubbo.rpc.RpcException) TTransport(org.apache.thrift.transport.TTransport) Test(org.junit.jupiter.api.Test)

Example 3 with RandomAccessByteArrayOutputStream

use of org.apache.dubbo.rpc.protocol.thrift.io.RandomAccessByteArrayOutputStream in project dubbo by alibaba.

the class ThriftCodecTest method testDecodeReplyResponse.

@Test
public void testDecodeReplyResponse() throws Exception {
    int port = NetUtils.getAvailablePort();
    URL url = URL.valueOf(ThriftProtocol.NAME + "://127.0.0.1:" + port + "/" + Demo.Iface.class.getName());
    Channel channel = new MockedChannel(url);
    RandomAccessByteArrayOutputStream bos = new RandomAccessByteArrayOutputStream(128);
    Request request = createRequest();
    DefaultFuture future = DefaultFuture.newFuture(channel, request, 10, null);
    TMessage message = new TMessage("echoString", TMessageType.REPLY, ThriftCodec.getSeqId());
    Demo.echoString_result methodResult = new Demo.echoString_result();
    methodResult.success = "Hello, World!";
    TTransport transport = new TIOStreamTransport(bos);
    TBinaryProtocol protocol = new TBinaryProtocol(transport);
    int messageLength, headerLength;
    // prepare
    protocol.writeI16(ThriftCodec.MAGIC);
    protocol.writeI32(Integer.MAX_VALUE);
    protocol.writeI16(Short.MAX_VALUE);
    protocol.writeByte(ThriftCodec.VERSION);
    protocol.writeString(Demo.Iface.class.getName());
    // path
    protocol.writeString(Demo.Iface.class.getName());
    protocol.writeI64(request.getId());
    protocol.getTransport().flush();
    headerLength = bos.size();
    protocol.writeMessageBegin(message);
    methodResult.write(protocol);
    protocol.writeMessageEnd();
    protocol.getTransport().flush();
    int oldIndex = messageLength = bos.size();
    try {
        bos.setWriteIndex(ThriftCodec.MESSAGE_LENGTH_INDEX);
        protocol.writeI32(messageLength);
        bos.setWriteIndex(ThriftCodec.MESSAGE_HEADER_LENGTH_INDEX);
        protocol.writeI16((short) (0xffff & headerLength));
    } finally {
        bos.setWriteIndex(oldIndex);
    }
    // prepare
    byte[] buf = new byte[4 + bos.size()];
    System.arraycopy(bos.toByteArray(), 0, buf, 4, bos.size());
    ChannelBuffer bis = ChannelBuffers.wrappedBuffer(buf);
    Object obj = codec.decode((Channel) null, bis);
    Assertions.assertNotNull(obj);
    Assertions.assertTrue(obj instanceof Response);
    Response response = (Response) obj;
    Assertions.assertEquals(request.getId(), response.getId());
    Assertions.assertTrue(response.getResult() instanceof AppResponse);
    AppResponse result = (AppResponse) response.getResult();
    Assertions.assertTrue(result.getValue() instanceof String);
    Assertions.assertEquals(methodResult.success, result.getValue());
}
Also used : Demo(org.apache.dubbo.rpc.gen.thrift.Demo) Channel(org.apache.dubbo.remoting.Channel) Request(org.apache.dubbo.remoting.exchange.Request) TIOStreamTransport(org.apache.thrift.transport.TIOStreamTransport) URL(org.apache.dubbo.common.URL) DefaultFuture(org.apache.dubbo.remoting.exchange.support.DefaultFuture) ChannelBuffer(org.apache.dubbo.remoting.buffer.ChannelBuffer) AppResponse(org.apache.dubbo.rpc.AppResponse) Response(org.apache.dubbo.remoting.exchange.Response) RandomAccessByteArrayOutputStream(org.apache.dubbo.rpc.protocol.thrift.io.RandomAccessByteArrayOutputStream) TBinaryProtocol(org.apache.thrift.protocol.TBinaryProtocol) TMessage(org.apache.thrift.protocol.TMessage) AppResponse(org.apache.dubbo.rpc.AppResponse) TTransport(org.apache.thrift.transport.TTransport) Test(org.junit.jupiter.api.Test)

Example 4 with RandomAccessByteArrayOutputStream

use of org.apache.dubbo.rpc.protocol.thrift.io.RandomAccessByteArrayOutputStream in project dubbo by alibaba.

the class ThriftCodecTest method testDecodeRequest.

@Test
public void testDecodeRequest() throws Exception {
    Request request = createRequest();
    // encode
    RandomAccessByteArrayOutputStream bos = new RandomAccessByteArrayOutputStream(1024);
    TIOStreamTransport transport = new TIOStreamTransport(bos);
    TBinaryProtocol protocol = new TBinaryProtocol(transport);
    int messageLength, headerLength;
    protocol.writeI16(ThriftCodec.MAGIC);
    protocol.writeI32(Integer.MAX_VALUE);
    protocol.writeI16(Short.MAX_VALUE);
    protocol.writeByte(ThriftCodec.VERSION);
    protocol.writeString(((RpcInvocation) request.getData()).getAttachment(INTERFACE_KEY));
    protocol.writeString(((RpcInvocation) request.getData()).getAttachment(PATH_KEY));
    protocol.writeI64(request.getId());
    protocol.getTransport().flush();
    headerLength = bos.size();
    Demo.echoString_args args = new Demo.echoString_args();
    args.setArg("Hell, World!");
    TMessage message = new TMessage("echoString", TMessageType.CALL, ThriftCodec.getSeqId());
    protocol.writeMessageBegin(message);
    args.write(protocol);
    protocol.writeMessageEnd();
    protocol.getTransport().flush();
    int oldIndex = messageLength = bos.size();
    try {
        bos.setWriteIndex(ThriftCodec.MESSAGE_HEADER_LENGTH_INDEX);
        protocol.writeI16((short) (0xffff & headerLength));
        bos.setWriteIndex(ThriftCodec.MESSAGE_LENGTH_INDEX);
        protocol.writeI32(messageLength);
    } finally {
        bos.setWriteIndex(oldIndex);
    }
    Object obj = codec.decode((Channel) null, ChannelBuffers.wrappedBuffer(encodeFrame(bos.toByteArray())));
    Assertions.assertTrue(obj instanceof Request);
    obj = ((Request) obj).getData();
    Assertions.assertTrue(obj instanceof RpcInvocation);
    RpcInvocation invocation = (RpcInvocation) obj;
    Assertions.assertEquals("echoString", invocation.getMethodName());
    Assertions.assertArrayEquals(new Class[] { String.class }, invocation.getParameterTypes());
    Assertions.assertArrayEquals(new Object[] { args.getArg() }, invocation.getArguments());
}
Also used : RpcInvocation(org.apache.dubbo.rpc.RpcInvocation) Demo(org.apache.dubbo.rpc.gen.thrift.Demo) RandomAccessByteArrayOutputStream(org.apache.dubbo.rpc.protocol.thrift.io.RandomAccessByteArrayOutputStream) TBinaryProtocol(org.apache.thrift.protocol.TBinaryProtocol) TMessage(org.apache.thrift.protocol.TMessage) Request(org.apache.dubbo.remoting.exchange.Request) TIOStreamTransport(org.apache.thrift.transport.TIOStreamTransport) Test(org.junit.jupiter.api.Test)

Example 5 with RandomAccessByteArrayOutputStream

use of org.apache.dubbo.rpc.protocol.thrift.io.RandomAccessByteArrayOutputStream in project dubbo by alibaba.

the class ThriftCodec method encodeRequest.

private void encodeRequest(Channel channel, ChannelBuffer buffer, Request request) throws IOException {
    RpcInvocation inv = (RpcInvocation) request.getData();
    int seqId = nextSeqId();
    String serviceName = inv.getAttachment(INTERFACE_KEY);
    if (StringUtils.isEmpty(serviceName)) {
        throw new IllegalArgumentException("Could not find service name in attachment with key " + INTERFACE_KEY);
    }
    TMessage message = new TMessage(inv.getMethodName(), TMessageType.CALL, seqId);
    String methodArgs = ExtensionLoader.getExtensionLoader(ClassNameGenerator.class).getExtension(channel.getUrl().getParameter(ThriftConstants.CLASS_NAME_GENERATOR_KEY, ThriftClassNameGenerator.NAME)).generateArgsClassName(serviceName, inv.getMethodName());
    if (StringUtils.isEmpty(methodArgs)) {
        throw new RpcException(RpcException.SERIALIZATION_EXCEPTION, "Could not encode request, the specified interface may be incorrect.");
    }
    Class<?> clazz = CACHED_CLASS.get(methodArgs);
    if (clazz == null) {
        try {
            clazz = ClassUtils.forNameWithThreadContextClassLoader(methodArgs);
            CACHED_CLASS.putIfAbsent(methodArgs, clazz);
        } catch (ClassNotFoundException e) {
            throw new RpcException(RpcException.SERIALIZATION_EXCEPTION, e.getMessage(), e);
        }
    }
    TBase args;
    try {
        args = (TBase) clazz.newInstance();
    } catch (InstantiationException | IllegalAccessException e) {
        throw new RpcException(RpcException.SERIALIZATION_EXCEPTION, e.getMessage(), e);
    }
    for (int i = 0; i < inv.getArguments().length; i++) {
        Object obj = inv.getArguments()[i];
        if (obj == null) {
            continue;
        }
        TFieldIdEnum field = args.fieldForId(i + 1);
        String setMethodName = ThriftUtils.generateSetMethodName(field.getFieldName());
        Method method;
        try {
            method = clazz.getMethod(setMethodName, inv.getParameterTypes()[i]);
        } catch (NoSuchMethodException e) {
            throw new RpcException(RpcException.SERIALIZATION_EXCEPTION, e.getMessage(), e);
        }
        try {
            method.invoke(args, obj);
        } catch (IllegalAccessException | InvocationTargetException e) {
            throw new RpcException(RpcException.SERIALIZATION_EXCEPTION, e.getMessage(), e);
        }
    }
    RandomAccessByteArrayOutputStream bos = new RandomAccessByteArrayOutputStream(1024);
    TIOStreamTransport transport = new TIOStreamTransport(bos);
    TBinaryProtocol protocol = new TBinaryProtocol(transport);
    int headerLength, messageLength;
    byte[] bytes = new byte[4];
    try {
        // magic
        protocol.writeI16(MAGIC);
        // message length placeholder
        protocol.writeI32(Integer.MAX_VALUE);
        // message header length placeholder
        protocol.writeI16(Short.MAX_VALUE);
        // version
        protocol.writeByte(VERSION);
        // service name
        protocol.writeString(serviceName);
        // path
        protocol.writeString(inv.getAttachment(PATH_KEY));
        // dubbo request id
        protocol.writeI64(request.getId());
        protocol.getTransport().flush();
        // header size
        headerLength = bos.size();
        // message body
        protocol.writeMessageBegin(message);
        args.write(protocol);
        protocol.writeMessageEnd();
        protocol.getTransport().flush();
        int oldIndex = messageLength = bos.size();
        // fill in message length and header length
        try {
            TFramedTransport.encodeFrameSize(messageLength, bytes);
            bos.setWriteIndex(MESSAGE_LENGTH_INDEX);
            protocol.writeI32(messageLength);
            bos.setWriteIndex(MESSAGE_HEADER_LENGTH_INDEX);
            protocol.writeI16((short) (0xffff & headerLength));
        } finally {
            bos.setWriteIndex(oldIndex);
        }
    } catch (TException e) {
        throw new RpcException(RpcException.SERIALIZATION_EXCEPTION, e.getMessage(), e);
    }
    buffer.writeBytes(bytes);
    buffer.writeBytes(bos.toByteArray());
}
Also used : RpcInvocation(org.apache.dubbo.rpc.RpcInvocation) TException(org.apache.thrift.TException) TIOStreamTransport(org.apache.thrift.transport.TIOStreamTransport) Method(java.lang.reflect.Method) InvocationTargetException(java.lang.reflect.InvocationTargetException) RandomAccessByteArrayOutputStream(org.apache.dubbo.rpc.protocol.thrift.io.RandomAccessByteArrayOutputStream) TBinaryProtocol(org.apache.thrift.protocol.TBinaryProtocol) TMessage(org.apache.thrift.protocol.TMessage) TFieldIdEnum(org.apache.thrift.TFieldIdEnum) RpcException(org.apache.dubbo.rpc.RpcException) TBase(org.apache.thrift.TBase)

Aggregations

RandomAccessByteArrayOutputStream (org.apache.dubbo.rpc.protocol.thrift.io.RandomAccessByteArrayOutputStream)5 TBinaryProtocol (org.apache.thrift.protocol.TBinaryProtocol)5 TMessage (org.apache.thrift.protocol.TMessage)5 TIOStreamTransport (org.apache.thrift.transport.TIOStreamTransport)5 Request (org.apache.dubbo.remoting.exchange.Request)3 AppResponse (org.apache.dubbo.rpc.AppResponse)3 RpcException (org.apache.dubbo.rpc.RpcException)3 Demo (org.apache.dubbo.rpc.gen.thrift.Demo)3 Test (org.junit.jupiter.api.Test)3 InvocationTargetException (java.lang.reflect.InvocationTargetException)2 Method (java.lang.reflect.Method)2 URL (org.apache.dubbo.common.URL)2 Channel (org.apache.dubbo.remoting.Channel)2 ChannelBuffer (org.apache.dubbo.remoting.buffer.ChannelBuffer)2 Response (org.apache.dubbo.remoting.exchange.Response)2 DefaultFuture (org.apache.dubbo.remoting.exchange.support.DefaultFuture)2 RpcInvocation (org.apache.dubbo.rpc.RpcInvocation)2 TApplicationException (org.apache.thrift.TApplicationException)2 TBase (org.apache.thrift.TBase)2 TException (org.apache.thrift.TException)2