Search code examples
javainputstreambytebuffer

How to make read-only data in ByteBuffer to be safely consumed by InputStream multiple times?


I am building an API and I want some read-only, static data to be loaded at startup. Below I am calling a remote API for such data to be loaded at startup and their SDK only has a return type of ByteBuffer:

class MyService {
  private ByteBuffer remoteData;

  @PostContruct
  public void init() {
    remoteData = callAPI(); // returns ByteBuffer as type
  }

  public getDataAndDoSomething(Request req) {
    try (Inputstream is = new ByteBufferBackedInputStream(remoteData)) {
      // proceed with ByteBufferBackedInputStream
    }
  }
}

The issue with above is that after initial invocation of getDataAndDoSomething(), remoteData is no longer consumable. This wouldn't be a issue if I make remoteData a local variable and call remote API each time, but I'd like to load remoteData only at startup.

I suspect I'd need to make a deepcopy of it somehow each time InputStream wants to consume it, but the ByteBuffer APIs are rather confusing. What is a good approach to make this safe to consume from multiple threads that invoke getDataAndDoSomething()?


Solution

  • I have the idea of cloning the current ByteBuffer each time, you can use the method duplicate() :

    ByteBuffer java.nio.ByteBuffer.duplicate()

    Creates a new byte buffer that shares this buffer's content.

    class MyService {
      private ByteBuffer remoteData;
    
      @PostContruct
      public void init() {
        remoteData = callAPI(); // returns ByteBuffer as type
      }
    
      public getDataAndDoSomething(Request req) {
        ByteBuffer remoteToBeUsed = remoteData.duplicate();
        try (Inputstream is = new ByteBufferBackedInputStream(remoteToBeUsed )) {
          // proceed with ByteBufferBackedInputStream
        }
      }
    }