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. You can view the live application running on OpenShift here. The application can 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.
Download and install JDK 8
Download and install Eclipse or any other IDE. Eclipse users make sure you have Eclipse with Java 8 support.
Download and install Apache Maven
Download and install MongoDB
Github Repository
The code for today's demo application is available on github: todoapp-spark.
Step 1: Create a Maven project
Open a new command-line terminal and navigate to the location where you want to create the project. Execute the command shown below to generate the template application.
Step 2: Update the maven project to use Java 8
Import the project into your IDE and replace the pom.xml with the one shown below.
In the pom.xml shown above, we changed the following:
You updated Maven to use Java 8 by defining maven.compiler.source and maven.compiler.target properties.
You removed the JUnit dependency from the original pom.xml file.
Delete App.java and AppTest.java files as we don't need them.
Step 3: Add Spark and other dependencies
The application uses the Spark framework and a MongoDB database. So, update the dependencies section of pom.xml with the one shown below.
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.
Step 4: Make Spark Say Hello World
Create a new class called Bootstrap and add the following code to it.
This code:
Imports the required classes from the Spark library.
Creates a new class called Bootstrap and defines a main method.
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.
Step 5: Defining the Domain Model and Service class
Our goal is an application that stores and manages ToDo items. Our simple ToDo class is shown below.
Our TodoService class implement methods that use CRUD operations on the Todo object. It basically Creates, Reads, and Updates Todo documents stored in MongoDB.
This code does the following:
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.
The code shown above exposes the TodoService CRUD methods as REST API's.
JsonTransformer in the code shown above is an implementation of Spark's ResponseTransformer interface. It allows you to convert response objects to other formats like JSON.
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.
In the html shown above:
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.
The code shown above does the following:
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.
To create an executable jar, run the mvn clean install command. This creates a todoapp-1.0-SNAPSHOT.jar in the target directory.
To run the application:
This would print following lines in the terminal.
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.
After this commands successfully finishes, you will see the todo app running at http://todoapp-{domain-name}.rhcloud.com. Please replace {domain-name} with your OpenShift account domain name.
Next Steps
Sign up for OpenShift Online and try this out yourself
Promote and show off your awesome app in the OpenShift Application Gallery today.
Automatic Updates
Stay informed and learn more about OpenShift by receiving email updates.
Get blog updates by email