thomasbruggink opened a new pull request, #2939:
URL: https://github.com/apache/thrift/pull/2939

   Some libraries want to bypass the TServer class and handle the full service 
startup manually. For example when building a service that hosts multiple 
thrift services where the IFace type is unknown when handling a request.
   
   For example when you host multiple services on top of netty and through an 
HTTP path you want to route to the correct thrift service. In this situation 
you treat can treat an IFace as an Object and use the `getProcessMapView()` 
method to parse a byte array into a thrift message and pass let the 
`AsyncProcessFunction` handle the invocation.
   
   To return a correct thrift response it's necessary to write the 
`{service_name}_result` that contains the response args. While it is possible 
to get an incoming args object from the (Async)ProcessFunction its 
unfortunately not possible to get a result object without using reflection.
   
   This PR extends the (Async)ProcessFunction by adding a 
`getEmptyResultInstance` method that returns a new generic `A` (answer) that 
matches the `{service_name}_result` object.
   
   This allows thrift users to write the following processing code:
   ```java
   <I> void handleRequest(
           TProtocol in,
           TProtocol out,
           TBaseAsyncProcessor<I> processor,
           I asyncIface
   ) throws TException {
       final Map<String, AsyncProcessFunction<Object, TBase<?, ?>, TBase<?, ?>, 
TBase<?, ?>>> processMap = (Map) processor.getProcessMapView();
       final var msg = in.readMessageBegin();
       final var fn = processMap.get(msg.name);
   
       final var args = fn.getEmptyArgsInstance();
       args.read(in);
       in.readMessageEnd();
   
       if (fn.isOneway()) {
           return;
       }
   
       fn.start(asyncIface, args, new AsyncMethodCallback<>() {
           @Override
           public void onComplete(TBase<?, ?> o) {
               try {
                   out.writeMessageBegin(new TMessage(fn.getMethodName(), 
TMessageType.REPLY, msg.getSeqid()));
                   final var response_result = fn.getEmptyResultInstance();
                   final var success_field = 
response_result.fieldForId(SUCCESS_ID);
                   ((TBase) response_result).setFieldValue(success_field, o);
                   response_result.write(out);
                   out.writeMessageEnd();
                   out.getTransport().flush();
               } catch (TException e) {
                   throw new RuntimeException(e);
               }
           }
   
           @Override
           public void onError(Exception e) {
               try {
                   out.writeMessageBegin(new TMessage(fn.getMethodName(), 
TMessageType.EXCEPTION, msg.getSeqid()));
                   ((TApplicationException) e).write(out);
                   out.writeMessageEnd();
                   out.getTransport().flush();
               } catch (TException ex) {
                   throw new RuntimeException(ex);
               }
           }
       });
   }
   ```
   The above example code doesn't need any reference to the original types and 
can dynamically create the correct objects to return a correct response.
   
   Please let me know what you think.


-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: dev-unsubscr...@thrift.apache.org

For queries about this service, please contact Infrastructure at:
us...@infra.apache.org

Reply via email to