Guide Area

Java Web Service (API) Tutorial with Source Code

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.

If you’d like to see how PHP service can be created using PHP, visit my tutorial Create a simple rest web service in PHP – Part I

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:

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!

I’m writing this tutorial for Linux users only. If you’re using Microsoft or MacOS, you can still follow this tutorial but you will have to do a bit of Googling around to find commands specific for your platform.

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

Javalin Documentation
Javalin Documentation

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.

Vladimir Marton

DevOps Engineer focused on cloud infrastructure, automation, CI/CD and programming in Javascript, Python, PHP and SQL. Guidearea is my oldest project where I write articles about programming, marketing, SEO and others.