Recently, I published an article related to MRS (MySQL REST Service), which we released as a lab.
I wanted to explore how I could use this new cool feature within an application.
I decided to create an application from scratch using Helidon.
The application uses the Sakila
sample database.
Why Helidon?
I decided to use Helidon because it’s a cool, open-source framework developed by Oracle, and I already had the chance to get an overview of it while co-presenting MySQL Document Store (X Protocol) at the Java User Group in Prague [1], [2], [3].
They recently released a new version that includes GenAI (Langchain) capabilities.
This is a quick demo of the application:
(1) Helidon
We use Helidon 4.3.0M2 to utilize OCI’s GenAI Service.
This is defined in our pom.xml file:
<parent>
<groupId>io.helidon.applications</groupId>
<artifactId>helidon-se</artifactId>
<version>4.3.0-M2</version>
<relativePath/>
</parent>
While creating this demo, I discovered some issues, and they were immediately considered and quickly fixed by the Helidon team:
- https://github.com/helidon-io/helidon/issues/10601
- https://github.com/helidon-io/helidon/pull/10609
- https://github.com/langchain4j/langchain4j-community/issues/356
(2) Authentication
MRS manages authentication, as we saw in the previous article; this is useful for a phone app, for example.
However, in our case, our Java application will connect to MySQL using the REST Service and will then utilize a dedicated user for the entire application.
But, as you can see in the video above, users will also need to authenticate with our application.
In this scenario, it could also be used if you already have an existing application with a large number of users and want to migrate it to MRS. Users are stored as in the good old days in a dedicated table in the application’s database. Of course, the passwords are not stored in clear text; they are hashed.
So we have two types of authentication:
- the application that authenticates to MRS
- the users who authenticate to our application
MRS Authentication
For MRS authentication, we only address the MySQL App, as the SCRAM method used by the MRS App will complicate this blog post.
We created our application to accept those parameters from the command line or the application.yaml configuration file
When we start our application, we can then pass the following parameters if we want to override the configuration:
-Dmrs.url=<url of our MRS Service>
-Dmrs.auth.app=MySQL
-Dmrs.auth.username=<username>
-Dmrs.auth.password=<password>
-Dmrs.auth.sessionType=bearer
Users Authentication
As already mentioned, users who connect to our application will authenticate using information stored in the application’s database.
Our application already has such a table that was previously added to the original Sakila sample database: sakila.user
MySQL> desc users;
+---------------+--------------+------+-----+-------------------+-----------------------------------------------+
| Field | Type | Null | Key | Default | Extra |
+---------------+--------------+------+-----+-------------------+-----------------------------------------------+
| user_id | int unsigned | NO | PRI | NULL | auto_increment |
| firstname | varchar(30) | YES | | NULL | |
| lastname | varchar(30) | YES | | NULL | |
| username | varchar(30) | YES | | NULL | |
| email | varchar(50) | YES | | NULL | |
| password_hash | varchar(60) | YES | | NULL | |
| updated_at | timestamp | NO | | CURRENT_TIMESTAMP | DEFAULT_GENERATED on update CURRENT_TIMESTAMP |
+---------------+--------------+------+-----+-------------------+-----------------------------------------------+
7 rows in set (0.0292 sec)
The password is stored as a bcrypt hash:
MySQL> select username, password_hash from users\G
*************************** 1. row ***************************
username: fred
password_hash: $2a$12$EW.Dli9DEMig0Nby/zjhSeJVdi4DVsL12Rj/qgz.em69rUyGxXyz.
1 row in set (0.0006 sec)
Our Helidon project can generate the hash for us using a dedicated route (/_debug/hash
) that is defined in our Auth.java class:
// helper to generate a bcrypt hash (to seed the table)
r.get("/_debug/hash", (req, res) -> {
String pwd = req.query().first("pwd").orElse("");
if (pwd.isBlank()) { res.status(400).send("Usage: /_debug/hash?pwd=yourPassword"); return; }
String h = BCrypt.hashpw(pwd, BCrypt.gensalt(12));
res.send(h);
});
This is how to use it:
$ curl -s 'http://127.0.0.1:8080/_debug/hash?pwd=fred'
$2a$12$AveeHEcz6/JmUBTfdCUC3uv3pma4BjTE2WiTUPJkcUzOXgK72HHNS
(3) Server-Sent-Events (SSE)
I needed a reliable and straightforward way to illustrate how to push real-time changes in the database to the browser without the complexity of WebSockets or the inefficiency of polling. SSE that is integrated in Helidon gave me precisely that.
This was relatively easy to code, requiring minimal JavaScript functions, and the result is as expected, as shown in the video.
(4) OCI GenAI
I also wanted to illustrate one of the new excellent functionalities of Helidon by integrating OCI GenAI in my demo.
Helidon, in its new version, supports LangChain4j, a Java framework for building AI-powered applications using LLMs.
I used the OCI GenAI service to ask an LLM to perform a task (summarizing an actor’s career).
The OCI information and LLM are configured in application.yaml and use the usual oci-cli config file:
langchain4j:
oci-gen-ai:
chat-model:
enabled: true
region: "eu-frankfurt-1"
compartment-id: "ocid1.compartment.oc1.XXXXXXXXX"
#model-name: "xai.grok-3"
model-name: "meta.llama-3.3-70b-instruct"
Model availability depends on the region.
You can also use the OCI GenAI free service. Let me show you how you can use it:


You can see all models available in your region, and as said before, all regions may have different models:

Then you click on View code button, and you can cut the value of COMPARTMENT_ID:

Ensure that you use the matching region, model, and compartment_id in application.yaml.
Of course, the answer will also depend on the model used. In the video, it was meta.llama-3.3-70b-instruct, and in the screenshot below, it’s xai.grok-3:

The prompt used is defined in the AiRoutes.java class and includes the full JSON information related to an actor:
String actorJson = mrs.get("/sakila/actor/" + id, null);
String prompt =
"Explain this actor record in a HTML snippet. " +
"Highlight first/last name and lastUpdate. Provide a summary of the actor's filmography " +
"with dates and languages. Please highlight the best and the worse movie explaining why with details, " +
"including rating and rentalRate." +
"Could you also add a chart of the categories of the movies this actor played in?" +
" Output ONLY HTML (no <html> wrapper).\n\n"
+ actorJson;
(5) MRS – MySQL without SQL
If you haven’t heard about MRS (MySQL REST Service), please check this article to see how to create the service and authentication apps.
The source code of this demo application also contains the statements to create all REST required resources (mySercvice.all.mrs.sql).
A bug related to @unnest
was also reported and fixed by the MySQL Team.
The class MrsClient.java contains various methods for utilizing the MySQL REST API, including get(), postJson(), patchJson(), putJson(), and delete().
There is zero SQL statement in the entire application!
Conclusion
Building this demo application with Helidon and MySQL REST Service was a great way to explore how modern frameworks and services can simplify development while enabling powerful features.
Along the way, I was able to integrate multiple technologies—authentication with MRS, secure user management with bcrypt, real-time updates using SSE, and even OCI GenAI with LangChain4j—all within a clean and lightweight Java stack.
What I found particularly valuable was not just Helidon’s flexibility, but also the development teams’ responsiveness in addressing issues quickly.
This project also shows that it’s possible to build a fully functional app—without writing a single SQL statement—thanks to MySQL REST Service. Combined with Helidon’s evolving ecosystem, this opens the door for many creative use cases that include AI-powered tasks.
The sources are available on my GitHub repository, but please be indulgent, I’m not a Java developer 😉
I’ve sent an enhancement request to the Helidon project to support the MRS Auth App (SCRAM): https://github.com/helidon-io/helidon/issues/10628