---
schema_version: "1"
id: 91298dc60e01727466d737584ea64784306ece3b00161099a913e8cff05fce83
title: Object Streaming (Pagination)
collection: mulesoft
version: current
locale: en-us
portal_url: https://docs.salesforce.com/mulesoft/current/en-us/mule-sdk/latest/object-streaming.md
canonical_url: https://docs.mulesoft.com/mule-sdk/latest/object-streaming
source_site: docs.mulesoft.com
content_type: documentation
content_hash: 7e0d0eff2235efaecb20f027b923f0faeee1db4f3482470a548905625847f52f
description: MuleSoft Documentation Site
release: "1.13"
latest: true
---
---
product: Mule SDK
version: 1.13
is-latest-version: true
keywords: mule, sdk, streaming, objects, pagination
---

# Object Streaming (Pagination)

> For the full documentation index, see: https://docs.mulesoft.com/llms.txt

Object streaming is similar to [binary streaming](https://docs.mulesoft.com/mule-sdk/latest/binary-streaming), except that it streams Java
objects, not a raw byte stream.

Here is an example that use object streaming through an oversimplified Select operation from the
Database connector:

```java
public PagingProvider<DbConnection, Map<String, Object>> list(@Text String sql) { (1)
    return new PagingProvider<DbConnection, Map<String, Object>>() {

      private ResultSet resultSet;

      @Override
      public List<Map<String, Object>> getPage(DbConnection connection) { (2)
        if (resultSet == null) {
            resultSet = executeQuery(connection, sql); (3)
        }

        return extractPageFrom(resultSet);
      }

      @Override
      public java.util.Optional<Integer> getTotalResults(DbConnection connection) {
        return java.util.Optional.empty(); (4)
      }

      @Override
      public void close(DbConnection connection) throws MuleException {
        resultSet.close(); (5)
      }
    }
}
```

<table><tbody><tr><td><i data-value="1"></i><b>1</b></td><td>Two things to notice about the signature of this method:<div><ul><li><p>The method returns a <code>PagingDelegate</code> object. <code>PagingDelegate</code> requires two generic types. The first one is the type of connection the delegate will use to get the next pages, and the second is the type of the elements in the page.</p></li><li><p>The List operation receives the parameters. However, notice that is does not receive a connection object. Paged operations cannot receive connections. Instead, they must always use the connections that the runtime passes to the <code>PagingProvider</code>.</p><div><p>So, this signature means that it will return the results of the query in pages, using a <code>DbConnection</code> object, and each item in the stream will be a <code>Map&lt;String, Object&gt;</code> that represents each row in the result.</p></div></li></ul></div></td></tr><tr><td><i data-value="2"></i><b>2</b></td><td><code>getPage()</code> fetches the next page and returns it. It receives the connection to use to fetch that page. When the stream is over, this method needs to return an empty List. Implementations should ensure that no empty pages are returned before the stream is finished.</td></tr><tr><td><i data-value="3"></i><b>3</b></td><td>Depending on the operation’s logic, you might need logic to obtain the first page versus logic to obtain the next pages.</td></tr><tr><td><i data-value="4"></i><b>4</b></td><td>Another feature of object streaming is the ability to tell how many objects are actually in the streams. To determine that, you need to implement the <code>getTotalResults()</code> method. The problem is that not all APIs support that. For example, the <em>Salesforce</em> API supports that, but JDBC (the API powering the Database connector) does not. That is why this method returns a Java <code>Optional</code>, in this case, an empty one. Users of your paginated operation can obtain this value through an expression similar to <code>#[payload.size]</code>.</td></tr><tr><td><i data-value="5"></i><b>5</b></td><td>Finally, the <code>close()</code> method will be invoked when no more objects are in the stream. This method <strong>IS NOT</strong> for closing the connection. The SDK will do that automatically. The method is for releasing any resources that this paging delegate might be holding. For example, in this case, the paging delegate has a <code>ResultSet</code> from which each of the page values are extracted. That <code>ResultSet</code> needs to be released.</td></tr></tbody></table>

## Sticky Connections

By default, there is no guarantee that the connection that `getPage()` receives will be the same one
on each invocation. And that is fine. For most APIs (especially Rest APIs), this is not only _not_ a
problem, but in some cases, it is a feature. However, there are other cases (like Database) in which
all pages **MUST** be obtained using the **SAME** connection. This was impossible to do with Devkit.

Mule SDK adds sticky connections, which signal that the runtime must guarantee that the `getPage()`
method is always invoked with the same transaction, for example:

```java
public PagingProvider<DbConnection, Map<String, Object>> list(String sql) {
    return new PagingProvider<DbConnection, Map<String, Object>>() {

      private ResultSet resultSet;

      @Override
      public List<Map<String, Object>> getPage(DbConnection connection) {
        ...
      }

      @Override
      public java.util.Optional<Integer> getTotalResults(DbConnection connection) {
        ...
      }

      @Override
      public void close(DbConnection connection) throws MuleException {
        ...
      }

      @Override
      public boolean useStickyConnections() {
        return true;
      }
    }
}
```

## Configuring Streaming

Just like with binary streaming, auto-paged operations automatically get the streaming configuration
through `<repeatable-in-memory-iterable />`, `<ee:repeatable-file-store-iterable />`, and
`<non-repeatable-iterable />`. For details on these elements, see
[binary streaming](https://docs.mulesoft.com/mule-sdk/latest/binary-streaming). Here is an example that configures custom file store streaming
for the select example above:

```xml
<db:select sql="select * from REALLY_LARGE_TABLE">
    <ee:repeatable-file-store-iterable inMemoryObjects="100"/>
</db:select>
```
