[
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)