




















































In this article by Grant Shipley author of Learning OpenShift we are going to learn how to use OpenShift in order to create and deploy Java-EE-based applications using the JBoss Enterprise Application Platform (EAP) application server. To illustrate and learn the concepts of Java EE, we are going to create an application that displays an interactive map that contains all of the major league baseball parks in the United States. We will start by covering some background information on the Java EE framework and then introduce each part of the sample application. The process for learning how to create the sample application, named mlbparks, will be started by creating the JBoss EAP container, then adding a database, creating the web services, and lastly, creating the responsive map UI.
(For more resources related to this topic, see here.)
I can't think of a single programming language other than Java that has so many fans while at the same time has a large community of developers that profess their hatred towards it. The bad reputation that Java has can largely be attributed to early promises made by the community when the language was first released and then not being able to fulfill these promises. Developers were told that we would be able to write once and run anywhere, but we quickly found out that this meant that we could write once and then debug on every platform. Java was also perceived to consume more memory than required and was accused of being overly verbose by relying heavily on XML configuration files.
Another problem the language had was not being able to focus on and excel at one particular task. We used Java to create thick client applications, applets that could be downloaded via a web browser, embedded applications, web applications, and so on. Having Java available as a tool that completes most projects was a great thing, but the implementation for each project was often confusing. For example, let's examine the history of the GUI development using the Java programming language. When the language was first introduced, it included an API called the Abstract Window Toolkit (AWT) that was essentially a Java wrapper around native UI components supplied by the operating system. When Java 1.2 was released, the AWT implementation was deprecated in the favor of the Swing API that contained GUI elements written in 100 percent Java. By this time, a lot of developers were quickly growing frustrated with the available APIs and a new toolkit called the Standard Widget Toolkit (SWT) was developed to create another UI toolkit for Java. SWT was developed at IBM and is the windowing toolkit in use by the Eclipse IDE and is considered by most to be the superior toolkit that can be used when creating applications. As you can see, rapid changes in the core functionality of the language coupled with the refusal of some vendors to ship the JRE as part of the operating system left a bad taste in most developers' mouths.
Another reason why developers began switching from Java to more attractive programming languages was the implementation of Enterprise JavaBeans (EJB). The first Java EE release occurred in December, 1999, and the Java community is just now beginning to recover from the complexity introduced by the language in order to create applications. If you were able to escape creating applications using early EJBs, consider yourself one of the lucky ones, as many of your fellow developers were consumed by implementing large-scale systems using this new technology. It wasn't fun; trust me. I was there and experienced it firsthand.
When developers began abandoning Java EE, they seemed to go in one of two directions. Developers who understood that the Java language itself was quite beautiful and useful adopted the Spring Framework methodology of having enterprise grade features while sticking with a Plain Old Java Object (POJO) implementation. Other developers were wooed away by languages that were considered more modern, such as Ruby and the popular Rails framework. While the rise in popularity of both Ruby and Spring was happening, the team behind Java EE continued to improve and innovate, which resulted in the creation of a new implementation that is both easy to use and develop with.
I am happy to report that if you haven't taken a look at Java EE in the last few years, now is the time to do so. Working with the language after a long hiatus has been a rewarding and pleasurable experience.
For the remainder of this article, we are going to develop an application called mlbparks that displays a map of the United States with a pin on the map representing the location of each major league baseball stadium. The requirements for the application are as follows:
The end state application will look like the following screenshot:
The user will also be able to zoom in on a specific location by double-clicking on the map or by clicking on the + zoom button in the top-left corner of the application. For example, if a user zooms the map in to the Phoenix, Arizona area of the United States, they will be able to see the information for the Arizona Diamondbacks stadium as shown in the following screenshot:
To view this sample application running live, open your browser and type http://mlbparks-packt.rhcloud.com.
Now that we have our requirements and know what the end result should look like, let's start creating our application.
For the sample application that we are going to develop as part of this article, we are going to take advantage of the JBoss EAP application server that is available on the OpenShift platform.
The JBoss EAP application server is a fully tested, stable, and supported platform for deploying mission-critical applications. Some developers prefer to use the open source community application server from JBoss called WildFly. Keep in mind when choosing WildFly over EAP that it only comes with community-based support and is a bleeding edge application server.
To get started with building the mlbparks application, the first thing we need to do is create a gear that contains the cartridge for our JBoss EAP runtime. For this, we are going to use the RHC tools. Open up your terminal application and enter in the following command:
$ rhc app create mlbparks jbosseap-6
Once the previous command is executed, you should see the following output:
Application Options ------------------- Domain: yourDomainName Cartridges: jbosseap-6 (addtl. costs may apply) Gear Size: default Scaling: no Creating application 'mlbparks' ... done Waiting for your DNS name to be available ... done Cloning into 'mlbparks'... Your application 'mlbparks' is now available. URL: http://mlbparks-yourDomainName.rhcloud.com/ SSH to: 5311180f500446f54a0003bb@mlbparks-yourDomainName.rhcloud.com Git remote: ssh://5311180f500446f54a0003bb@mlbparks-yourDomainName.rhcloud.com/~/git/mlbparks.git/ Cloned to: /home/gshipley/code/mlbparks Run 'rhc show-app mlbparks' for more details about your app.
If you have a paid subscription to OpenShift Online, you might want to consider using a medium- or large-size gear to host your Java-EE-based applications. To create this application using a medium-size gear, use the following command:
$ rhc app create mlbparks jbosseap-6 -g medium
Now that our application gear has been created, the next thing we want to do is embed a database cartridge that will hold the information about the baseball stadiums we want to track. Given that we are going to develop an application that doesn't require referential integrity but provides a REST-based API that will return JSON, it makes sense to use MongoDB as our database.
MongoDB is arguably the most popular NoSQL database available today. The company behind the database, MongoDB, offers paid subscriptions and support plans for production deployments. For more information on this popular NoSQL database, visit www.mongodb.com.
Run the following command to embed a database into our existing mlbparks OpenShift gear:
$ rhc cartridge add mongodb-2.4 -a mlbparks
Once the preceding 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 'mlbparks' ... done mongodb-2.4 (MongoDB 2.4) ------------------------- Gears: Located with jbosseap-6 Connection URL: mongodb://$OPENSHIFT_MONGODB_DB_HOST:$OPENSHIFT_MONGODB_DB_PORT/ Database Name: mlbparks Password: q_6eZ22-fraN Username: admin MongoDB 2.4 database added. Please make note of these credentials: Root User: admin Root Password: yourPassword Database Name: mlbparks Connection URL: mongodb://$OPENSHIFT_MONGODB_DB_HOST:$OPENSHIFT_MONGODB_DB_PORT/
Now that we have our application gear created and our database added, we need to populate the database with the information about the stadiums that we are going to place on the map. The data is provided as a JSON document and contains the following information:
A sample for the Arizona Diamondbacks looks like the following line of code:
{ "name":"Diamondbacks", "payroll":89000000, "coordinates":[ -112.066662, 33.444799 ], "ballpark":"Chase Field", "city":"Phoenix", "league":"National League", "year":"2013", "players":[ { "name":"Miguel Montero", "position":"Catcher", "salary":10000000 }, ………… ]}
In order to import the preceding data, we are going to use the SSH command. To get started with the import, SSH into your OpenShift gear for the mlbparks application by issuing the following command in your terminal prompt:
$ rhc app ssh mlbparks
Once we are connected to the remote gear, we need to download the JSON file and store it in the /tmp directory of our gear. To complete these steps, use the following commands on your remote gear:
$ cd /tmp $ wget https://raw.github.com/gshipley/mlbparks/master/mlbparks.json
Wget is a software package that is available on most Linux-based operating systems in order to retrieve files using HTTP, HTTPS, or FTP.
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 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
What just happened? To understand this, we need to break the command we issued into smaller chunks, as detailed in the following table:
Command/argument
|
Description
|
mongoimport | This command is provided by MongoDB to allow users to import data into a database. |
--jsonArray | This specifies that we are going to import an array of JSON documents. |
-d $OPENSHIFT_APP_NAME | Specifies the database that we are going to import the data into the database. We are using a system environment variable to use the database that was created by default when we embedded the database cartridge in our application. |
-c teams | This defines the collection to which we want to import the data. If the collection does not exist, it will be created. |
--type json | This specifies the type of file we are going to import. |
--file /tmp/mlbparks.json | This specifies the full path and name of the file that we are going to import into the database. |
-h $OPENSHIFT_MONGODB_DB_HOST | This specifies the host of the MongoDB server. |
--port $OPENSHIFT_MONGODB_DB_PORT | This specifies the port of the MongoDB server. |
-u $OPENSHIFT_MONGODB_DB_USERNAME | This specifies the username to be used to be authenticated to the database. |
-p $OPENSHIFT_MONGODB_DB_PASSWORD | This specifies the password to be authenticated to the database. |
To verify that data was loaded properly, you can use the following command that will print out the number of documents in the teams collections of the mlbparks 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.
Geospatial queries are what allow us to search for specific documents that fall within a given location as provided by the latitude and longitude parameters.
To add the 2d index to the teams collections, 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" } );'
The next step in creating the mlbparks application is adding the MongoDB driver dependency to our application. OpenShift Online supports the popular Apache Maven build system as the default way of compiling the source code and resolving dependencies.
Maven was originally created to simplify the build process by allowing developers to specify specific JARs that their application depends on. This alleviates the bad practice of checking JAR files into the source code repository and allows a way to share JARs across several projects. This is accomplished via a pom.xml file that contains configuration items and dependency information for the project.
In order to add the dependency for the MongoDB client to our mlbparks applications, we need to modify the pom.xml file that is in the root directory of the Git repository. The Git repository was cloned to our local machine during the application's creation step that we performed earlier in this article. Open up your favorite text editor and modify the pom.xml file to include the following lines of code in the <dependencies> block:
<dependency> <groupId>org.mongodb</groupId> <artifactId>mongo-java-driver</artifactId> <version>2.9.1</version> </dependency>
Once you have added the dependency, commit the changes to your local repository by using the following command:
$ git commit -am "added MongoDB dependency"
Finally, let's push the change to our Java application to include the MongoDB database drivers using the git push command:
$ git push
The first time the Maven build system builds the application, it downloads all the dependencies for the application and then caches them. Because of this, the first build will always that a bit longer than any subsequent build.
At this point, we have our application created, the MongoDB database embedded, all the information for the baseball stadiums imported, and the dependency for our database driver added to our application. The next step is to do some actual coding by creating a Java class that will act as the interface for connecting to and communicating with the MongoDB database. Create a Java file named DBConnection.java in the mlbparks/src/main/java/org/openshift/mlbparks/mongo directory and add the following source code:
package org.openshift.mlbparks.mongo; import java.net.UnknownHostException; import javax.annotation.PostConstruct; import javax.enterprise.context.ApplicationScoped; import javax.inject.Named; import com.mongodb.DB; import com.mongodb.Mongo; @Named @ApplicationScoped public class DBConnection { private DB mongoDB; public DBConnection() { super(); } @PostConstruct public void afterCreate() { String mongoHost = System.getenv("OPENSHIFT_MONGODB_DB_HOST"); String mongoPort = System.getenv("OPENSHIFT_MONGODB_DB_PORT"); String mongoUser = System.getenv("OPENSHIFT_MONGODB_DB_USERNAME"); String mongoPassword = System.getenv("OPENSHIFT_MONGODB_DB_PASSWORD"); String mongoDBName = System.getenv("OPENSHIFT_APP_NAME"); int port = Integer.decode(mongoPort); Mongo mongo = null; try { mongo = new Mongo(mongoHost, port); } catch (UnknownHostException e) { System.out.println("Couldn't connect to MongoDB: " + e.getMessage() + " :: " + e.getClass()); } mongoDB = mongo.getDB(mongoDBName); if (mongoDB.authenticate(mongoUser, mongoPassword.toCharArray()) == false) { System.out.println("Failed to authenticate DB "); } } public DB getDB() { return mongoDB; } }
The preceding source code as well as all source code for this article is available on GitHub at https://github.com/gshipley/mlbparks.
The preceding code snippet simply creates an application-scoped bean that is available until the application is shut down.
The @ApplicationScoped annotation is used when creating application-wide data or constants that should be available to all the users of the application. We chose this scope because we want to maintain a single connection class for the database that is shared among all requests.
The next bit of interesting code is the afterCreate method that gets authenticated on the database using the system environment variables.
Once you have created the DBConnection.java file and added the preceding source code, add the file to your local repository and commit the changes as follows:
$ git add . $ git commit -am "Adding database connection class"
The DBConnection class we just created makes use of Context Dependency Injection (CDI), which is part of the Java EE specification, for dependency injection.
According to the official specification for CDI, an application that uses CDI must have a file called beans.xml. The file must be present and located under the WEB-INF directory. Given this requirement, create a file named beans.xml under the mlbparks/src/main/webapp/WEB-INF directory and add the following lines of code:
<?xml version="1.0"?> <beans xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://jboss.org/schema/cdi/beans_1_0.xsd"/>
After you have added the beans.xml file, add and commit it to your local Git repository:
$ git add . $ git commit -am "Adding beans.xml for CDI"
In this article we learned about the evolution of Java EE, created a JBoss EAP application, and created the database access class.