[id='hotrod_streaming']
= Streaming API
{brandname} provides a Streaming API that implements methods that return
instances of `InputStream` and `OutputStream` so you can stream large objects
between Hot Rod clients and {brandname} servers.

Consider the following example of a large object:

[source,java]
----
StreamingRemoteCache<String> streamingCache = remoteCache.streaming();
OutputStream os = streamingCache.put("a_large_object");
os.write(...);
os.close();
----

You could read the object through streaming as follows:

[source,java]
----
StreamingRemoteCache<String> streamingCache = remoteCache.streaming();
InputStream is = streamingCache.get("a_large_object");
for(int b = is.read(); b >= 0; b = is.read()) {
   // iterate
}
is.close();
----

[NOTE]
====
The Streaming API does *not* marshall values, which means you cannot access the
same entries using both the Streaming and Non-Streaming API at the same time.
You can, however, implement a custom marshaller to handle this case.
====

The `InputStream` returned by the `RemoteStreamingCache.get(K key)` method
implements the `VersionedMetadata` interface, so you can retrieve version and
expiration information as follows:

[source,java]
----
StreamingRemoteCache<String> streamingCache = remoteCache.streaming();
InputStream is = streamingCache.get("a_large_object");
long version = ((VersionedMetadata) is).getVersion();
for(int b = is.read(); b >= 0; b = is.read()) {
   // iterate
}
is.close();
----

[NOTE]
====
Conditional write methods (`putIfAbsent()`, `replace()`) perform the actual
condition check after the value is completely sent to the server. In other
words, when the `close()` method is invoked on the `OutputStream`.
====

.Reference

* link:{javadocroot}/org/infinispan/client/hotrod/StreamingRemoteCache.html[org.iinfinispan.client.hotrod.StreamingRemoteCache]
