This class asynchronously pulls responses from upstream via StreamController#request(int) and exposes them via its Iterator. The implementation is back
pressure aware and uses a constant buffer of 1 item.
Please note that the stream can only be consumed once and must either be fully consumed or be
canceled.
This class can also be used to send requests to the server using #send(Object).
Neither this class nor the iterator it returns is thread-safe.
In the example below, we iterate through responses from the server and echo back the items we
see:
BidiStream<Item>stream=...;for(Itemitem:stream){System.out.println(item.id());stream.send(item.id());// Allow for early terminationif(item.id().equals("needle")){// Cancelling the stream will cause hasNext() to return false on the next iteration,// naturally breaking the loop.stream.cancel();}}
[[["Easy to understand","easyToUnderstand","thumb-up"],["Solved my problem","solvedMyProblem","thumb-up"],["Other","otherUp","thumb-up"]],[["Missing the information I need","missingTheInformationINeed","thumb-down"],["Too complicated / too many steps","tooComplicatedTooManySteps","thumb-down"],["Out of date","outOfDate","thumb-down"],["Samples / code issue","samplesCodeIssue","thumb-down"],["Other","otherDown","thumb-down"]],["Last updated 2025-08-28 UTC."],[[["\u003cp\u003eThe \u003ccode\u003eBidiStream\u003c/code\u003e class is a wrapper for bidirectional streams, enabling asynchronous pulling of responses and sending of requests.\u003c/p\u003e\n"],["\u003cp\u003eThis class is not thread-safe and can only be consumed once, requiring either complete consumption or cancellation.\u003c/p\u003e\n"],["\u003cp\u003eThe \u003ccode\u003eBidiStream\u003c/code\u003e uses a back-pressure-aware implementation with a buffer size of one and is capable of sending messages and closing the send stream, even with an error.\u003c/p\u003e\n"],["\u003cp\u003eThe provided content highlights a comprehensive list of available versions for the \u003ccode\u003eBidiStream\u003c/code\u003e class, starting from version 2.63.1 down to 2.7.1, with 2.63.1 being the latest.\u003c/p\u003e\n"]]],[],null,["# Class BidiStream<RequestT,ResponseT> (2.69.0)\n\nVersion latestkeyboard_arrow_down\n\n- [2.69.0 (latest)](/java/docs/reference/gax/latest/com.google.api.gax.rpc.BidiStream)\n- [2.68.2](/java/docs/reference/gax/2.68.2/com.google.api.gax.rpc.BidiStream)\n- [2.67.0](/java/docs/reference/gax/2.67.0/com.google.api.gax.rpc.BidiStream)\n- [2.66.0](/java/docs/reference/gax/2.66.0/com.google.api.gax.rpc.BidiStream)\n- [2.65.0](/java/docs/reference/gax/2.65.0/com.google.api.gax.rpc.BidiStream)\n- [2.63.1](/java/docs/reference/gax/2.63.1/com.google.api.gax.rpc.BidiStream)\n- [2.62.0](/java/docs/reference/gax/2.62.0/com.google.api.gax.rpc.BidiStream)\n- [2.61.0](/java/docs/reference/gax/2.61.0/com.google.api.gax.rpc.BidiStream)\n- [2.60.0](/java/docs/reference/gax/2.60.0/com.google.api.gax.rpc.BidiStream)\n- [2.59.1](/java/docs/reference/gax/2.59.1/com.google.api.gax.rpc.BidiStream)\n- [2.58.0](/java/docs/reference/gax/2.58.0/com.google.api.gax.rpc.BidiStream)\n- [2.57.0](/java/docs/reference/gax/2.57.0/com.google.api.gax.rpc.BidiStream)\n- [2.55.0](/java/docs/reference/gax/2.55.0/com.google.api.gax.rpc.BidiStream)\n- [2.54.1](/java/docs/reference/gax/2.54.1/com.google.api.gax.rpc.BidiStream)\n- [2.53.0](/java/docs/reference/gax/2.53.0/com.google.api.gax.rpc.BidiStream)\n- [2.52.0](/java/docs/reference/gax/2.52.0/com.google.api.gax.rpc.BidiStream)\n- [2.51.0](/java/docs/reference/gax/2.51.0/com.google.api.gax.rpc.BidiStream)\n- [2.50.0](/java/docs/reference/gax/2.50.0/com.google.api.gax.rpc.BidiStream)\n- [2.49.0](/java/docs/reference/gax/2.49.0/com.google.api.gax.rpc.BidiStream)\n- [2.48.1](/java/docs/reference/gax/2.48.1/com.google.api.gax.rpc.BidiStream)\n- [2.47.0](/java/docs/reference/gax/2.47.0/com.google.api.gax.rpc.BidiStream)\n- [2.46.1](/java/docs/reference/gax/2.46.1/com.google.api.gax.rpc.BidiStream)\n- [2.45.0](/java/docs/reference/gax/2.45.0/com.google.api.gax.rpc.BidiStream)\n- [2.43.0](/java/docs/reference/gax/2.43.0/com.google.api.gax.rpc.BidiStream)\n- [2.42.0](/java/docs/reference/gax/2.42.0/com.google.api.gax.rpc.BidiStream)\n- [2.41.0](/java/docs/reference/gax/2.41.0/com.google.api.gax.rpc.BidiStream)\n- [2.39.0](/java/docs/reference/gax/2.39.0/com.google.api.gax.rpc.BidiStream)\n- [2.38.0](/java/docs/reference/gax/2.38.0/com.google.api.gax.rpc.BidiStream)\n- [2.37.0](/java/docs/reference/gax/2.37.0/com.google.api.gax.rpc.BidiStream)\n- [2.36.0](/java/docs/reference/gax/2.36.0/com.google.api.gax.rpc.BidiStream)\n- [2.35.0](/java/docs/reference/gax/2.35.0/com.google.api.gax.rpc.BidiStream)\n- [2.34.1](/java/docs/reference/gax/2.34.1/com.google.api.gax.rpc.BidiStream)\n- [2.33.0](/java/docs/reference/gax/2.33.0/com.google.api.gax.rpc.BidiStream)\n- [2.32.1](/java/docs/reference/gax/2.32.1/com.google.api.gax.rpc.BidiStream)\n- [2.31.1](/java/docs/reference/gax/2.31.1/com.google.api.gax.rpc.BidiStream)\n- [2.30.1](/java/docs/reference/gax/2.30.1/com.google.api.gax.rpc.BidiStream)\n- [2.24.0](/java/docs/reference/gax/2.24.0/com.google.api.gax.rpc.BidiStream)\n- [2.23.3](/java/docs/reference/gax/2.23.3/com.google.api.gax.rpc.BidiStream)\n- [2.22.0](/java/docs/reference/gax/2.22.0/com.google.api.gax.rpc.BidiStream)\n- [2.21.0](/java/docs/reference/gax/2.21.0/com.google.api.gax.rpc.BidiStream)\n- [2.20.1](/java/docs/reference/gax/2.20.1/com.google.api.gax.rpc.BidiStream)\n- [2.19.6](/java/docs/reference/gax/2.19.6/com.google.api.gax.rpc.BidiStream)\n- [2.18.7](/java/docs/reference/gax/2.18.7/com.google.api.gax.rpc.BidiStream)\n- [2.17.0](/java/docs/reference/gax/2.17.0/com.google.api.gax.rpc.BidiStream)\n- [2.16.0](/java/docs/reference/gax/2.16.0/com.google.api.gax.rpc.BidiStream)\n- [2.15.0](/java/docs/reference/gax/2.15.0/com.google.api.gax.rpc.BidiStream)\n- [2.14.0](/java/docs/reference/gax/2.14.0/com.google.api.gax.rpc.BidiStream)\n- [2.13.0](/java/docs/reference/gax/2.13.0/com.google.api.gax.rpc.BidiStream)\n- [2.12.2](/java/docs/reference/gax/2.12.2/com.google.api.gax.rpc.BidiStream)\n- [2.11.0](/java/docs/reference/gax/2.11.0/com.google.api.gax.rpc.BidiStream)\n- [2.10.0](/java/docs/reference/gax/2.10.0/com.google.api.gax.rpc.BidiStream)\n- [2.9.0](/java/docs/reference/gax/2.9.0/com.google.api.gax.rpc.BidiStream)\n- [2.8.1](/java/docs/reference/gax/2.8.1/com.google.api.gax.rpc.BidiStream)\n- [2.7.1](/java/docs/reference/gax/2.7.1/com.google.api.gax.rpc.BidiStream) \n\n public class BidiStream\u003cRequestT,ResponseT\u003e extends ServerStream\u003cResponseT\u003e implements ClientStream\u003cRequestT\u003e\n\nA wrapper around a bidirectional stream.\n\nThis class asynchronously pulls responses from upstream via [StreamController#request(int)](/java/docs/reference/gax/latest/com.google.api.gax.rpc.StreamController#com_google_api_gax_rpc_StreamController_request_int_) and exposes them via its Iterator. The implementation is back\npressure aware and uses a constant buffer of 1 item.\n\nPlease note that the stream can only be consumed once and must either be fully consumed or be\ncanceled.\n\nThis class can also be used to send requests to the server using [#send(Object)](/java/docs/reference/gax/latest/com.google.api.gax.rpc.BidiStream#com_google_api_gax_rpc_BidiStream_send_).\n\nNeither this class nor the iterator it returns is thread-safe.\n\nIn the example below, we iterate through responses from the server and echo back the items we\nsee: \n\n\n BidiStream\u003cItem\u003e stream = ...;\n\n for (Item item : stream) {\n System.out.println(item.id());\n\n stream.send(item.id());\n\n // Allow for early termination\n if (item.id().equals(\"needle\")) {\n // Cancelling the stream will cause `hasNext()` to return false on the next iteration,\n // naturally breaking the loop.\n stream.cancel();\n }\n }\n \nInheritance\n-----------\n\n[java.lang.Object](https://docs.oracle.com/javase/8/docs/api/java/lang/Object.html) \\\u003e [ServerStream](/java/docs/reference/gax/latest/com.google.api.gax.rpc.ServerStream) \\\u003e BidiStream\\\u003cRequestT,ResponseT\\\u003e \n\nImplements\n----------\n\ncom.google.api.gax.rpc.ClientStream\\\u003cRequestT\\\u003e \n\nInherited Members\n-----------------\n\n[ServerStream.cancel()](/java/docs/reference/gax/latest/com.google.api.gax.rpc.ServerStream#com_google_api_gax_rpc_ServerStream_cancel__) \n[ServerStream.isReceiveReady()](/java/docs/reference/gax/latest/com.google.api.gax.rpc.ServerStream#com_google_api_gax_rpc_ServerStream_isReceiveReady__) \n[ServerStream.iterator()](/java/docs/reference/gax/latest/com.google.api.gax.rpc.ServerStream#com_google_api_gax_rpc_ServerStream_iterator__) \n[ServerStream.stream()](/java/docs/reference/gax/latest/com.google.api.gax.rpc.ServerStream#com_google_api_gax_rpc_ServerStream_stream__) \n[Object.clone()](https://docs.oracle.com/javase/8/docs/api/java/lang/Object.html#clone--) \n[Object.equals(Object)](https://docs.oracle.com/javase/8/docs/api/java/lang/Object.html#equals-java.lang.Object-) \n[Object.finalize()](https://docs.oracle.com/javase/8/docs/api/java/lang/Object.html#finalize--) \n[Object.getClass()](https://docs.oracle.com/javase/8/docs/api/java/lang/Object.html#getClass--) \n[Object.hashCode()](https://docs.oracle.com/javase/8/docs/api/java/lang/Object.html#hashCode--) \n[Object.notify()](https://docs.oracle.com/javase/8/docs/api/java/lang/Object.html#notify--) \n[Object.notifyAll()](https://docs.oracle.com/javase/8/docs/api/java/lang/Object.html#notifyAll--) \n[Object.toString()](https://docs.oracle.com/javase/8/docs/api/java/lang/Object.html#toString--) \n[Object.wait()](https://docs.oracle.com/javase/8/docs/api/java/lang/Object.html#wait--) \n[Object.wait(long)](https://docs.oracle.com/javase/8/docs/api/java/lang/Object.html#wait-long-) \n[Object.wait(long,int)](https://docs.oracle.com/javase/8/docs/api/java/lang/Object.html#wait-long-int-)\n\nMethods\n-------\n\n### closeSend()\n\n public void closeSend()\n\nCloses the sending side of the stream. Once called, no further calls to [#send(Object)](/java/docs/reference/gax/latest/com.google.api.gax.rpc.BidiStream#com_google_api_gax_rpc_BidiStream_send_),\n[#closeSend()](/java/docs/reference/gax/latest/com.google.api.gax.rpc.BidiStream#com_google_api_gax_rpc_BidiStream_closeSend__), or [#closeSendWithError(Throwable)](/java/docs/reference/gax/latest/com.google.api.gax.rpc.BidiStream#com_google_api_gax_rpc_BidiStream_closeSendWithError_java_lang_Throwable_) are allowed.\n\nCalling this method does not affect the receiving side, the iterator will continue to yield\nresponses from the server.\n\n### closeSendWithError(Throwable t)\n\n public void closeSendWithError(Throwable t)\n\nCloses the sending side of the stream with error. The error is propagated to the server. Once\ncalled, no further calls to [#send(Object)](/java/docs/reference/gax/latest/com.google.api.gax.rpc.BidiStream#com_google_api_gax_rpc_BidiStream_send_), [#closeSend()](/java/docs/reference/gax/latest/com.google.api.gax.rpc.BidiStream#com_google_api_gax_rpc_BidiStream_closeSend__), or [#closeSendWithError(Throwable)](/java/docs/reference/gax/latest/com.google.api.gax.rpc.BidiStream#com_google_api_gax_rpc_BidiStream_closeSendWithError_java_lang_Throwable_) are allowed.\n\nCalling this method does not affect the receiving side, the iterator will continue to yield\nresponses from the server.\n\n### isSendReady()\n\n public boolean isSendReady()\n\nReports whether a message can be sent without requiring excessive buffering internally.\n\nThis method only provides a hint. It is still correct for the user to call [#send(Object)](/java/docs/reference/gax/latest/com.google.api.gax.rpc.BidiStream#com_google_api_gax_rpc_BidiStream_send_) even when this method returns `false`.\n\n### send(RequestT req)\n\n public void send(RequestT req)\n\nSend `req` to the server."]]