Skip to content

Commit

Permalink
Simplify documentation
Browse files Browse the repository at this point in the history
  • Loading branch information
LarsSven authored and ozangunalp committed Jan 27, 2025
1 parent ce6d33e commit c2b3e3c
Showing 1 changed file with 7 additions and 44 deletions.
51 changes: 7 additions & 44 deletions docs/src/main/asciidoc/kafka.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -2955,10 +2955,10 @@ Let's imagine the following process:
NOTE: If you use Hibernate Reactive, look at <<writing-entities-managed-by-hibernate-reactive-to-kafka>>.

Because we write to a database, we must run this method in a transaction.
Yet, sending the entity to Kafka happens asynchronously. Therefore, we must be sure that the transaction is still running until the object is written.
There are two ways to achieve this: Either we wait for the Kafka operation to complete before returning, or we return a `CompletionStage` or `Uni` and let the transaction commit when the Kafka operation completes.
Yet, sending the entity to Kafka happens asynchronously.
We can achieve this by using `.sendAndAwait()` or `.sendAndForget()` on the `MutinyEmitter`, or `.send().toCompletableFuture().join()` on the `Emitter`.

To implement this process by awaiting the Kafka operation, you need the following approach:
To implement this process, you need the following approach:

[source, java]
----
Expand All @@ -2980,10 +2980,10 @@ public class ResourceSendingToKafka {
@POST
@Path("/fruits")
@Transactional // <1>
public void storeAndSendToKafka(Fruit fruit) { // <2>
@Transactional // <1>
public void storeAndSendToKafka(Fruit fruit) { // <2>
fruit.persist();
return emitter.sendAndAwait(new FruitDto(fruit)); // <3>
emitter.sendAndAwait(new FruitDto(fruit)); // <3>
}
}
----
Expand All @@ -2993,44 +2993,7 @@ public class ResourceSendingToKafka {
This makes sure that managed entity is not impacted by the Kafka serialization.
Then await the completion of the operation before returning.

The alternative approach of returning a `CompletionStage` is as follows:

[source, java]
----
package org.acme;
import java.util.concurrent.CompletionStage;
import jakarta.transaction.Transactional;
import jakarta.ws.rs.POST;
import jakarta.ws.rs.Path;
import org.eclipse.microprofile.reactive.messaging.Channel;
import org.eclipse.microprofile.reactive.messaging.Emitter;
@Path("/")
public class ResourceSendingToKafka {
@Channel("kafka") Emitter<Fruit> emitter;
@POST
@Path("/fruits")
@Transactional // (1)
public CompletionStage<Void> storeAndSendToKafka(Fruit fruit) { // (2)
fruit.persist();
return emitter.send(new FruitDto(fruit)); // (3)
}
}
----
<1> As we are writing to the database, make sure we run inside a transaction
<2> The method receives the fruit instance to persist. It returns a `CompletionStage` which is used for the transaction demarcation. The transaction is committed when the return `CompletionStage` completes. In our case, it's when the message is written to Kafka.
<3> Wrap the managed entity inside a Data transfer object and send it to Kafka.
This makes sure that managed entity is not impacted by the Kafka serialization.

There are however a few reasons why the first approach is preferred for most usecases:

1. The `MutinyEmitter` is more optimized than the `Emitter`.
2. When returning an asynchronous operation (`CompletionStage` or `Uni`) with `@Transactional`, the transaction is committed by the asynchronous operation. All asynchronous operations are executed on the same thread, so the throughput of the application may slow down as transaction commits cannot run in parallel anymore.
NOTE: You should not return a `CompletionStage` or `Uni` when using `@Transactional`, as all transaction commits will happen on a single thread, which impacts performance.

[[writing-entities-managed-by-hibernate-reactive-to-kafka]]
=== Writing entities managed by Hibernate Reactive to Kafka
Expand Down

0 comments on commit c2b3e3c

Please sign in to comment.