quarkusio / quarkus

Quarkus: Supersonic Subatomic Java.
https://quarkus.io
Apache License 2.0
13.87k stars 2.71k forks source link

Quarkus Resteasy-reactive Client and InputStream as parameter causing a BlockingOperationNotAllowedException #33346

Open forsti0506 opened 1 year ago

forsti0506 commented 1 year ago

Describe the bug

Hi,

if you are using quarkus-resteasy-reactive rest-client and you are using a RestClient where an input parameter is an InputStream and afterwards you are performing an blocking operation on the ClientSide (for example an database write with the content of the stream) you are getting a BlockingNotAllowed exception!

Expected behavior

InputStream can be used to contribute large data between services without restriction.

Actual behavior

InputStream can be used without doing some blocking operation in the read of the stream

How to Reproduce?

(Very easy and not realse useful example, but tried to do it as easy as possible)

  1. Checkout: https://github.com/forsti0506/quarkus-inputstream-resthandling
  2. Start the 2 quarkus-services
  3. Make a get call to localhost:8082/hello
  4. see the BlockingNotAllowedException

Output of uname -a or ver

No response

Output of java -version

No response

GraalVM version (if different from Java)

No response

Quarkus version or git rev

No response

Build tool (ie. output of mvnw --version or gradlew --version)

No response

Additional information

No response

quarkus-bot[bot] commented 1 year ago

/cc @FroMage (resteasy-reactive), @Sgitario (resteasy-reactive), @geoand (resteasy-reactive), @stuartwdouglas (resteasy-reactive)

geoand commented 1 year ago

@Sgitario didn't you fix something similar?

Sgitario commented 1 year ago

@Sgitario didn't you fix something similar?

I guess you mean these two changes:

I don't think any of these are related to this issue. The issue here is that you're having a custom InputStream that internally is performing a blocking operation (a database query):

public class MyInputStream extends InputStream {
    EntityManager em;
    public MyInputStream(String input, EntityManager em) {
        var test = new TestEntitiy();
        this.em = em;
        test.setName(new String(input));
        em.persist(test);
    }

    @Override
    public int read() throws IOException {
        var results = em.createQuery("SELECT a FROM TestEntitiy a", TestEntitiy.class).getResultList();

        return results.size();
    }
}

Honestly, I think this use case is a bit tricky. Normally, you perform the query and then call the client. @forsti0506 can you elaborate a bit more on why are you doing it? If what you want is to send entities in batches, the way to go should be https://quarkus.io/guides/rest-client-reactive#multipart-mixed-odata-usage.

forsti0506 commented 1 year ago

We are transferring large Files from one MicroService to another one and there the content is stored in a database for example!

I don't know the concept of odata. I will have a look at that!

mkomadel commented 9 months ago

Hi, @geoand has there been any development in this issue? I have seen that similar problem in rest client exception mapper was solved by marking the exception mapper with @Blocking annotation (https://quarkus.io/guides/rest-client-reactive#using-blocking-annotation-in-exception-mappers).

geoand commented 9 months ago

No updates yet