<commit_before>////
This guide is maintained in the main Quarkus repository
and pull requests should be submitted there:
https://github.com/quarkusio/quarkus/tree/master/docs/src/main/asciidoc
////
= Using Software Transactional Memory in Quarkus

include::./attributes.adoc[]
:extension-status: preview

Software Transactional Memory (STM) has been around in research environments since the late
1990's and has relatively recently started to appear in products and various programming
languages. We won't go into all of the details behind STM but the interested reader could look at https://groups.csail.mit.edu/tds/papers/Shavit/ShavitTouitou-podc95.pdf[this paper].
However, suffice it to say that STM offers an approach to developing transactional applications in a highly
concurrent environment with some of the same characteristics of ACID transactions, which you've probably already used
through JTA. Importantly though, the Durability property is relaxed (removed) within STM implementations,
or at least made optional. This is not the situation with JTA, where state changes are made durable
to a relational database which supports https://pubs.opengroup.org/onlinepubs/009680699/toc.pdf[the X/Open XA
standard].

Note, the STM implementation provided by Quarkus is based on the https://narayana.io/docs/project/index.html#d0e16066[Narayana STM] implementation. This document isn't meant to be a replacement for that project's documentation so you may want
to look at that for more detail. However, we will try to focus more on how you can combine some of the key capabilities
into Quarkus when developing Kubernetes native applications and microservices.

== Why use STM with Quarkus?

Now you may still be asking yourself "Why STM instead of JTA?" or "What are the benefits
to STM that I don't get from JTA?" Let's try to answer those or similar questions, with
a particular focus on why we think they're great for Quarkus, microservices and Kubernetes
native applications. So in no specific order ...

* The goal of STM is to simplify object reads and writes from multiple threads/protect
state from concurrent updates. The Quarkus STM implementation will safely manage any conflicts between
these threads using whatever isolation model has been chosen to protect that specific state
instance (object in the case of Quarkus). In Quarkus STM, there are two isolation implementations,
pessimistic (the default), which would cause conflicting threads to be blocked until the original
has completed its updates (committed or aborted the transaction); then there's the optimistic
approach which allows all of the threads to proceed and checks for conflicts at commit time, where
one or more of the threads may be forced to abort if there have been conflicting updates.

* STM objects have state but it doesn't need to be persistent (durable). In fact the
default behaviour is for objects managed within transactional memory to be volatile, such that
if the service or microservice within which they are being used crashes or is spawned elsewhere, e.g.,
by a scheduler, all state in memory is lost and the objects start from scratch. But surely you get this and more
with JTA (and a suitable transactional datastore) and don't need to worry about restarting your application?
Not quite. There's a trade-off here: we're doing away
with persistent state and the overhead of reading from and then writing (and sync-ing) to the datastore during each
transaction. This makes updates to (volatile) state very fast but you still get the benefits of atomic updates
across multiple STM objects (e.g., objects your team wrote then calling objects you inherited from another team and requiring
them to make all-or-nothing updates), as well as consistency
and isolation in the presence of concurrent threads/users (common in distributed microservices architectures).
Furthermore, not all stateful applications need to be durable - even when JTA transactions are used, it tends to be the
exception and not the rule. And as you'll see later, because applications can optionally start and control transactions, it's possible to build microservices which can undo state changes and try alternative paths.

* Another benefit of STM is composability and modularity. You can write concurrent Quarkus objects/services that
can be easily composed with any other services built using STM, without exposing the details of how the objects/services
are implemented. As we discussed earlier, this ability to compose objects you wrote with those other teams may have
written weeks, months or years earlier, and have A, C and I properties can be hugely beneficial. Furthermore, some
STM implementations, including the one Quarkus uses, support nested transactions and these allow changes made within
the context of a nested (sub) transaction to later be rolled back by the parent transaction.

* Although the default for STM object state is volatile, it is possible to configure the STM implementation
such that an object's state is durable. Although it's possible to configure Narayana such that different
backend datastores can be used, including relational databases, the default is the local operating system
file system, which means you don't need to configure anything else with Quarkus such as a database.

* Many STM implementations allow "plain old language objects" to be made STM-aware with little or no changes to
the application code. You can build, test and deploy applications without wanting them to be STM-aware and
then later add those capabilities if they become necessary and without much development overhead at all.

== Building STM applications

There is also a fully worked example in the quickstarts which you may access by cloning the
Git repository: `git clone {quickstarts-clone-url}`, or by downloading an {quickstarts-archive-url}[archive].
Look for the `software-transactional-memory-quickstart` example. This will help to understand how you
can build STM-aware applications with Quarkus. However, before we do so there are a few basic concepts
which we need to cover.

Note, as you will see, STM in Quarkus relies on a number of annotations to define behaviours. The lack
of these annotations causes sensible defaults to be assumed but it is important for the developer to
understand what these may be. Please refer to the https://narayana.io/docs/project/index.html#d0e16066[Narayana STM manual]
and the https://narayana.io//docs/project/index.html#d0e16133[STM annotations guide] for more details on
all of the annotations Narayana STM provides.

include::./status-include.adoc[]

== Setting it up

To use the extension include it as a dependency in your application pom:

[source,xml]
----
<dependencies>
    <!-- STM extension -->
    <dependency>
      <groupId>io.quarkus</groupId>
      <artifactId>quarkus-narayana-stm</artifactId>
      <version>${quarkus.version}</version>
    </dependency>
</dependencies>
----

== Defining STM-aware classes

In order for the STM subsytem to have knowledge about which classes are to be managed within the context
of transactional memory it is necessary to provide a minimal level of instrumentation. This occurs by
categorising STM-aware and STM-unaware classes through an interface boundary; specifically all STM-aware objects
must be instances of classes which inherit from interfaces that themselves have been annotated to identify them
as STM-aware. Any other objects (and their classes) which do not follow this rule will not be managed by the
STM subsystem and hence any of their state changes will not be rolled back, for example.

The specific annotation that STM-aware application interfaces must use is `org.jboss.stm.annotations.Transactional`.
For example:

[source,java]
----
@Transactional
public interface FlightService {
    int getNumberOfBookings();
    void makeBooking(String details);
}
----

Classes which implement this interface are able to use additional annotations from Narayana to tell the STM
subsystem about things such as whether a method will modify the state of the object, or what state variables
within the class should be managed transactionally, e.g., some instance variables may not need to be rolled back
if a transaction aborts. As mentioned earlier, if those annotations are not present then defaults are chosen to<commit_msg>docs: fix typo in stm doc<commit_after>////
This guide is maintained in the main Quarkus repository
and pull requests should be submitted there:
https://github.com/quarkusio/quarkus/tree/master/docs/src/main/asciidoc
////
= Using Software Transactional Memory in Quarkus

include::./attributes.adoc[]
:extension-status: preview

Software Transactional Memory (STM) has been around in research environments since the late
1990's and has relatively recently started to appear in products and various programming
languages. We won't go into all of the details behind STM but the interested reader could look at https://groups.csail.mit.edu/tds/papers/Shavit/ShavitTouitou-podc95.pdf[this paper].
However, suffice it to say that STM offers an approach to developing transactional applications in a highly
concurrent environment with some of the same characteristics of ACID transactions, which you've probably already used
through JTA. Importantly though, the Durability property is relaxed (removed) within STM implementations,
or at least made optional. This is not the situation with JTA, where state changes are made durable
to a relational database which supports https://pubs.opengroup.org/onlinepubs/009680699/toc.pdf[the X/Open XA
standard].

Note, the STM implementation provided by Quarkus is based on the https://narayana.io/docs/project/index.html#d0e16066[Narayana STM] implementation. This document isn't meant to be a replacement for that project's documentation so you may want
to look at that for more detail. However, we will try to focus more on how you can combine some of the key capabilities
into Quarkus when developing Kubernetes native applications and microservices.

== Why use STM with Quarkus?

Now you may still be asking yourself "Why STM instead of JTA?" or "What are the benefits
to STM that I don't get from JTA?" Let's try to answer those or similar questions, with
a particular focus on why we think they're great for Quarkus, microservices and Kubernetes
native applications. So in no specific order ...

* The goal of STM is to simplify object reads and writes from multiple threads/protect
state from concurrent updates. The Quarkus STM implementation will safely manage any conflicts between
these threads using whatever isolation model has been chosen to protect that specific state
instance (object in the case of Quarkus). In Quarkus STM, there are two isolation implementations,
pessimistic (the default), which would cause conflicting threads to be blocked until the original
has completed its updates (committed or aborted the transaction); then there's the optimistic
approach which allows all of the threads to proceed and checks for conflicts at commit time, where
one or more of the threads may be forced to abort if there have been conflicting updates.

* STM objects have state but it doesn't need to be persistent (durable). In fact the
default behaviour is for objects managed within transactional memory to be volatile, such that
if the service or microservice within which they are being used crashes or is spawned elsewhere, e.g.,
by a scheduler, all state in memory is lost and the objects start from scratch. But surely you get this and more
with JTA (and a suitable transactional datastore) and don't need to worry about restarting your application?
Not quite. There's a trade-off here: we're doing away
with persistent state and the overhead of reading from and then writing (and sync-ing) to the datastore during each
transaction. This makes updates to (volatile) state very fast but you still get the benefits of atomic updates
across multiple STM objects (e.g., objects your team wrote then calling objects you inherited from another team and requiring
them to make all-or-nothing updates), as well as consistency
and isolation in the presence of concurrent threads/users (common in distributed microservices architectures).
Furthermore, not all stateful applications need to be durable - even when JTA transactions are used, it tends to be the
exception and not the rule. And as you'll see later, because applications can optionally start and control transactions, it's possible to build microservices which can undo state changes and try alternative paths.

* Another benefit of STM is composability and modularity. You can write concurrent Quarkus objects/services that
can be easily composed with any other services built using STM, without exposing the details of how the objects/services
are implemented. As we discussed earlier, this ability to compose objects you wrote with those other teams may have
written weeks, months or years earlier, and have A, C and I properties can be hugely beneficial. Furthermore, some
STM implementations, including the one Quarkus uses, support nested transactions and these allow changes made within
the context of a nested (sub) transaction to later be rolled back by the parent transaction.

* Although the default for STM object state is volatile, it is possible to configure the STM implementation
such that an object's state is durable. Although it's possible to configure Narayana such that different
backend datastores can be used, including relational databases, the default is the local operating system
file system, which means you don't need to configure anything else with Quarkus such as a database.

* Many STM implementations allow "plain old language objects" to be made STM-aware with little or no changes to
the application code. You can build, test and deploy applications without wanting them to be STM-aware and
then later add those capabilities if they become necessary and without much development overhead at all.

== Building STM applications

There is also a fully worked example in the quickstarts which you may access by cloning the
Git repository: `git clone {quickstarts-clone-url}`, or by downloading an {quickstarts-archive-url}[archive].
Look for the `software-transactional-memory-quickstart` example. This will help to understand how you
can build STM-aware applications with Quarkus. However, before we do so there are a few basic concepts
which we need to cover.

Note, as you will see, STM in Quarkus relies on a number of annotations to define behaviours. The lack
of these annotations causes sensible defaults to be assumed but it is important for the developer to
understand what these may be. Please refer to the https://narayana.io/docs/project/index.html#d0e16066[Narayana STM manual]
and the https://narayana.io//docs/project/index.html#d0e16133[STM annotations guide] for more details on
all of the annotations Narayana STM provides.

include::./status-include.adoc[]

== Setting it up

To use the extension include it as a dependency in your application pom:

[source,xml]
----
<dependencies>
    <!-- STM extension -->
    <dependency>
      <groupId>io.quarkus</groupId>
      <artifactId>quarkus-narayana-stm</artifactId>
      <version>${quarkus.version}</version>
    </dependency>
</dependencies>
----

== Defining STM-aware classes

In order for the STM subsystem to have knowledge about which classes are to be managed within the context
of transactional memory it is necessary to provide a minimal level of instrumentation. This occurs by
categorising STM-aware and STM-unaware classes through an interface boundary; specifically all STM-aware objects
must be instances of classes which inherit from interfaces that themselves have been annotated to identify them
as STM-aware. Any other objects (and their classes) which do not follow this rule will not be managed by the
STM subsystem and hence any of their state changes will not be rolled back, for example.

The specific annotation that STM-aware application interfaces must use is `org.jboss.stm.annotations.Transactional`.
For example:

[source,java]
----
@Transactional
public interface FlightService {
    int getNumberOfBookings();
    void makeBooking(String details);
}
----

Classes which implement this interface are able to use additional annotations from Narayana to tell the STM
subsystem about things such as whether a method will modify the state of the object, or what state variables
within the class should be managed transactionally, e.g., some instance variables may not need to be rolled back
if a transaction aborts. As mentioned earlier, if those annotations are not present then defaults are chosen to
{'fraction_non_alphanumeric': 0.04567552968009123, 'fraction_numerical': 0.003961346857931697, 'mean_word_length': 4.773388773388773, 'pattern_counts': {'":': 0, '<': 25, '<?xml version=': 0, '>': 25, 'https://': 12, 'lorem ipsum': 0, 'www.': 0, 'xml': 2}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 2, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '6717366', 'n_tokens_mistral': 4082, 'n_tokens_neox': 3792, 'n_words': 2374}