Creating and Deploying Spring Framework Java Applications - Learning OpenShift (2014)

Learning OpenShift (2014)

Chapter 6. Creating and Deploying Spring Framework Java Applications

In this chapter, we are going to learn how to use OpenShift in order to create and deploy Java applications that utilize the popular Spring Framework. To illustrate how to do this, we are going to convert the mlbparks application that we wrote in Chapter 5, Creating and Deploying Java EE Applications, so that it uses the Spring Framework instead of Java EE. First, we are going to cover the history of the framework, and then we will learn how to create Tomcat-based applications on the OpenShift platform. After we have created our application, we will embed the MongoDB NoSQL database and then begin our application coding. We will then learn how to deploy our application from either the source code or binary .war files.

An overview of the Spring Framework

In the beginning, there was EJB, and EJB was bad. Why would I say that? I spent the early part of my career as a Java fan and I believed that Java could do no wrong. I labored for weeks, months, and even years creating EJBs for highly scalable enterprise class applications. Even though I fully understood the specification, I felt that creating these JavaBeans was overly complex and required a lot of arcane interfaces and coding structure that didn't make sense to me. Having worked with a lot of other Java developers at the time, I realized that many of my fellow developers in the industry shared this same opinion. While you could accomplish fantastic results with the early EJB implementations, our friends were coding circles around us in more simple-to-use languages. Of course, the argument we would always make for sticking with EJB and Java normally included loaded terms such as scalable and enterprise grade.

At that time, I was on a team of two Java developers inside of a larger team of developers consisting of PHP and Perl developers. I was so adamant about the merits of Java that my team implemented weekly coding challenges to see how quickly we could solve programming problems in our respective languages. We would be timed on the length of the implementation and then on the execution speed of the code. Given that the size of challenges was broken up into small chucks, we would normally spend 10 minutes or less on the actual implementation to solve the problem. This was a great experience for me, as I developed strong friendships with other developers that continue to exist today even though 15 years have passed. More importantly, I began to see merits in other languages, except Perl, of course!

As I have gained more experience in my career and learned to open my mind to see the value in other languages, I have learned an important lesson: a language is just a tool, and you can accomplish great things regardless of your programming language weapon. To develop great applications, you need to understand how to architect software and put all the moving pieces together in an extensible manner. If you are a hardcore Java enthusiast, I probably just committed the cardinal sin by speaking ill of your language. Don't get me wrong; I love Java today and use it for many projects. However, let's be honest with each other; the early version of web programming in Java was really bad and not a joy to program in.

Where was I? Oh, sorry, we are supposed to be talking about the Spring Framework. As I said previously, the early implementation of EJB left a bad taste in a lot of Java developers' mouths. We wanted something simple and quick that still allowed us to create enterprise-grade applications. We were tired of EJB and wanted to get back to the roots of Java. Enter the Spring Framework!

The Spring Framework was a radical departure from the traditional way of developing software using the Java programming language. The biggest selling point of Spring was its ability to develop applications using only POJO(s). POJO breathed new life into the language and dramatically reduced the complexity of programming. It also introduced an inversion of control and had tight integration with the Hibernate ORM project. Many felt that using Spring alongside Hibernate was a marriage made in heaven and would stand the test of time.

The first 1.0 GA version of Spring was released in March, 2004, and I am happy to report that this framework is still innovative and is still a very popular framework. The framework was originally created by Rod Johnson but has gone through several ownership changes over the years. Recently, VMWare spun the Spring Framework out to its own company, which is called Pivotal.

Spring Framework version

Release date

1.0

March, 2004

2.0

October, 2006

3.0

December, 2009

4.0

December, 2013

The Spring Framework consists of the following core modules:

Module name

Description

IoC

Inversion of the Control container

AOP

Aspect-oriented programming

Data access

Provides API(s) to communicate with data stores

Transactions

Provides API(s) to wrap code inside of transactions with the rollback capability

MVC

The model view controller framework that creates applications

Remote access

API(s) to create objects that can be accessed over the network

Authentication

API(s) for authentication and authorization

Messaging

API(s) for the implementation of message-driven Java code

On top of the core modules, several subprojects exist to provide API(s) that work with social networks, Big Data, and even to help develop mobile applications. For a complete list of Spring components, you can visit the official project site at http://www.spring.io.

Creating a Spring application

Now that we have a good understanding of why Spring was created and the modules available as part of the distribution, let's explore how to create and deploy applications on the OpenShift platform. For the sample application, called springmlb, we are going to convert the application we created in the previous chapter to utilize this framework. Just to recap, the requirements for the application are as follows:

· A single map that a user can zoom in and out

· As the user moves the map around, the map must be updated with all baseball stadiums that are located in the shown area

· The location of the stadiums must be searchable based on map coordinates that are passed to the REST API

· The data should be transferred in the JSON format

· The web application must be responsive so that it is displayed correctly regardless of the resolution of the browser

· When a stadium is listed on the map, the user should be able to click on the stadium to view details about the associated team

The final state application will look like the following screenshot:

Creating a Spring application

Now that we have our requirements and know what the end result will look like, let's start creating the application.

Taking the easy way out

For the remainder of this chapter, we are going to build a Spring-based application using the source code included as part of this chapter. If typing in the source code is not your cup of tea, there are several options available to you.

The first option is to clone the Git repository that is available on GitHub. Head over to the project page at https://github.com/gshipley/springmlb for instructions.

The second option is to chain the RHC command arguments together to create the application, embed the database, and download the source code—all with one command. Keep in mind that after running the RHC command, you will still need to import the JSON documents into thedatabase, as outlined in this chapter. If you want to take this approach, enter the following command:

$ rhc app create springmlb tomcat7 mongodb-2.4 --from-code https://github.com/gshipley/springmlb.git

When the preceding command is finished, all you need to do is import the data. Magic indeed!

Creating a Tomcat gear on OpenShift

You decided to do all of the coding yourself? Awesome; let's get to work.

If you are familiar with Spring, chances are that you are deploying your applications on the popular Tomcat servlet container. While Spring-based applications will certainly work and perform well on the JBoss suite of application servers, I have found that developers typically deploy their Spring applications on top of Tomcat. For this reason, we are going to learn how to create Tomcat-based gears on the OpenShift platform.

The first thing we need to do is create a gear that will hold our application code. In order to do this, enter the following command in your terminal prompt:

$ rhc app create springmlb tomcat

After entering the preceding command, you'll most certainly see the following error message:

Short Name Full name

========== =========

jbossews-1.0 Tomcat 6 (JBoss EWS 1.0)

jbossews-2.0 Tomcat 7 (JBoss EWS 2.0)

There are multiple cartridges that match Tomcat. Please provide the short name of the correct cart.

This is because OpenShift supports multiple versions of the Tomcat servlet container and the platform did not know which version you wanted to use for your deployment. For the application that we are going to create, let's select the Tomcat 7 servlet container for our springmlb application with the following command:

$ rhc app create springmlb tomcat7

Note

If you received an error message stating that you have reached your maximum number of gears, you will need to delete an application that you are no longer using. The free tier for OpenShift Online only allows users to create a limited number of running applications without paying for the service. I would suggest that now might be a good time to review the affordable pricing plans available for the service and consider upgrading to a pay-as-go account.

If the preceding command is executed successfully, your application gear is created and the default template application is cloned to your local filesystem under the springmlb directory.

Note

If you want to use a newer version of Tomcat than what is provided by default, such as an alpha version, we will cover how to do this later in the book when learning about creating Do-It-Yourself (DIY) application gears.

Adding the MongoDB NoSQL database to our application

As we learned in Chapter 2, Creating and Managing Applications, OpenShift provides several add-on cartridges that allow developers to extend the functionality of a gear. The steps required to add a database and import data are exactly the same as what we did in Chapter 5, Creating and Deploying Java EE Applications, where we imported all of the stadium information.

To embed the MongoDB database into our existing springmlb OpenShift gear, run the following command:

$ rhc cartridge add mongodb-2.4 -a springmlb

Once the command is executed and the database has been added to your application, you will see the following information on the screen that contains the username and password for the database:

Adding mongodb-2.4 to application 'springmlb' ... done

mongodb-2.4 (MongoDB 2.4)

-------------------------

Gears: Located with jbossews-2.0

Connection URL: mongodb://$OPENSHIFT_MONGODB_DB_HOST:$OPENSHIFT_MONGODB_DB_PORT/

Database Name: springmlb

Password: JEf8CTqJSG9_

Username: admin

MongoDB 2.4 database added. Please make note of these credentials:

Root User: admin

Root Password: JEf8CTqJSG9_

Database Name: springmlb

Connection URL: mongodb://$OPENSHIFT_MONGODB_DB_HOST:$OPENSHIFT_MONGODB_DB_PORT/

To get started, SSH to your OpenShift gear for the springmlb application by issuing the following command in your terminal prompt:

$ rhc app ssh springmlb

Once you are connected to the remote gear, you need to download the JSON file and store it in the /tmp directory of your gear. To complete these steps, use the following commands on your remote gear:

$ cd /tmp

$ wget https://raw.github.com/gshipley/springmlb/master/mlbparks.json

Once the file has completed downloading, take a quick look at the contents using your favorite text editor in order to get familiar with the structure of the document. When you are comfortable with the data that we are going to import into the database, execute the following command on the remote gear in order to populate MongoDB with the JSON documents:

$ mongoimport --jsonArray -d $OPENSHIFT_APP_NAME -c teams --type json --file /tmp/mlbparks.json -h $OPENSHIFT_MONGODB_DB_HOST --port $OPENSHIFT_MONGODB_DB_PORT -u $OPENSHIFT_MONGODB_DB_USERNAME -p $OPENSHIFT_MONGODB_DB_PASSWORD

If the command was executed successfully, you should see the following output on the screen:

connected to: 127.7.150.130:27017

Fri Feb 28 20:57:24.125 check 9 30

Fri Feb 28 20:57:24.126 imported 30 objects

To verify that the data was loaded properly, use the following command that will print out the number of documents in the teams collections of the springmlb database:

$ mongo -quiet $OPENSHIFT_MONGODB_DB_HOST:$OPENSHIFT_MONGODB_DB_PORT/$OPENSHIFT_APP_NAME -u $OPENSHIFT_MONGODB_DB_USERNAME -p $OPENSHIFT_MONGODB_DB_PASSWORD --eval "db.teams.count()"

The result should be 30.

Lastly, we need to create a 2d index on the teams collection to ensure that we can perform spatial queries on the data.

To add the 2d index to the teams collection, enter the following command on the remote gear:

$ mongo $OPENSHIFT_MONGODB_DB_HOST:$OPENSHIFT_MONGODB_DB_PORT/$OPENSHIFT_APP_NAME --eval 'db.teams.ensureIndex( { coordinates : "2d" } );'

Adding Spring support to the application

As we have learned previously in this book, OpenShift makes use of the Maven build system for Java-based projects. Because of this, we can simply add the dependencies for the Spring Framework to our pom.xml file that is included in the default template. To accomplish this, open up thepom.xml file in the application's root directory with your favorite text editor or IDE. The first thing we want to do is remove the dependencies for PostgreSQL and MySQL by removing the following lines from the <dependencies> section of the file:

<dependency>

<groupId>org.postgresql</groupId>

<artifactId>postgresql</artifactId>

<version>9.2-1003-jdbc4</version>

</dependency>

<dependency>

<groupId>mysql</groupId>

<artifactId>mysql-connector-java</artifactId>

<version>5.1.25</version>

</dependency>

Once we have removed these unneeded dependencies, we can add support for the Spring Framework by adding the following code in the <dependencies> section of the pom.xml file:

<dependency>

<groupId>org.springframework</groupId>

<artifactId>spring-webmvc</artifactId>

<version>4.0.2.RELEASE</version>

</dependency>

<dependency>

<groupId>javax.servlet</groupId>

<artifactId>javax.servlet-api</artifactId>

<version>3.1.0</version>

<scope>provided</scope>

</dependency>

<dependency>

<groupId>com.fasterxml.jackson.core</groupId>

<artifactId>jackson-databind</artifactId>

<version>2.3.1</version>

</dependency>

<dependency>

<groupId>org.springframework.data</groupId>

<artifactId>spring-data-mongodb</artifactId>

<version>1.3.4.RELEASE</version>

</dependency>

We also need to add a configuration item in the file to specify that we do not want the build to fail if we are missing a web.xml file in our project. For this, add the following line of code directly after the <configuration> opening tag under the <build> section of the file:

<failOnMissingWebXml>false</failOnMissingWebXml>

Once you have added the preceding XML code, save your changes to the file.

Adding a configuration to the application

Now that we have our application skeleton created and have added support for the Spring Framework and associated dependencies, the next thing we want to do is set up the connection information for our MongoDB database in our Java source code. In order to do this, create a new directory under your application's root folder, called src/main/java/org/springapp/config. Once this directory has been created, create a new source code file named ApplicationConfig.java and add the following code snippet:

package org.springapp.config;

import org.springframework.context.annotation.Bean;

import org.springframework.context.annotation.Configuration;

import org.springframework.data.authentication.UserCredentials;

import org.springframework.data.mongodb.MongoDbFactory;

import org.springframework.data.mongodb.core.MongoTemplate;

import org.springframework.data.mongodb.core.SimpleMongoDbFactory;

import com.mongodb.Mongo;

@Configuration

public class ApplicationConfig {

@Bean

public MongoTemplate mongoTemplate() throws Exception {

String openshiftMongoDbHost = System.getenv("OPENSHIFT_MONGODB_DB_HOST");

if(openshiftMongoDbHost == null){

return new MongoTemplate(new Mongo(), "springmlb");

}

int openshiftMongoDbPort = Integer.parseInt(System.getenv("OPENSHIFT_MONGODB_DB_PORT"));

String username = System.getenv("OPENSHIFT_MONGODB_DB_USERNAME");

String password = System.getenv("OPENSHIFT_MONGODB_DB_PASSWORD");

Mongo mongo = new Mongo(openshiftMongoDbHost, openshiftMongoDbPort);

UserCredentials userCredentials = new UserCredentials(username, password);

String databaseName = System.getenv("OPENSHIFT_APP_NAME");

MongoDbFactory mongoDbFactory = new SimpleMongoDbFactory(mongo, databaseName, userCredentials);

MongoTemplate mongoTemplate = new MongoTemplate(mongoDbFactory);

return mongoTemplate;

}

}

The preceding code snippet specifies the connection information in order to connect to the MongoDB database that we embedded previously in this chapter.

Note

Note that we are connecting to the database by utilizing the environment variables for the username, password, host, and so on that are created by the OpenShift platform.

Now that we have written our Java code that specifies our database connection information, the next step is to create a WebMvcConfig class that extends the WebMvcConfigurerAdpater class, which ships as part of the Spring Framework. This allows us to create a JSON view for our REST endpoint. Create a new file called WebMvcConfig.java and place it in the src/main/java/org/springapp/config directory. Once you have created the new file, add the following source code:

package org.springapp.config;

import org.springapp.rest.MLBParkResource;

import org.springframework.context.annotation.Bean;

import org.springframework.context.annotation.ComponentScan;

import org.springframework.context.annotation.Configuration;

import org.springframework.web.servlet.config.annotation.EnableWebMvc;

import org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter;

import org.springframework.web.servlet.view.json.MappingJackson2JsonView;

@EnableWebMvc

@ComponentScan(basePackageClasses = MLBParkResource.class)

@Configuration

public class WebMvcConfig extends WebMvcConfigurerAdapter {

@Bean

public MappingJackson2JsonView jsonView() {

MappingJackson2JsonView jsonView = new MappingJackson2JsonView();

jsonView.setPrefixJson(true);

return jsonView;

}

}

The last configuration item that we need to add to our application is the SpringAppWebApplicationInitializer class that implements the WebApplicationInitializer interface, which is a standard interface for the Spring Framework. Create this file under thesrc/main/java/org/springapp/config directory and add the following source code:

package org.springapp.config;

import javax.servlet.ServletContext;

import javax.servlet.ServletException;

import javax.servlet.ServletRegistration.Dynamic;

import org.springframework.web.WebApplicationInitializer;

import org.springframework.web.context.support.AnnotationConfigWebApplicationContext;

import org.springframework.web.servlet.DispatcherServlet;

public class SpringAppWebApplicationInitializer implements WebApplicationInitializer {

@Override

public void onStartup(ServletContext servletContext) throws ServletException {

AnnotationConfigWebApplicationContext webApplicationContext = new AnnotationConfigWebApplicationContext();

webApplicationContext.register(ApplicationConfig.class, WebMvcConfig.class);

Dynamic dynamc = servletContext.addServlet("dispatcherServlet", new DispatcherServlet(webApplicationContext));

dynamc.addMapping("/api/v1/*");

dynamc.setLoadOnStartup(1);

}

}

The preceding source code loads our configuration and specifies the default URL mapping of /api/v1 for the REST web services that we are going to create.

Adding the domain model to the application

At this point in the development process, we should have accomplished the following tasks:

· Created a new application gear to hold our source code

· Added the MongoDB NoSQL database to our OpenShift gear

· Added configuration items to our Java source code

Now, it is time to add our domain model that represents the baseball stadium object. Create a new file named MLBPark.java and place it in the src/main/java/org/springapp/domain directory. Once the new Java file has been created, add the following lines of code:

package org.springapp.domain;

import org.springframework.data.annotation.Id;

import org.springframework.data.mongodb.core.index.Indexed;

import org.springframework.data.mongodb.core.mapping.Document;

@Document(collection="teams")

public class MLBPark {

@Id

private String id;

private String name;

@Indexed

private double[] coordinates;

private String ballpark;

private long payroll;

private String league;

public String getId() {

return id;

}

public void setId(String id) {

this.id = id;

}

public String getName() {

return name;

}

public void setName(String name) {

this.name = name;

}

public double[] getCoordinates() {

return coordinates;

}

public void setCoordinates(double[] coordinates) {

this.coordinates = coordinates;

}

public String getBallpark() {

return ballpark;

}

public void setBallpark(String ballpark) {

this.ballpark = ballpark;

}

public long getPayroll() {

return payroll;

}

public void setPayroll(long payroll) {

this.payroll = payroll;

}

public String getLeague() {

return league;

}

public void setLeague(String league) {

this.league = league;

}

}

Adding the REST endpoint to the application

The final piece of Java code that we need to add is the actual logic for the REST web service that will be available at the /api/v1/parks URL. The class will contain the following two methods:

· getAllParks(): This method will return a JSON document that contains all the baseball stadiums that we imported previously in this chapter

· findParksWithin(): This method will return baseball stadiums within the supplied latitude and longitude

Create a new source file named MLBParkResource.java, and place the file in the src/main/java/org/springapp/rest directory. Once the file has been created, add the following code snippet:

package org.springapp.rest;

import java.util.List;

import org.springapp.domain.MLBPark;

import org.springframework.beans.factory.annotation.Autowired;

import org.springframework.data.mongodb.core.MongoTemplate;

import org.springframework.data.mongodb.core.geo.Box;

import org.springframework.data.mongodb.core.geo.Point;

import org.springframework.data.mongodb.core.query.Criteria;

import org.springframework.data.mongodb.core.query.Query;

import org.springframework.http.MediaType;

import org.springframework.stereotype.Controller;

import org.springframework.web.bind.annotation.RequestMapping;

import org.springframework.web.bind.annotation.RequestMethod;

import org.springframework.web.bind.annotation.RequestParam;

import org.springframework.web.bind.annotation.ResponseBody;

@Controller

@RequestMapping("/parks")

public class MLBParkResource {

@Autowired

private MongoTemplate mongoTemplate;

@RequestMapping(method = RequestMethod.GET, produces = MediaType.APPLICATION_JSON_VALUE)

public @ResponseBody List<MLBPark> getAllParks() {

return mongoTemplate.findAll(MLBPark.class);

}

@RequestMapping(value="within", method = RequestMethod.GET, produces = MediaType.APPLICATION_JSON_VALUE)

public @ResponseBody List<MLBPark> findParksWithin(@RequestParam("lat1") float lat1, @RequestParam("lon1") float lon1, @RequestParam("lat2") float lat2, @RequestParam("lon2") float lon2) {

Query query = Query.query(Criteria.where("coordinates").within(new Box(new Point(lon2,lat2), new Point(lon1,lat1))));

return mongoTemplate.find(query , MLBPark.class);

}

}

Deploying the application

At this point, we have all the pieces of the puzzle in order to deploy our application and to verify that the REST web service is behaving correctly. To deploy the code, we need to add all of the new source files that we created to our local repository, commit the changes, and finally, push the new code to our OpenShift gear. Change to the root directory of your application and execute the following commands:

$ git add .

$ git commit -am "Adding configuration and REST endpoint"

$ git push

Once you push the changes, the build process will begin. The first time a Java application is built using the Maven build system, it can take a few minutes as all of the new dependencies are downloaded to your gear. On subsequent builds, the process will be faster as the dependencies are cached in the local Maven repository.

Once your application has been deployed, try it out by visiting the link for the application in your web browser at http://springmlb-packt.rhcloud.com/api/v1/parks.

Tip

Ensure that you replace the example namespace, which is packt, with the correct one for your OpenShift account.

If everything has been deployed correctly, you should see the following screenshot:

Deploying the application

Congratulations! You just wrote and deployed a Spring application complete with MongoDB, REST-based web services, and geospatial capabilities.

Adding the web frontend

If you recall from Chapter 5, Creating and Deploying Java EE Applications, we are using the Leaflet and OpenStreetMap projects in order to create our frontend. Since we covered these technologies in the previous chapter, we will not be covering the HTML source file in this chapter in depth. Instead, I will list the instructions for removing the default index.html file that is part of the gear template and provide the source code for the new file that will communicate with our REST web service.

The first thing we want to do is remove the existing index.html file that is created by the OpenShift Online template for Tomcat-based applications. The existing index file presents a getting started page that looks like the following screenshot:

Adding the web frontend

To remove this file, switch to the springmlb/src/main/webapp directory and issue the following commands:

$ git rm index.html

$ git commit -am "Remove existing index file"

Now that we have removed the existing index file, it's time to create a new one. Open your favorite text editor and create a file named index.html under the springmlb/src/main/webapp directory. Once the file has been created, add the following source code:

<!doctype html>

<html lang="en">

<head>

<title>Map of MLB Parks</title>

<link rel="stylesheet" href="http://cdn.leafletjs.com/leaflet-0.5.1/leaflet.css" />

<!--[if lte IE 8]>

<link rel="stylesheet" href="http://cdn.leafletjs.com/leaflet-0.5.1/leaflet.ie.css" />

<![endif]-->

<script src="http://code.jquery.com/jquery-2.0.0.min.js"></script>

<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no" /> <style type="text/css">

body {

padding: 0;

margin: 0;

}

html, body, #map {

height: 100%;

font-family: 'oswald';

}

.leaflet-container .leaflet-control-zoom {

margin-left: 13px;

margin-top: 70px;

}

#map { z-index: 1;}

#title { z-index: 2; position: absolute; left: 10px; }

</style>

</head>

The preceding code snippet creates the <HEAD> element of the HTML file and specifies the JavaScript dependencies that we need for both the Leaflet and JQuery projects. We also define some custom CSS styles that we will use while creating the layout of the HTML page. We are now ready to create the <BODY> section of the HTML file. Open the index.html file again and add the following code directly after the closing </HEAD> tag:

<body>

<h1 id="title">MLB Stadiums</h1>

<div id="map"></div>

<script src="http://cdn.leafletjs.com/leaflet-0.5.1/leaflet.js"></script>

<script>

center = new L.LatLng(39.82, -98.57);

zoom = 5;

var map = L.map('map').setView(center, zoom);

var markerLayerGroup = L.layerGroup().addTo(map);

L.tileLayer('http://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png', {

maxZoom: 18,

attribution: 'Map data © <a href="http://openstreetmap.org">OpenStreetMap</a> contributors, <a href="http://creativecommons.org/licenses/by-sa/2.0/">CC-BY-SA</a>'

}).addTo(map);

In the preceding code snippet, we defined the center of the map that the user will see when opening the web page. The center is set to the 39.92 and -98.57 coordinates, which is the center of the United States. We also created our attribution tag that will be displayed on the bottom right-hand corner of the map.

It is now time for us to create a couple of functions to get the locations of the stadiums by calling our REST API and then placing the pins or markers on the map in order to display the location of each stadium. Open the index.html file and add the following lines of code to the bottom of the file:

function getPins(e){

bounds = map.getBounds();

url = "api/v1/parks/within?lat1=" + bounds.getNorthEast().lat + "&lon1=" + bounds.getNorthEast().lng + "&lat2=" + bounds.getSouthWest().lat + "&lon2=" + bounds.getSouthWest().lng;

$.get(url, pinTheMap, "json")

}

Number.prototype.toCurrencyString = function() { return "$" + Math.floor(this).toLocaleString() + (this % 1).toFixed(2).toLocaleString().replace(/^0/,''); }

function pinTheMap(data){

//clear the current pins

map.removeLayer(markerLayerGroup);

//add the new pins

var markerArray = new Array(data.length)

for (var i = 0; i < data.length; i++){

park = data[i];

var popupInformation = "<b>" + park.name + "</b></br>" + park.ballpark + "</br>";

popupInformation += "<b>Team Payroll: </b>" + park.payroll.toCurrencyString() + "</br>";

popupInformation += "<b>League: </b>" + park.league + "</br>";

markerArray[i] = L.marker([park. coordinates [1], park. coordinates [0]]).bindPopup(popupInformation);

}

markerLayerGroup = L.layerGroup(markerArray).addTo(map);

}

map.on('dragend', getPins);

map.on('zoomend', getPins);

map.whenReady(getPins)

</script>

</body>

</html>

Once the code has been added, save your changes, and then deploy the application again with the following commands:

$ git add index.html

$ git commit -am "adding UI"

$ git push

Once the code has been deployed, point your web browser to the URL of your application, and you should see the finished application as shown in the following screenshot:

Adding the web frontend

Having fun with the web UI

Fantastic! At this point, our first iteration of the application is complete and functional, but it's time to make a few tweaks to the user interface. One of the great benefits of using projects such as Leaflet and OpenStreetMap is being able to switch out the tiles that are displayed to the user. For instance, suppose we are tired of the same look and feel of our application and want to spice it up a bit by showing the terrain view. In order to accomplish this, let's switch out the tiling system in the index.html file. The existing line that specifies the tiles is as follows:

L.tileLayer('http://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png', {

Change the preceding line of code to the following line of code:

L.tileLayer('http://{s}.tile.stamen.com/terrain/{z}/{x}/{y}.png', {

Save and commit your change and then push the code to your OpenShift server. When the deployment is complete, you should see the following new map available:

Having fun with the web UI

Pretty fancy, isn't it? Why stop there; let's try out a watercolor view with the following code change:

L.tileLayer('http://{s}.tile.stamen.com/watercolor/{z}/{x}/{y}.png', {

The map now looks like the following image:

Having fun with the web UI

Note

The preceding map tiles are made available by Stamen Design and are licensed under Creative Commons. For more information on using these tile sets and attribution, head over to http://maps.stamen.com/.

Summary

In this chapter, we learned how to create a Spring-Framework-based application using the Tomcat 7 servlet container. Along the journey, we tackled tasks such as using environment variables to configure the MongoDB database and how to create REST-based web services. We also explored how to change the tile sets that are displayed to the user when interacting with the application.

In the next chapter, we are going to learn how to use a continuous integration environment by adding support for the popular Jenkins project to our baseball parks application.