Get married thanks toJakarta EE and MicroProfile
I recently proposed to my girlfriend. Luckily, she said yes. After a while, we started to plan the wedding, and figured out some dates next year that could be a great fit for celebrating our love. Proximity to public holidays, expected outside temperature and so on into consideration, and we were ready to settle on one of a few possible dates — all of which were Saturdays.
The problem? All other couples also want Saturdays as their wedding day, in spring or summer.
We’re not religious, so we want a civil ceremony. In Oslo, where we live, you can get married on Wednesdays, Fridays or Saturdays, and there are about ten time slots each day. The ceremonies are in the wedding room in the City Hall, in addition to five or six days a year at other places in the city: the opera, the botanical garden and an old cabin in the outskirts.
The City Hall is open for bookings at 00.00 one year in advance. On our first planned date, 8th of May, I was busy at midnight, so I didn’t get to look at the booking until 00.45. The state by then? All gone. People plan early.

However, there may be cancellations, so there might still be hope. If someone cancels their booking, the slot becomes available again. This can happen at any time, and you won’t get notified.
Also, when is it possible to book wedding time at one of the other locations? And which dates are available for next year? Well, who knows.
The day after, I decided to let technology help me get married.
The municipality of Oslo has a web page where you can see available times. The inspection tab of the browser disclosed that it was a GET call to some endpoint, with a date span and a location as query parameters, and a nicely structured JSON as response, listing all the possible time slots, and a flag stating whether it was available for booking or not. I also found that each wedding location was identified by a specific UUID.
Which meant that all I had to do was setting up something that regularly hit that endpoint with our desired dates and locations, and notifying me when something got available.
We figured that the City Hall is a nice location, and the botanical garden was even better. For the botanical garden, only 2026 dates were published, so we emailed the wedding office and asked if they planned to do weddings there in 2027 as well. Of course, I could have figured this out by asking for availability for every single day, but as we had no idea on when this would be published, it pruned the tree of potential opportunities quite a lot just asking. [1]
Quickly, they confirmed that they would do weddings there in 2027, on the 8th of May. Exactly the day we had on top of our wishlist. So I jotted down our search parameters — 8th of May both in the City Hall and the botanical garden, and 15th of May in the City Hall.
How did I solve it?
With that, the problem was fully specified, so now I just needed to create the solution. I went for a familiar tech stack, as I didn’t want any technical quirks on such an important application, nor did I at that moment have much time nor energy for learning a new tech stack. You can solve this with lots of different technologies and providers, of course.
I needed something that could fetch data from a REST endpoint at given times, filter to find the possible times, and if found, notify me. I have good experiences with Quarkus, so I headed to the Quarkus starter, added the necessary dependencies and configurations, and started from there. I chose Kotlin as the programming language, and went to create a simple GET endpoint that could later on be invoked regularly.
With MicroProfile REST client, it is easy to set up a remote REST endpoint declaratively, as an interface. You add the URL in the configuration file, add some annotations, and declare the response object as a plain data class (or in Java, a record). I prefer to use proper data types whenever I can, so it was some tweaking to get it right, as it always is.
Once I had the connection up and running, the filtering logic was pretty straight forward. I chose to consider our dates and locations as secrets, as I couldn’t stand the scenario that someone else found my application and used it to book before we got to it ourselves. Pretty close to paranoia, I admit.
For now, I used a .env file with the dates and locations. With MicroProfile Config, it is easy to fetch environment variables as needed.
Next step, and the final step in the application itself, was to make it able to send email. Quarkus Mail is a nice Quarkus extension that makes it easy to send emails programmatically, so I added the dependency, injected the Mailer object with plain CDI, and added mailer.sendMail(…) that would be invoked if there were available times. Quarkus Mail uses the SMTP protocol to send emails, and they have guides for popular email providers, including Gmail, which I use [2]. This guide worked out of the box, and I now had a complete application that when run on my machine did exactly what I wanted.
To the cloud
Quarkus has built-in support for being run in a container, and provides a reasonable Dockerfile. So you need something that can run a container and something that can regularly invoke an endpoint.
I’m familiar with Google Cloud Platform, so I chose to put my application there, to be run within Cloud Run, their serverless platform.
I put together a workflow for GitHub Actions that would run on every Git push, that would compile the code, build the container, and ship it to Cloud Run. There is a community-run reusable GitHub Action for this , so it was not rocket science.
Luckily, there is also an auth action, as setting up authentication might be cumbersome. I followed their step-by-step guide for Workload Identity Federation through a Service Account, ran the workflow, and fixed whatever issues the workflow crashed on — mainly activating relevant APIs in Google Cloud and giving the service account the required permissions.
Some experiencing later, the workflow went green and reported all good. Invoking the endpoint gave an error — that’s how it tends to be with new applications. The problem was that I had not added the email username and password, as well as the secret with the dates and locations.
The secrets are safely stored in Google Cloud Secret Manager. But how do you make Quarkus read from Secret Manager? I tried different hacks until I found this blog post, which provides a simple and easy solution: You put this in the configuration file (application.properties):
my-top-secret=${sm//projects/<project-id>/secrets/<secret-id>}
Fix, redeploy, and voila.

Run it regularly
Cloud Scheduler is the Google Cloud way of doing cron-like invocations. You tell it when to run, using cron syntax, and point it towards an endpoint.
I did not get the security part of it to work properly with my application, so after spending 20 minutes struggling with that, I gave up, and made my endpoint publicly available. After all, the worst thing that could functionally happen was that someone else invoked it, resulting in duplicate emails. The risk of getting a huge cloud bill is always there, of course, if someone chose to DDOS it or so, but I found that risk to be very low and worth taking. This application was not going to run forever anyway.
Implementation done
Yep, that was all the code and all the necessary steps. I added a date I knew was available — a Wednesday — to get a proper test that everything was working as intended, enabled the scheduler, and sat back to observe my email inbox, waiting for my notification. A minute later, I got the email from my application exactly as I was hoping for.
Now, the only thing remaining was waiting. Waiting for the positive email to drop into our email inboxes.
The code is open source
I open sourced both the source code and the infrastructure configuration from the start, so everything is coded in the open. You can find the repository at https://github.com/madsop/finn-tid-bryllaup. Feel free to use it for your own wedding!
Did we find a date?
Some time after this, my fiancé and I went on vacation with my father and stepmom. When the plane landed, I checked my email, and my inbox was full of Available time for wedding-emails from my system. While we were in the clouds, they had opened the booking for weddings in the botanical garden for 2027. The newest notification came just a minute ago, so it was still available. We immediately went on to booking, and two minutes after touchdown in Split, we had our booking ready. As you can imagine, we got really excited, so the passenger beside us — a stranger — immediately congratulated us and told us about a wedding fixer he knew in Split. My stepmom could hardly sit still. What a way to start a vacation.

So next May, we are getting married. Thank you, Jakarta EE, MicroProfile, Quarkus and Google Cloud, for helping us on the way.

[1]: Yes, this is the good old sometimes you can save a lot of work by asking someone who knows rather than trying to figure it out with code.
[2]: Yes, I’m considering moving to Proton mail
Get married thanks toJakarta EE and MicroProfile was originally published in Compendium on Medium, where people are continuing the conversation by highlighting and responding to this story.


