Source:
<code>public ListenableFuture<Object> asynchronousInvoke( final RequestChannel channel, final TChannelBufferInputTransport inputTransport, final TChannelBufferOutputTransport outputTransport, final TProtocol inputProtocol, final TProtocol outputProtocol, final int sequenceId, final ClientContextChain contextChain, final Object[] args) throws Exception { final AsyncMethodCallFuture<Object> future = AsyncMethodCallFuture.create(contextChain); final RequestContext requestContext = RequestContexts.getCurrentContext(); contextChain.preWrite(args); outputTransport.resetOutputBuffer(); writeArguments(outputProtocol, sequenceId, args); ChannelBuffer requestBuffer = outputTransport.getOutputBuffer().copy(); contextChain.postWrite(args); channel.sendAsynchronousRequest(requestBuffer, false, new RequestChannel.Listener() { @Override public void onRequestSent() { if (oneway) { try { future.set(null); } catch (Exception e) { future.setException(e); } } } @Override public void onResponseReceived(ChannelBuffer message) { RequestContext oldRequestContext = RequestContexts.getCurrentContext(); RequestContexts.setCurrentContext(requestContext); try { contextChain.preRead(); inputTransport.setInputBuffer(message); waitForResponse(inputProtocol, sequenceId); Object results = readResponse(inputProtocol); contextChain.postRead(results); future.set(results); } catch (Exception e) { contextChain.postReadException(e); future.setException(e); } finally { RequestContexts.setCurrentContext(oldRequestContext); } } @Override public void onChannelError(TException e) { RequestContext oldRequestContext = RequestContexts.getCurrentContext(); RequestContexts.setCurrentContext(requestContext); contextChain.preReadException(e); future.setException(e); <START> RequestContexts.setCurrentContext(oldRequestContext); <END> } }); return future; }</code><technical_language>try-finally in case user's preReadException throws</technical_language>

Target:
public ListenableFuture<Object> asynchronousInvoke( final RequestChannel channel, final TChannelBufferInputTransport inputTransport, final TChannelBufferOutputTransport outputTransport, final TProtocol inputProtocol, final TProtocol outputProtocol, final int sequenceId, final ClientContextChain contextChain, final Object[] args) throws Exception { final AsyncMethodCallFuture<Object> future = AsyncMethodCallFuture.create(contextChain); final RequestContext requestContext = RequestContexts.getCurrentContext(); contextChain.preWrite(args); outputTransport.resetOutputBuffer(); writeArguments(outputProtocol, sequenceId, args); ChannelBuffer requestBuffer = outputTransport.getOutputBuffer().copy(); contextChain.postWrite(args); channel.sendAsynchronousRequest(requestBuffer, false, new RequestChannel.Listener() { @Override public void onRequestSent() { if (oneway) { try { future.set(null); } catch (Exception e) { future.setException(e); } } } @Override public void onResponseReceived(ChannelBuffer message) { RequestContext oldRequestContext = RequestContexts.getCurrentContext(); RequestContexts.setCurrentContext(requestContext); try { contextChain.preRead(); inputTransport.setInputBuffer(message); waitForResponse(inputProtocol, sequenceId); Object results = readResponse(inputProtocol); contextChain.postRead(results); future.set(results); } catch (Exception e) { contextChain.postReadException(e); future.setException(e); } finally { RequestContexts.setCurrentContext(oldRequestContext); } } @Override public void onChannelError(TException e) { RequestContext oldRequestContext = RequestContexts.getCurrentContext(); RequestContexts.setCurrentContext(requestContext); try { contextChain.preReadException(e); future.setException(e); } finally { RequestContexts.setCurrentContext(oldRequestContext); } } }); return future; }