In this post you will learn how to use a micro framework called Spark to build a RESTful backend. The RESTful backend is consumed by a single page web application using AngularJS and MongoDB for data storage. I’ll also show you how to run Java 8 on OpenShift.

Application Use Case

You will develop a todo application which allows users to create and list todo items. The application will do the following:

When a user goes to the ‘/’ url of the application, they will see a list of all todos stored in the application database. Behind the curtain, AngularJS makes a REST(/api/v1/todos) call to fetch all the todo items.

When a user clicks on the checkbox then a todo is marked done. AngularJS makes a PUT request and update the todo item.

Finally, a user can add a new todo by navigating to http://todoapp-shekharblogs.rhcloud.com/#/create. This makes a POST call to the RESTful backend and saves the todo in the MongoDB datastore.

What is Spark?

Spark is a Java based microframework for building web applications with minimum fuss. It is inspired by a framework written in Ruby called Sinatra. It has a minimalist core providing all the essential features required to build a web application quickly with little code.

Prerequisite

To build the sample application developed in this blog, you would need the following on your machine.

Spark uses SLF4J for logging, so we added slf4j-simple binding in the dependencies. This is required to view the log and error messages. Also, we added the gson library as its used to convert objects to and from JSON.

Defines a route that tells Spark that when an HTTP GET request is made to ‘/’, return “Hello World”. You use Spark’s get() method to define the mapping from the URL to the callback.

To see the application in action, run the main program using your IDE. The application will start the embedded Jetty server at http://0.0.0.0:4567. When you open this link in your web browser, you will see “Hello World!!”.

Take advantage of Java 8 lambda expressions to make your code more concise and clean. Spark is a modern Java web framework that takes advantage of Java 8 features.

The TodoService class constructor receives the MongoDB database object and stores that in the instance variable. You use the db.getCollection() method to fetch the todos collection. All of the operation are done on the todos collection.

The findAll() method fetches all of the todo documents from the MongoDB database. The documents fetched from MongoDB are of the DBObject type. You iterated over the DBCursor object and converted the individual documents to Todo objects and then added them to a List. Finally, you returned the list of todos.

The createNewTodo() method receives a JSON string representing the Todo item. You used GSON to convert the JSON to a Todo object. Finally, you inserted the BasicDBObject into the todos collection.

The find() method finds the Todo item corresponding to a given id.

The update() method updates the Todo document for the given todo Id. It also updates the done field of the document.

Step 6: Creating the Resource class

It is generally not a good idea to add all of the code to one class so we will move the application REST endpoints to another class. This new class is called TodoResource and exposes CRUD operations over Todo objects.

Step 7: Bootstrap the application

Now we will write the entry point for our application. The Bootstrap class shown below configures all of the components. When you run this class as a Java application, it starts the Jetty server and start listening to requests.

Step 8 : Setup AngularJS and Twitter Bootstrap

Create a new directory with name public and place the javascript and css files in it. You can checkout the required directory structure from the Github repository. Download the latest copy of AngularJS and Bootstrap from their respective official websites, or you can copy the resources from this project github repository.

Step 9: Create index.html

Create a new file called index.html inside of the src/main/resources/public directory and place the following content into it.

You imported all of the required libraries. Our application code is in /scripts/app.js. The app.js file will be created in step 10.

In Angular, you defined the scope of the project using the ng-app directive. You used ng-app on the html element but we can use it with any other element as well. Using the ng-app directive with html element means that AngularJS is available on the whole index.html. The ng-app directive can take a name. This name is the module name. I used todoapp as this application module name.

The last interesting thing in the index.html is the use of the ng-view directive. The ng-view directive renders the template corresponding to the current route inside index.html. So that everytime you navigate to a route only the ng-view portion changes.

Step 10: Write the Angular application

The app.js houses all of the application specific JavaScript. All of the application routes are defined inside it. In the code shown below, we have defined two routes and each has a corresponding Angular controller.

First, it configures the Angular module named todoapp and defines all of it’s dependencies.

It defines the routes that this application will respond to.

When a user makes request to ‘/’, the ListCtrl will be invoked. The ListCtrl will make an HTTP GET request to ‘/api/v1/todos’ to fetch all of the todo items. The todo items are put on the scope. The list.html uses the ng-repeat directive to iterate over all of the todo items and generate a table.

When a user clicks on the checkbox next to the item, the todoStatusChanged() function is invoked. This function makes an HTTP PUT request to update the todo item.

When a user makes a GET request to ‘/create’, create.html is rendered. The create.html renders a bootstrap form. The form HTML element uses the ng-submit directive. On form submit the createTodo function is invoked. The createTodo function makes an HTTP POST request to create a new todo item.

You can find the respective views for different routes in the application’s Github repository.

Step 11: Run the application

You can either run the application using your IDE or package this application as an executable jar and then run it from the command-line. Add the following plugin to your project pom.xml to create an executable JAR. This plugin provides the capability to package the artifact in an uber-jar, including its dependencies and to shade – i.e. rename – the packages of some of the dependencies.

Step 12: Deploying on OpenShift

This blog would not be complete if I didn’t show you how to run this application on OpenShift. Today OpenShift does not support JDK 8 but that doesn’t mean you can’t run Java 8 applications. You can use the DIY cartridge and install your own JDK version. The next command creates the todo application you created in the above mentioned steps. It installs JDK 8 on the DIY gear and configures other settings.

Thanks for noting that. We’ve removed reference to the demo so others don’t have the same experience.

Lucas David

I’m stuck at step 4. I run Bootstrap.java and Eclipse outputs something like “server is running at 0.0.0.0:4567″, but when I go to the browser and try to access this IP address it shows me “Firefox can’t establish a connection to the server at 0.0.0.0:4567.” (the regular message when a server is unavailable). Any ideas why that might be happening? I’ve followed your tutorial rigorously.

Lucas David

Oh, never mind. Just realized it’s working perfectly at ‘127.0.0.1:4567’! Thank you!

Shurap1

Hi Shekhar, I really liked this blog. It helped me in understanding how to use angular js with spark java framework. I have one question, when I click on the Done check box, then the TODO item is getting striked out. Looking into the list.hml and app.js, I am unable to understand how this has been achieved. Can you please let me know how this is done?

Shurap1

Sorry submitted too soon…I got it. It is done using the class name dynamically.

class=”success-{{todo.done}}”

Alex Mills

Can you explain how the System.getenv map gets populated with the OpenShift info?

Alex Mills

In order to get this to work, I had to remove one argument from TodoResource — public class TodoResource {