I work for GigaSpaces as a Solutions Architect/Engineer. Shravan (sean) has posted 1 posts at DZone. You can read more from them at their website. View Full User Profile

RESTFul Service for GigaSpaces data using SparkJava

03.07.2013
| 4229 views |
  • submit to reddit

I came across SparkJava yesterday. It is a really interesting micro web framework especially for Java, where nothing really is micro and something like this is badly needed. Their website does a good job of explaining how it works and get started. I was up and running in minutes.

I build demos and proof of concepts as part of my job and always in the lookout for efficient and easier way to do things. The RESTful example caught my eye. I decided to extend this and show how you can expose data stored in GigaSpaces easily.

I created a maven web project using maven archetype:generate goal,

mvn  -DgroupId=com.gigaspaces.spark -DartifactId=gs-spark -DarchetypeArtifactId=maven-archetype-webapp

I took the RESTful code mentioned above. As I want to run the RESTful service in GigaSpaces I changed the code to implement SparkApplication interface and define the Routes in the init() method.

I also created the web.xml as suggested here

<!DOCTYPE web-app PUBLIC
 "-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN"
 "http://java.sun.com/dtd/web-app_2_3.dtd" >

<web-app>
	<display-name>Archetype Created Web Application</display-name>

	<filter>
		<filter-name>SparkFilter</filter-name>
		<filter-class>spark.servlet.SparkFilter</filter-class>
		<init-param>
			<param-name>applicationClass</param-name>
			<param-value>com.gigaspaces.spark.BooksService</param-value>
		</init-param>
	</filter>

	<filter-mapping>
		<filter-name>SparkFilter</filter-name>
		<url-pattern>/*</url-pattern>
	</filter-mapping>
</web-app>

I modified the CRUD operations to go against a GigaSpace instead of a Map. Complete  BooksService code is here,

package com.gigaspaces.spark;

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

import java.util.Random;

import org.openspaces.core.GigaSpace;
import org.openspaces.core.GigaSpaceConfigurer;
import org.openspaces.core.space.UrlSpaceConfigurer;

import spark.Request;
import spark.Response;
import spark.Route;
import spark.servlet.SparkApplication;

public class BooksService implements SparkApplication {

	/**
	 * Map holding the books
	 */

	private GigaSpace gigaSpace;

	public void init() {

		if (gigaSpace == null) {
			gigaSpace = new GigaSpaceConfigurer(new UrlSpaceConfigurer(
					"/./bookSpace").space()).gigaSpace();
		}

		// Creates a new book resource, will return the ID to the created
		// resource
		// author and title are sent as query parameters e.g.
		// /books?author=Foo&title=Bar
		post(new Route("/books") {
			Random random = new Random();

			@Override
			public Object handle(Request request, Response response) {
				String author = request.queryParams("author");
				String title = request.queryParams("title");
				Book book = new Book(author, title);

				int id = random.nextInt(Integer.MAX_VALUE);
				book.setId(id + "");

				gigaSpace.write(book);

				response.status(201); // 201 Created
				return id;

			}
		});

		// Gets the book resource for the provided id
		get(new Route("/books/:id") {
			@Override
			public Object handle(Request request, Response response) {
				Book template = new Book();

				template.setId(request.params(":id"));

				Book book = gigaSpace.read(template);
				if (book != null) {
					return "Title: " + book.getTitle() + ", Author: "
							+ book.getAuthor();
				} else {
					response.status(404); // 404 Not found
					return "Book not found";
				}
			}
		});

		// Updates the book resource for the provided id with new information
		// author and title are sent as query parameters e.g.
		// /books/<id>?author=Foo&title=Bar
		put(new Route("/books/:id") {
			@Override
			public Object handle(Request request, Response response) {
				String id = request.params(":id");

				Book template = new Book();

				template.setId(id);

				Book book = gigaSpace.read(template);

				if (book != null) {
					String newAuthor = request.queryParams("author");
					String newTitle = request.queryParams("title");
					if (newAuthor != null) {
						book.setAuthor(newAuthor);
					}
					if (newTitle != null) {
						book.setTitle(newTitle);
					}

					gigaSpace.write(book);
					return "Book with id '" + id + "' updated";
				} else {
					response.status(404); // 404 Not found
					return "Book not found";
				}
			}
		});

		// Deletes the book resource for the provided id
		delete(new Route("/books/:id") {
			@Override
			public Object handle(Request request, Response response) {
				String id = request.params(":id");
				
				Book template = new Book();

				template.setId(id);

				Book book = gigaSpace.take(template);
				
				if (book != null) {
					return "Book with id '" + id + "' deleted";
				} else {
					response.status(404); // 404 Not found
					return "Book not found";
				}
			}
		});

		// Gets all available book resources (id's)
		get(new Route("/books") {
			@Override
			public Object handle(Request request, Response response) {
				String ids = "";

				Book[] books = gigaSpace.readMultiple(new Book());
				
				for (Book book:books)
					ids = book.getId() + " " + ids;

				return ids;
			}
		});

	}
}

For keeping it simple, I am creating GigaSpace inside the RESTful service/web container but in real applications you will be connecting to an external GigaSpace cluster which can be changed by updating the GigaSpace URL. For embedded space use "/./bookSpace" and for remote space use "jini://*/*/bookSpace" URL.

Source code is in the github repo here. README file has instructions on how to run this on your side.

As you can see, SparkJava seems to be a promising framework. Very simple configuration and code needed for building web apps.

Hope this helps others looking for building simple web apps in Java.

Published at DZone with permission of its author, Shravan (sean) Pabba.

(Note: Opinions expressed in this article and its replies are the opinions of their respective authors and not those of DZone, Inc.)