title: Reactive Quarkus app behaving differently when run as Java or native
body: <p>I have a reactive quarkus app with hibernate-panache-reactive. The problem is it behaves differently when I run it as a Java app or a native app.</p>
  <p>The app</p>
  <ol>
  <li>loads a lot of data from a MySQL DB via hibernate-panache-reactive</li>
  <li>builds a graph based on the data loaded</li>
  <li>runs some time consuming algorithm on the graph</li>
  <li>loads some more data from the DB based on the results returned from 3)</li>
  </ol>
  <p>So initially the code looked something like this:</p>
  <pre><code>GraphProcessor graphProcessor = createInitialProcessor();
          return Uni.createFrom().item(graphProcessor)
  // 1) loading of initial data
                  .onItem().transformToUni(this::loadDataViaPanaceReactive1)
                  .onItem().transformToUni(this::loadDataViaPanaceReactive2)
                  .onItem().transformToUni(this::loadDataViaPanaceReactive3)
  // 2) building of graph               
                  .onItem().transform(graphProcessor::processLoadedData)
                  .onItem().invoke(graphProcessor::loadingComplete) //sync
  // 3) running time consuming algorithm on graph
                  .onItem().transformToMulti(this::runTimeConsumingTask)
                  .onItem().invoke(this::prepareDBQueries)
  // 4) load more data from DB
                  .onItem().transformToUniAndConcatenate(this::loadMoreData1)
                  .onItem().transformToUniAndConcatenate(this::loadMoreData2)
                  .onItem().transformToUniAndConcatenate(this::transformToPublicForm)
                  .onFailure().invoke(log::error);
  </code></pre>
  <p>That worked fine when run as a Java app but when I tried to run it as a native app it first complained that the computation in 2 and 3 were taking too long and this was blocking the calling thread.</p>
  <p>I fixed that by using</p>
  <pre><code>.emitOn(Infrastructure.getDefaultWorkerPool())
  </code></pre>
  <p>Between 1 and 2</p>
  <p>This time I got another error</p>
  <blockquote>
  <p>java.lang.IllegalStateException: HR000069: Detected use of the
  reactive Session from a different Thread than the one which was used
  to open the reactive Session - this suggests an invalid integration;
  original thread: 'vert.x-eventloop-thread-0' current Thread:
  'vert.x-eventloop-thread-1'</p>
  </blockquote>
  <p>I've fixed that by inserting</p>
  <pre><code>.emitOn(Infrastructure.getDefaultExecutor())
  </code></pre>
  <p>between 3 and 4.</p>
  <pre><code>GraphProcessor graphProcessor = createInitialProcessor();
          return Uni.createFrom().item(graphProcessor)
  // 1) loading of initial data
                  .onItem().transformToUni(this::loadDataViaPanaceReactive1)
                  .onItem().transformToUni(this::loadDataViaPanaceReactive2)
                  .onItem().transformToUni(this::loadDataViaPanaceReactive3)
  // 2) building of graph               
                  .emitOn(Infrastructure.getDefaultWorkerPool()) // Required for native mode
                  .onItem().transform(graphProcessor::processLoadedData)
                  .onItem().invoke(graphProcessor::loadingComplete)
  // 3) running time consuming algorithm on graph
                  .onItem().transformToMulti(this::runTimeConsumingTask)
                  .onItem().invoke(this::prepareDBQueries)
                  .emitOn(Infrastructure.getDefaultExecutor()) // Required for native mode
  // 4) load more data from DB
                  .onItem().transformToUniAndConcatenate(this::loadMoreData1)
                  .onItem().transformToUniAndConcatenate(this::loadMoreData2)
                  .onItem().transformToUniAndConcatenate(this::transformToPublicForm)
                  .onFailure().invoke(log::error);
  </code></pre>
  <p>That worked when run in native mode but now when I run it in Java I get the same exception (Detected use of the
  reactive Session from a different Thread than the one which was used
  to open the reactive Session)</p>
  <p>The emitOn(Infrastructure.getDefaultExcecutor()) should have switched back to the original thread.</p>
  <p>The odd thing is also that this exception is not thrown every time I hit the app.
  So what am I doing wrong here? What is the best way to handle time consuming tasks and then having to do some more DB queries after?</p>
  <p>You could use .runSubscriptionOn(Executor) but I would need to switch back to the original thread for part 4 again.</p>
  <p>Thanks for you help.</p>