days
0
6
hours
0
7
minutes
3
4
seconds
5
7
search

How to create CRUD REST APIs with Spark Framework

Yong Mook Kim

© Shutterstock / Shahril KHMD

In this article, Yong Mook Kim, founder at Mkyong.com shows you how to create CRUD REST APIs with Spark Java Framework and Jackson library.

Spark Java runs on an embedded Jetty web server, provide simple APIs to handle HTTP request and response, combine with the Jackson library to serve the JSON output.

I believe this is the simplest, fastest and easiest micro framework to create a REST APIs server.

Tools and technologies used :

  1. Spark Java 2.6.0
  2. Jackson 2.8.8
  3. Java 8
  4. Maven 3
  5. cURL (test the REST APIs)

We are going to create the following RESR APIs

POST /user/add - POST request to add an user.
GET /user/:id - GET request to get user by :id.
GET /user - GET request to get all the users.
PUT /user/:id - UPDATE request to update an user by :id.
DELETE /user/:id - DELETE request to delete an user by :id.

1. Project directory

Review the existing project directory layout, nothing special, just a standard Maven directory layout.

2. Project Dependencies

In pom.xml, declare sparkjavajackson and logback (optional, for logging)

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <groupId>com.mkyong</groupId>
    <artifactId>sparkjava</artifactId>
    <version>1.0-SNAPSHOT</version>

	<!-- Spark Java need Java 8 -->
    <properties>
        <maven.compiler.target>1.8</maven.compiler.target>
        <maven.compiler.source>1.8</maven.compiler.source>
    </properties>

    <dependencies>

        <dependency>
            <groupId>com.sparkjava</groupId>
            <artifactId>spark-core</artifactId>
            <version>2.6.0</version>
        </dependency>

        <dependency>
            <groupId>com.fasterxml.jackson.core</groupId>
            <artifactId>jackson-databind</artifactId>
            <version>2.8.8.1</version>
        </dependency>

        <dependency>
            <groupId>ch.qos.logback</groupId>
            <artifactId>logback-classic</artifactId>
            <version>1.2.2</version>
        </dependency>

    </dependencies>

</project>

3. User & UserService

3.1 A simple POJO.

package com.mkyong.user;

public class User {

    int id;
    String name;
    String email;

    public User(int id, String name, String email) {
        this.id = id;
        this.name = name;
        this.email = email;
    }

    //getters, setters and toString()
}

3.2 No database involves, just store all users’ objects into a local variable.

package com.mkyong.user;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.atomic.AtomicInteger;

public class UserService {

    public static Map users = new HashMap<>();
    private static final AtomicInteger count = new AtomicInteger(0);

    public User findById(String id) {
        return users.get(id);
    }

    public User add(String name, String email) {
        int currentId = count.incrementAndGet();
        User user = new User(currentId, name, email);
        users.put(String.valueOf(currentId), user);
        return user;
    }

    public User update(String id, String name, String email) {

        User user = users.get(id);
        if (name != null) {
            user.setName(name);
        }

        if (email != null) {
            user.setEmail(email);
        }
        users.put(id, user);

        return user;

    }


    public void delete(String id) {
        users.remove(id);
    }

    public List findAll() {
        return new ArrayList<>(users.values());
    }

    public UserService() {
    }
}

4. Spark Java + Jackson

Time to code. Review the comments for self-explanatory.

package com.mkyong;

import com.fasterxml.jackson.databind.ObjectMapper;
import com.mkyong.user.User;
import com.mkyong.user.UserService;

import java.util.List;

import static spark.Spark.get;
import static spark.Spark.port;
import static spark.Spark.post;
import static spark.Spark.put;
import static spark.Spark.delete;

public class Main {

    private static UserService userService = new UserService();
    private static ObjectMapper om = new ObjectMapper();

    public static void main(String[] args) {

        // Start embedded server at this port
        port(8080);

        // Main Page, welcome
        get("/", (request, response) -> "Welcome");

        // POST - Add an user
        post("/user/add", (request, response) -> {

            String name = request.queryParams("name");
            String email = request.queryParams("email");
            User user = userService.add(name, email);
            response.status(201); // 201 Created
            return om.writeValueAsString(user);

        });

        // GET - Give me user with this id
        get("/user/:id", (request, response) -> {
            User user = userService.findById(request.params(":id"));
            if (user != null) {
                return om.writeValueAsString(user);
            } else {
                response.status(404); // 404 Not found
                return om.writeValueAsString("user not found");
            }
        });

        // Get - Give me all users
        get("/user", (request, response) -> {
            List result = userService.findAll();
            if (result.isEmpty()) {
                return om.writeValueAsString("user not found");
            } else {
                return om.writeValueAsString(userService.findAll());
            }
        });

        // PUT - Update user
        put("/user/:id", (request, response) -> {
            String id = request.params(":id");
            User user = userService.findById(id);
            if (user != null) {
                String name = request.queryParams("name");
                String email = request.queryParams("email");
                userService.update(id, name, email);
                return om.writeValueAsString("user with id " + id + " is updated!");
            } else {
                response.status(404);
                return om.writeValueAsString("user not found");
            }
        });

        // DELETE - delete user
        delete("/user/:id", (request, response) -> {
            String id = request.params(":id");
            User user = userService.findById(id);
            if (user != null) {
                userService.delete(id);
                return om.writeValueAsString("user with id " + id + " is deleted!");
            } else {
                response.status(404);
                return om.writeValueAsString("user not found");
            }
        });

    }

}

Done, let’s test it.

5. Test with cURL

Start Main.java and the embedded Jetty server will start as well. Those REST APIs are ready to test. Open a terminal and test the REST APIs with cURL.

//Start Main.java...

2017-05-26 16:18:49 DEBUG spark.route.Routes - Adds route: get, /, spark.RouteImpl$1@612679d6
2017-05-26 16:18:49 DEBUG spark.route.Routes - Adds route: post, /user/add, spark.RouteImpl$1@6950e31
2017-05-26 16:18:49 DEBUG spark.route.Routes - Adds route: get, /user/:id, spark.RouteImpl$1@42eca56e
2017-05-26 16:18:49 DEBUG spark.route.Routes - Adds route: get, /user, spark.RouteImpl$1@7cbd213e
2017-05-26 16:18:49 DEBUG spark.route.Routes - Adds route: put, /user/:id, spark.RouteImpl$1@3ecd23d9
2017-05-26 16:18:49 DEBUG spark.route.Routes - Adds route: delete, /user/:id, spark.RouteImpl$1@43bd930a
2017-05-26 16:18:49 INFO  s.e.jetty.EmbeddedJettyServer - == Spark has ignited ...
2017-05-26 16:18:49 INFO  s.e.jetty.EmbeddedJettyServer - >> Listening on 0.0.0.0:8080

Let’s test the following REST APIs :

POST	/user/add - POST request to add an user.
GET 	/user/:id - GET request to get user by :id.	
GET 	/user	  - GET request to get all the users.
PUT 	/user/:id - UPDATE request to update an user by :id.
DELETE	/user/:id - DELETE request to delete an user by :id.

5.1 POST /user/add

# Add user 'mkyong'
$ curl -X POST -d "name=mkyong&email=test1@gmail.com" http://localhost:8080/user/add
{"id":1,"name":"mkyong","email":"test1@gmail.com"}

# Add user 'jack'
$ curl -X POST -d "name=jack&email=test2@gmail.com" http://localhost:8080/user/add
{"id":2,"name":"jack","email":"test2@gmail.com"}

5.2 GET /user/:id & GET /user

# Get user where id = 1
$ curl http://localhost:8080/user/1
{
  "id" : 1,
  "name" : "mkyong",
  "email" : "test1@gmail.com"
}

# Get user where id = 2
$ curl http://localhost:8080/user/2
{
  "id" : 2,
  "name" : "jack",
  "email" : "test2@gmail.com"
}

# Get all users
$ curl http://localhost:8080/user
[ {
  "id" : 1,
  "name" : "mkyong",
  "email" : "test1@gmail.com"
}, {
  "id" : 2,
  "name" : "jack",
  "email" : "test2@gmail.com"
} ]

5.3 PUT /user/:id

# Update
$ curl -X PUT -d "name=jack2&email=test2@yahoo.com" http://localhost:8080/user/2
"user with id 2 is updated!"

# Get user where id = 2
$ curl http://localhost:8080/user/2
{
  "id" : 2,
  "name" : "jack2",
  "email" : "test2@yahoo.com"
}

5.4 DELETE /user/:id

# Delete user where id = 2
$ curl -X DELETE http://localhost:8080/user/2
"user with id 2 is deleted!"

# User id = 2 is no longer exists
$ curl http://localhost:8080/user/2
"user not found"

# Get all users
$ curl http://localhost:8080/user
[ {
  "id" : 1,
  "name" : "mkyong",
  "email" : "test1@gmail.com"
} ]

Download source code

References

  1. cURL official Website
  2. Spark Java Documentation
  3. Jackson 2 – Convert Java Object to / from JSON

This post was created by mkyong.com.

asap

Author

Yong Mook Kim

Yong Mook Kim is the founder of Mkyong.com, loves Java and open source stuff.


Comments
comments powered by Disqus