[ https://issues.apache.org/jira/browse/THRIFT-5762?page=com.atlassian.jira.plugin.system.issuetabpanels:all-tabpanel ]
Jens Geyer resolved THRIFT-5762. -------------------------------- Fix Version/s: 0.21.0 Assignee: Thomas Bruggink Resolution: Fixed > Expose service result objects in Java > ------------------------------------- > > Key: THRIFT-5762 > URL: https://issues.apache.org/jira/browse/THRIFT-5762 > Project: Thrift > Issue Type: New Feature > Reporter: Thomas Bruggink > Assignee: Thomas Bruggink > Priority: Major > Fix For: 0.21.0 > > Time Spent: 20m > Remaining Estimate: 0h > > 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: > {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); > } > } > }); > } > {code} > 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. -- This message was sent by Atlassian Jira (v8.20.10#820010)