Java web service – step-by-step
In this tutorial I will show you how to create a very simple Java web service using the newest (to this date) Java 11, Javalin microframework, Gradle, MariaDB and JDBC connector.
World of technologies and languages is changing. As you know, Oracle’s Java turned away from the free plan and from version 8 (which is supported only until beginning of 2019) it switched to paid plans. Also, MySQL no longer allows you to run its free version in production. You can still use it in development and staging environments though. Not paying for a license while using MySQL server in production will result in severe fees. That is why I decided to go on a more open-source road and show you how to create a completely FREE web service. We will use:
- OpenJDK 11 (open source Java) – https://openjdk.java.net/projects/jdk/11
- MariaDB 10 (open source DB server) – https://mariadb.org/
- Javalin (free Java microframework) – https://javalin.io/
- Gradle (dependency manager) – https://gradle.org/
- MariaDB JDBC connector – https://mariadb.com/kb/en/library/about-mariadb-connector-j/
I don’t know how many of you have used Gradle before. It’s widely spread in the Android development world, where dependencies are handled by Gradle in every single project. Gradle is a tool which allows you to import any third-party library from the maven repository (such as Javalin) by adding one simple line into gradle build file. You don’t have to import .jar files or anything like that.
Just so you know, there aren’t many differences between MySQL and MariaDB. The two are almost identical, so you do not need any extra knowledge. You can also use any MySQL-based tool to connect to MariaDB. For example, MySQL Workbench will still work even if you try to connect to MariaDB – it will prompt you that there might be compatibility issues, but in my rich 2-year experience I haven’t seen any.
Let’s get started!
1. Installation
OPENJDK11
Openjdk11 is now available through apt-get. Launch your command line and execute:
sudo apt-get install openjdk-11-jdk
If for some reason your linux distribution does not offer this option, follow the tutorial on Stackoverflow: https://stackoverflow.com/questions/49507160/how-to-install-jdk-10-under-ubuntu/49507161#49507161
MARIADB
MariaDB is also available through apt-get.
sudo apt-get install mariadb-server mariadb-client
GRADLE
Download the newest gradle binary file (binary-only) from this URL: https://gradle.org/releases/
Then, execute following commands:
cd ~/Downloads unzip gradle-4.10.2-bin.zip // Change the version to yours sudo mkdir /opt/gradle sudo mv gradle-4.10.2 /opt/gradle/ export PATH=$PATH:/opt/gradle/gradle-4.10.2/bin
Test that gradle works:
gradle -v
2. Create new Java project using gradle
Go to a directory where you want to start a new project and create a directory for this project.
mkdir my-java-project cd my-java-project/
Then, initialize project using gradle:
gradle init --type java-application
Gradle will create the whole project structure for you, which will look somehow like this:
├── build.gradle ├── gradle │ └── wrapper │ ├── gradle-wrapper.jar │ └── gradle-wrapper.properties ├── gradlew ├── gradlew.bat ├── settings.gradle └── src ├── main │ └── java │ └── App.java └── test └── java └── AppTest.java * Structure copied from https://guides.gradle.org/building-java-applications/
3. Add Javalin and MariaDB connector to gradle dependencies
Open file build.gradle in the root of your Java project and add dependencies for these two libraries, among some other libraries that will help you maintain database connection.
dependencies { compile 'com.google.guava:guava:23.0' testCompile 'junit:junit:4.12' testCompile group: 'junit', name: 'junit', version: '4.12' compile 'io.javalin:javalin:2.3.0' compile group: 'org.apache.commons', name: 'commons-dbcp2', version: '2.5.0' compile group: 'org.apache.commons', name: 'commons-pool2', version: '2.6.0' compile group: 'org.mariadb.jdbc', name: 'mariadb-java-client', version: '2.3.0' compile "org.slf4j:slf4j-simple:1.7.25" }
Then, let gradle build the project, so you can run it later on. This will download all dependencies.
./gradlew build
4. Write your first API endpoint
Navigate to src/main/java. Open class App.java and populate it with following content:
import io.javalin.Javalin; public class HelloWorld { public static void main(String[] args) { Javalin app = Javalin.create().start(8090); app.get("/", ctx -> ctx.result("Hello World")); } }
Start the project by running following command from the project root directory:
./gradlew run
… and then open your browser and enter URL http://localhost:7000. The application will greet you by saying Hello World. This is the default Javalin endpoint that applies for any URL path written after host and port. We will remove this and instead create our own endpoint.
Before we do that, you have to have a database created together with at least one table. Create new database called mydb and add table called user. Then, populate it with some values.
CREATE SCHEMA mydb; CREATE TABLE mydb.user (id int, name varchar(256)); INSERT INTO mydb.user VALUES (1, "Anthony"),(2, "Michael");
Now, create a new class called DatabaseConnection.java and insert the following code into it:
import java.sql.Connection; import java.sql.ResultSet; import java.sql.SQLException; import java.sql.Statement; import java.util.ArrayList; import java.util.Arrays; import javax.sql.DataSource; import io.javalin.Context; import org.apache.commons.dbcp2.BasicDataSource; public class DatabaseFactory { private static final String DB_DRIVER = "jdbc:mariadb://localhost:3306/mydb?user=YOURUSER&password=YOURPASSWORD"; private static final String SQLQUERY = "SELECT * FROM user;"; public static void getUsers() { DataSource dataSource = setupDataSource(); Connection conn = null; Statement stmt = null; ResultSet rset = null; try { conn = dataSource.getConnection(); stmt = conn.createStatement(); rset = stmt.executeQuery(SQLQUERY); ArrayList<String> resultstring = new ArrayList<>(); while (rset.next()) { resultstring.add("ID: " + rset.getInt("id") + " | Name: " + rset.getString("name")); } ctx.result(Arrays.toString(resultstring.toArray())); } catch(SQLException e) { e.printStackTrace(); } finally { try { if (rset != null) rset.close(); } catch(Exception e) { } try { if (stmt != null) stmt.close(); } catch(Exception e) { } try { if (conn != null) conn.close(); } catch(Exception e) { } } } private static DataSource setupDataSource() { BasicDataSource ds = new BasicDataSource(); ds.setUrl(DB_DRIVER); return ds; } }
And then, create an endpoint in the main class App.java which will call the getUsers() method each time you call http://localhost:7000/users:
import io.javalin.Javalin; public class App { public static void main(String[] args) { Javalin app = Javalin.create().start(8090); app.get("/", ctx -> ctx.result("Hello World")); app.get("/users", DatabaseFactory::getUsers); } }
Last step is to restart the application so all changes are up. Execute:
./gradlew run
5. Test and enjoy
Now, when you call URL
http://localhost:8090/users
… you should see following response:
[ID: 1 | Name: Anthony, ID: 2 | Name: Michael]
Documentation
Javalin, even though it’s a micro-framework, has well-documented product. Going over to its website will give you a great overview of many, many API endpoints. I suggest that you go over there right now and read about its usage. URL: https://javalin.io/documentation#getting-started

Even if you decide that Javalin isn’t what you’re looking for, you will have hands-on experience with Java micro-frameworks, which is very valuable. Many of the frameworks work on the same basis and you will manage to learn other frameworks easily and faster.