Writing an API Service in core Java-1

Part 1 of my 4 part series on developing a light-weight RESTful API service in pure Java without any frameworks. 

What is a REST API?

A RESTful or REST API is a type of Application Programming Interface that allows 2 computers to share data securely over the internet. It can be also be used to drive the backend of your website serving as a middle layer between your database and the internet/Mobile App. We use standard HTTP requests to access and use the data. RESTful APIs offer faster performance being lightweight, are more scalable as needs grow. Developing your API is the first step to developing a modern Mobile/Internet app.

There are many ways to skin a cat! You can write code in Java, Python, PHP or even C language. To further complicate things, There are frameworks like Django that make writing API "easier" and "faster". I am personally not a fan of using frameworks and prefer to use lightweight coding practices abjuring the use of these heavy framework layers. An API service developed in core Java offers the fastest performance and the lightest final deployment package of all the options out there - I did a thorough evaluation of this 2 years back!
 
So today in the first part, I will show you how to create a basic Java app to listen to basic requests over the internet and return stock text back to the Browser. Over the next 3 parts, we will add various functionality to our API Service and learn how to parse URLs, connect to the database and format & return data in standard JSON format.

Getting started.

 In a IDE of your choice, create a file called ApiService.java. In this file create a public class called ApiService which will contain our main() function which is the entry point to our server application. Note: When working with Java, it is critical that each file name exactly matches the name of the class contained within. This is important! Then, copy paste the following code into this file.

import java.io.IOException;             
import java.io.OutputStream;            
import java.net.InetSocketAddress;      
//import java.util.HashMap;
//import java.util.Map;

import com.sun.net.httpserver.HttpExchange;
import com.sun.net.httpserver.HttpHandler;
import com.sun.net.httpserver.HttpServer;

public class ApiService 
{
    final static int PORT=8080;

    public static void main(String[] args) throws IOException {
        HttpServer server = HttpServer.create(new InetSocketAddress(PORT), 0);

        server.createContext("/", new RootHandler());           // Root URL Handler
        server.createContext("/modani", new ModaniHandler());    // Handler for 2nd URL 

        server.setExecutor(null); // creates a default executor
        server.start();
        System.out.println("Hello World!\n\r@KaleshiBua's API Service is Running and Accepting Requests from y'all!");
    }

    static class RootHandler implements HttpHandler {
        @Override
        public void handle(HttpExchange xchg) throws IOException {
            String response = "@KaleshiBua's API Service v0.01";
            
            xchg.sendResponseHeaders(200, response.length());      //Send Response
            
            //OPTIONAL - Print Status on Server Console
            System.out.println("Sent Root Response");

            OutputStream os = xchg.getResponseBody();
            os.write(response.getBytes());
            os.close();

        }
    }
    
    static class ModaniHandler implements HttpHandler {
        @Override
        public void handle(HttpExchange xchg) throws IOException {
            String response = "Arrest Modi-Adani NOW!";
            xchg.sendResponseHeaders(200, response.length());
            
            //OPTIONAL - Print Status on Server Console
            System.out.println("Sent Modani Response");

            OutputStream os = xchg.getResponseBody();
            os.write(response.getBytes());
            os.close();
        }
    }

}

Lets go over this code now. The main() function is the entry point for our Server application. First thing we need to do is to setup a "listener" that will listen to requests made over the internet and respond appropriately. We will make use of the HttpServer class for this purpose.
 
        HttpServer server = HttpServer.create(new InetSocketAddress(PORT), 0);

This creates a new instance of the HttpServer object and prepares it for listening to requests on the port specified by the PORT constant. By default, internet requests are served over Port 80. PORT can be set to any numerical value. We are using Port 8080 for our purpose here.
 
 This next line creates a "Server Context" using which we can map any URL path to specific functions to handler that request. We start with a Handler for the root. This function will be called when someone requests "http://www.[your server].com/" .

server.createContext("/", new RootHandler());          

We can setup as many handlers as we need. For eg we may have urls like "http://server/customers/", or "http://server/books/" and so on. Here we are setting up a 2nd handler to handle requests made to "http://server/modani/"
 
server.createContext("/modani", new ModaniHandler());

Next we have to set our server object to handle connection pools. By default, HttpServer uses a single thread to handle all requests. This will obviously be a bottleneck on a live server where you will have many concurrent requests simultaneously. The setExecutor() method allows us to set this up to our requirement. For our current requirement, we will set it up to use single thread and then call server.start() to begin listening to requests on our PORT. We will also print a nice text on the Server console! :)

server.setExecutor(null); 
server.start();
server.start();
        System.out.println("Hello World!\n\r@KaleshiBua's API Service is Running and Accepting Requests from y'all!");

Thats it! Thats our basic code to setup and run the server. Next we write the Handlers that will actually handle the requests. We are writing 2 almost identical functions to handle 2 request paths with only a minor change in the Text returned.
 
static class ModaniHandler implements HttpHandler {
        @Override
        public void handle(HttpExchange xchg) throws IOException {
            String response = "Arrest Modi-Adani NOW!";
            xchg.sendResponseHeaders(200, response.length());
            
            //OPTIONAL - Print Status on Server Console
            System.out.println("Sent Modani Response");

            OutputStream os = xchg.getResponseBody();
            os.write(response.getBytes());
            os.close();
        }
    } 
Each Handler Class has to implement HttpHandler and contains a handle() function. The handle() function receives an object of class HttpExchange as parameter. The HttpExchange class is a "package" containing both the Request and Response packets each time it is called. The Request packet serves as our Input and the the Response packet serves as our Output stream within the handler. We can thus use this Exchange object to get details of the Request and write out our Response.

Every Response must have a Header which tells the receiver (Browser/Mobile App) what the response contains among other things. Right now we will just send a basic Header specifying the Length of the Text we are sending back and a status code of "200" which means "OK". For a detailed list of HTTP status codes check the following link.

We then print some text to the Server console. This is an optional step. In our real life Server applications we rarely output Text like this to the Server console since those apps are running in the background. So this is for demonstration purposes only.

We then actually write the text we want to send back using the write() method of the ResponseBody stream and close the stream when we are done. That's it! Our Handler is done! We are ready to run!

On your console, type the following line to Compile the code.
javac ApiService.java

This will compile your source code into a "machine language" .class file. This can be executed using the following command.
java ApiService

That's it! Our Service is now running on the server and listening to requests!

Now to test our little Service, open up a Browser and type out our root URL http://server/. This will execute the RootHandler() on our Service.


Then type in our second url "http://server/modani/" in your Browser and check the response in the Browser window (left) and the Server Console (right).


Thats it folks! We have just made a simple Api Service in pure Java to listen to requests and respond with standard Text responses.

Tomorrow we will see how to handle the Server Load and Exit in a more classier way, and also learn how to format and return data in standard JSON format - which is our ultimate objective.

Hope you liked this first Lesson on writing your own API service in Java. Consider supporting my product work with a contribution using the link below.

Comments