Micronaut-core: CompositeByteBuf is freed after first call

Created on 22 Aug 2018  路  3Comments  路  Source: micronaut-projects/micronaut-core

In my first application using new Micronaut I have a simple controller which calls one service class.

This service interface is annotated with Client to retrieve a file from another service using a simple REST call.

For the first time everything works fine. I get a filled CompositeByteBuf with the following properties:

  1. readIndex: 0
  2. writeIndex: 2160
  3. capacity: 2160
  4. components: 2

Therefore I am able to retrieve the underlying byte array and log the values to console.

But when I do this another time I am not able to get the bytes anymore. The CompositeByteBuf now has following properties:

  1. freed
  2. components: 2

I don't know what to do to get my simple application working.

After restarting the app the first call succeeds again.

What is wrong with following code snipped?

        CompositeByteBuf compositeByteBuf = serviceClient.getDocument(id)
        println compositeByteBuf

        println compositeByteBuf.readableBytes()
        byte[] data = new byte[compositeByteBuf.readableBytes()]
        println data.size()

        // this line is causing the error when calling a second or third time
        // io.netty.util.IllegalReferenceCountException: refCnt: 0
        compositeByteBuf.readBytes(data)

Thank you very much for your help.

notabug

Most helpful comment

Why are you returning a CompositeByteBuf from your service? You should specify a meaningful type, even if byte[] so the response data will be available.

A blocking client will have its buffer released immediately, which is the correct behavior

All 3 comments

Why are you returning a CompositeByteBuf from your service? You should specify a meaningful type, even if byte[] so the response data will be available.

A blocking client will have its buffer released immediately, which is the correct behavior

Thank you very much for your fast comment.

Well, what type of client will be the right one to get both the header information and the bytes? The low level one or the declarative one according to the docs?

Can you perhaps pass a short example?

Something like this?

@Client("/documents") 
public interface documentClient { 

  @Get("/{id}")
  Single<HttpResponse<byte[]>> getDocument(Long id)
}

This evening I solved my problem.

Implementing a low level client fulfills all my needs meaning having access to the response and retrieving the body as an array of bytes.

Was this page helpful?
0 / 5 - 0 ratings