This post will detail a low-level, hands-on approach to deploying a full-featured Java application.
There are several methods for deploying Java applications, each with its own advantages and disadvantages.
These can be broadly categorized into the following three approaches:
To understand the process and details, we start with the low-level approach. While this may not be the most straightforward method in 2025, and you want something simple, I think it helps with a better understanding of the underlying mechanisms when utilizing higher-level tools and services such as CaaS or PaaS. So, let’s learn!
For this deployment exercise, I’m using this URL shortening Java service by Sven Ruppert. He has built a full-featured URL shortening service setup as an “Advent Calendar 2025” piece by piece. It is surprising how many features and moving parts a well-made application actually has.
Particularly, the application is a nice example of a Vaadin administration UI for a separate public-facing service. So, we basically need to deploy and run two applications.
Furthermore, having your own local instance of URL shortening actually makes sense. Afterall, we want to send users across continents to ask for a shorter URL for a local service, right?
The first question is, where do you find a suitable hosting provider? I chose UpCloud.com, which is a European cloud provider specializing in high-performance and reliable infrastructure. Based in Helsinki, Finland, it offers local cloud solutions and a strong performance alternative to larger global providers. For this, UpCloud was a cheap way to get a full server.
Once you create an account at upcloud.com you get a free 7-day trial to play around and check that everything works for free. For testing deployment, we chose the cheapest possible server. We only have two light-weight services running: the URL shortening service and the Vaadin-based management UI. And we don’t need large resources for them.
Note: Do these steps with the dedicated url-app-user account.
Download and extract the Jetty server runtime for running the app:
wget https://repo1.maven.org/maven2/org/eclipse/jetty/jetty-home/12.1.5/jetty-home-12.1.5.tar.gz && tar xfz jetty-home-12.1.5.tar.gz && export JETTY_HOME=~/jetty-home-12.1.5
Create a public base folder:
mkdir ~/jetty-base && cd ~/jetty-base
Configure the server features we need:
java -jar $JETTY_HOME/start.jar --add-modules=http,ee11-deploy,ee11-annotations,graceful
Change the default password in application properties:
nano ~/urlshortener-ui/src/main/resources/auth.properties
Rebuild the management UI:
cd ~/url-shortener/urlshortener-ui && mvn clean package -DskipTestls
Deploy the management UI application to the server:
cp ~/url-shortener/urlshortener-ui/target/ROOT.war ~/jetty-base/webapps/
Start the server: cd ~/jetty-base && java -jar $JETTY_HOME/start.jar jetty.server.stopAtShutdown=true &
You can now access the Management UI in your browser here: http://80-69-172-111.fi-hel1.upcloud.host:8080 but we will change the port later when the front proxy is configured.
Note: You need to be root to be able to configure nginx like this.
Now you can change the Jetty server to be available for localhost only.
Lots of steps there, right? But by now, you have everything up and running, and you are ready to do some URL shortening in real life. The light-weight shortening service itself and the Vaadin-based management UI are both up and running in your own server ready for production.
In this two-service setup, the admin UI detects when the service is
unavailable and switches to in-memory mode if it’s not running.
You might have still noticed a couple of things that you might want to still change for your own setup:
UpCloud also offers a K8s upgrade and a Kubernetes control plane to deploy and manage containerized applications. Should we look into that next? Let me know in the comments.