Posts Tagged Web Application
Retrieving and Displaying Data with AngularJS and the MEAN Stack: Part II
Posted by Gary A. Stafford in Client-Side Development, DevOps, Enterprise Software Development, Mobile HTML Development, Software Development on March 24, 2014
Explore various methods of retrieving and displaying data using AngularJS and the MEAN Stack.
Introduction
In this two-part post, we are exploring methods of retrieving and displaying data using AngularJS and the MEAN Stack. The post’s corresponding GitHub project, ‘meanstack-data-samples‘, is based on William Lepinski’s ‘generator-meanstack‘, which is in turn is based on Yeoman’s ‘generator-angular‘. As a bonus, since both projects are based on ‘generator-angular’, all the code generators work. Generators can save a lot of time and aggravation when building AngularJS components.
In part one of this post, we installed and configured the ‘meanstack-data-samples’ project from GitHub. In part two, we will we will look at five examples of retrieving and displaying data using AngularJS:
- Function within AngularJS Controller returns array of strings.
- AngularJS Service returns an array of simple object literals to the controller.
- AngularJS Factory returns the contents of JSON file to the controller.
- AngularJS Factory returns the contents of JSON file to the controller using a resource object
(In GitHub project, but not discussed in this post). - AngularJS Factory returns a collection of documents from MongoDB Database to the controller.
- AngularJS Factory returns results from Google’s RESTful Web Search API to the controller.
Project Structure
For brevity, I have tried to limit the number of files in the project. There are two main views, both driven by a single controller. The primary files, specific to data retrieval and display, are as follows:
- Default site file (./)
- index.html – loads all CSS and JavaScript files, and views
- App and Routes (./app/scripts/)
- app.js – instantiates app and defines routes (route/view/controller relationship)
- Views (./app/views/)
- data-bootstrap.html – uses Twitter Bootstrap
- data-no-bootstrap.html – basically the same page, without Twitter Bootstrap
- Controllers (./app/scripts/controllers/)
- DataController.js (DataController) – single controller used by both views
- Services and Factories (./app/scripts/services/)
- meanService.js (meanService) – service returns array of object literals to DataController
- jsonFactory.js (jsonFactory) – factory returns contents of JSON file
- jsonFactoryResource.js (jsonFactoryResource) – factory returns contents of JSON file using resource object (new)
- mongoFactory.js (mongoFactory) – factory returns MongoDB collection of documents
- googleFactory.js (googleFactory) – factory call Google Web Search API
- Models (./app/models/)
- Components.js – mongoose constructor for the Component schema definition
- Routes (./app/)
- routes.js – mongoose RESTful routes
- Data (./app/data/)
- otherStuff.json – static JSON file loaded by jsonFactory
- Environment Configuration (./config/environments/)
- index.js – defines all environment configurations
- test.js – Configuration specific to the current ‘test’ environment
- Unit Tests (./test/spec/…)
- Various files – all controller and services/factories unit test files are in here…
There are many more files, critical to the project’s functionality, include app.js, Gruntfile.js, bower.json, package.json, server.js, karma.conf.js, and so forth. You should understand each of these file’s purposes.
Function Returns Array
In the first example, we have the yeomanStuff()
method, a member of the $scope
object, within the DataController
. The yeomanStuff()
method return an array object containing three strings. In JavaScript, a method is a function associated with an object.
$scope.yeomanStuff = function () { return [ 'yo', 'Grunt', 'Bower' ]; };
The yeomanStuff()
method is called from within the view by Angular’s ng-repeat
directive. The directive, ng-repeat
, allows us to loop through the array of strings and add them to an unordered list. We will use ng-repeat
for all the examples in this post.
<ul class="list-group"> <li class="list-group-item" ng-repeat="stuff in yeomanStuff()"> {{stuff}} </li> <ul>
Although this first example is easy to implement, it is somewhat impractical. Generally, you would not embed static data into your code. This limits your ability to change the data, independent of a application’s code. In addition, the function is tightly coupled to the controller, limiting its reuse.
Service Returns Array
In the second example, we also use data embedded in our code. However, this time we have improved the architecture slightly by moving the data to an Angular Service. The meanService
contains the getMeanStuff()
function, which returns an array containing four object literals. Using a service, we can call the getMeanStuff()
function from anywhere in our project.
angular.module('generatorMeanstackApp') .service('meanService', function () { this.getMeanStuff = function () { return ([ { component: 'MongoDB', url: 'http://www.mongodb.org' }, { component: 'Express', url: 'http://expressjs.com' }, { component: 'AngularJS', url: 'http://angularjs.org' }, { component: 'Node.js', url: 'http://nodejs.org' } ]) }; });
Within the DataController
, we assign the array object, returned from the meanService.getMeanStuff()
function, to the meanStuff
object property of the $scope
object.
$scope.meanStuff = {}; try { $scope.meanStuff = meanService.getMeanStuff(); } catch (error) { console.error(error); }
The meanStuff
object property is accessed from within the view, using ng-repeat
. Each object in the array contains two properties, component
and url
. We display the property values on the page using Angular’s double curly brace expression notation (i.e. ‘{{stuff.component}}
‘).
<ul class="nav nav-pills nav-stacked"> <li ng-repeat="stuff in meanStuff"> url}}" target="_blank">{{stuff.component}} </li> <ul>
Promises, Promises…
The remaining methods implement an asynchronous (non-blocking) programming model, using the $http
and $q
services of Angular’s ng
module. The services implements the asynchronous Promise and Deferred APIs. According to Chris Webb, in his excellent two-part post, Promise & Deferred objects in JavaScript: Theory and Semantics, a promise represents a value that is not yet known and a deferred represents work that is not yet finished. I strongly recommend reading Chris’ post, before continuing. I also highly recommend watching RED Ape EDU’s YouTube video, Deferred and Promise objects in Angular js. This video really clarified the promise and deferred concepts for me.
Factory Loads JSON File
In the third example, we will read data from a JSON file (‘./app/data/otherStuff.json
‘) using an AngularJS Factory. The differences between a service and a factory can be confusing, and are beyond the scope of this post. Here is two great links on the differences, one on Angular’s site and one on StackOverflow.
{ "components": [ { "component": "jQuery", "url": "http://jquery.com" }, { "component": "Jade", "url": "http://jade-lang.com" }, { "component": "JSHint", "url": "http://www.jshint.com" }, { "component": "Karma", "url": "http://karma-runner.github.io" }, ... ] }
The jsonFactory
contains the getOtherStuff()
function. This function uses $http.get()
to read the JSON file and returns a promise of the response object. According to Angular’s site, “since the returned value of calling the $http function is a promise, you can also use the then method to register callbacks, and these callbacks will receive a single argument – an object representing the response. A response status code between 200 and 299 is considered a success status and will result in the success callback being called. ” As I mentioned, a complete explanation of the deferreds and promises, is too complex for this short post.
angular.module('generatorMeanstackApp') .factory('jsonFactory', function ($q, $http) { return { getOtherStuff: function () { var deferred = $q.defer(), httpPromise = $http.get('data/otherStuff.json'); httpPromise.then(function (response) { deferred.resolve(response); }, function (error) { console.error(error); }); return deferred.promise; } }; });
The response object contains the data
property. Angular defines the response object’s data
property as a string or object, containing the response body transformed with the transform functions. One of the properties of the data
property is the components
array containing the seven objects. Within the DataController
, if the promise is resolved successfully, the callback function assigns the contents of the components
array to the otherStuff
property of the $scope
object.
$scope.otherStuff = {}; jsonFactory.getOtherStuff() .then(function (response) { $scope.otherStuff = response.data.components; }, function (error) { console.error(error); });
The otherStuff
property is accessed from the view, using ng-repeat
, which displays individual values, exactly like the previous methods.
<ul class="nav nav-pills nav-stacked"> <li ng-repeat="stuff in otherStuff"> <a href="{{stuff.url}}" target="_blank">{{stuff.component}}</a> </li> </ul>
This method of reading a JSON file is often used for configuration files. Static configuration data is stored in a JSON file, external to the actual code. This way, the configuration can be modified without requiring the main code to be recompiled and deployed. It is a technique used by the components within this very project. Take for example the bower.json
files and the package.json
files. Both contain configuration data, stored as JSON, used by Bower and npm to perform package management.
Factory Retrieves Data from MongoDB
In the fourth example, we will read data from a MongoDB database. There are a few more moving parts in this example than in the previous examples. Below are the documents in the components
collection of the meanstack-test
MongoDB database, which we will retrieve and display with this method. The meanstack-test
database is defined in the test.js
environments file (discussed in part one).
To connect to the MongoDB, we will use Mongoose. According to their website, “Mongoose provides a straight-forward, schema-based solution to modeling your application data and includes built-in type casting, validation, query building, business logic hooks and more, out of the box.” But wait, MongoDB is schemaless? It is. However, Mongoose provides a schema-based API for us to work within. Again, according to Mongoose’s website, “Everything in Mongoose starts with a Schema. Each schema maps to a MongoDB collection and defines the shape of the documents within that collection.”
In our example, we create the componentSchema
schema, and pass it to the Component
model (the ‘M’ in MVC). The componentSchema
maps to the database’s components
collection.
var mongoose = require('mongoose'); var Schema = mongoose.Schema; var componentSchema = new Schema({ component: String, url: String }); module.exports = mongoose.model('Component', componentSchema);
The routes.js
file associates routes (Request URIs) and HTTP methods to Mongoose actions. These actions are usually CRUD operations. In our simple example, we have a single route, ‘/api/components
‘, associated with an HTTP GET
method. When an HTTP GET
request is made to the ‘/api/components
‘ request URI, Mongoose calls the Model.find()
function, ‘Component.find()
‘, with a callback function parameter. The Component.find()
function returns all documents in the components
collection.
var Component = require('./models/component'); module.exports = function (app) { app.get('/api/components', function (req, res) { Component.find(function (err, components) { if (err) res.send(err); res.json(components); }); }); };
You can test these routes, directly. Below, is the results of calling the ‘/api/components
‘ route in Chrome.
The mongoFactory
contains the getMongoStuff()
function. This function uses $http.get()
to call the ‘/api/components
‘ route. The route is resolved by the routes.js
file, which in turn executes the Component.find()
command. The promise of an array of objects is returned by the getMongoStuff()
function. Each object represents a document in the components
collection.
angular.module('generatorMeanstackApp') .factory('mongoFactory', function ($q, $http) { return { getMongoStuff: function () { var deferred = $q.defer(), httpPromise = $http.get('/api/components'); httpPromise.success(function (components) { deferred.resolve(components); }) .error(function (error) { console.error('Error: ' + error); }); return deferred.promise; } }; });
Within the DataController
, if the promise is resolved successfully, the callback function assigns the array of objects, representing the documents in the collection, to the mongoStuff
property of the $scope object.
$scope.mongoStuff = {}; mongoFactory.getMongoStuff() .then(function (components) { $scope.mongoStuff = components; }, function (error) { console.error(error); });
The mongoStuff
property is accessed from the view, using ng-repeat
, which displays individual values using Angular expressions, exactly like the previous methods.
<ul class="list-group"> <li class="list-group-item" ng-repeat="stuff in mongoStuff"> <b>{{stuff.component}}</b> <div class="text-muted">{{stuff.description}}</div> </li> </ul>
Factory Calls Google Search
Post Update: the Google Web Search API is no longer available as of September 29, 2014. The post’s example post will no longer return a resultset. Please migrate to the Google Custom Search API (https://developers.google.com/custom-search/). Please read ‘Calling Third-Party HTTP-based RESTful APIs from the MEAN Stack‘ post for more information on using Google’s Custom Search API.
In the last example, we will call the Google Web Search API from an AngularJS Factory. The Google Web Search API exposes a simple RESTful interface. According to Google, “in all cases, the method supported is GET and the response format is a JSON encoded result set with embedded status codes.” Google describes this method of using RESTful access to the API, as “for Flash developers, and those developers that have a need to access the Web Search API from other Non-JavaScript environment.” However, we will access it in our JavaScript-based MEAN stack application, due to the API’s ease of implementation.
Note according to Google’s site, “the Google Web Search API has been officially deprecated…it will continue to work…but the number of requests…will be limited. Therefore, we encourage you to move to Custom Search, which provides an alternative solution.” Google Search, or more specifically, the Custom Search JSON/Atom API, is a newer API, but the Web Search API is easier to demonstrate in this brief post than Custom Search JSON/Atom API, which requires the use of an API key.
The googleFactory
contains the getSearchResults()
function. This function uses $http.jsonp()
to call the Google Web Search API RESTful interface and return the promise of the JSONP-formatted (‘JSON with padding’) response. JSONP provides cross-domain access to a JSON payload, by wrapping the payload in a JavaScript function call (callback).
angular.module('generatorMeanstackApp') .factory('googleFactory', function ($q, $http) { return { getSearchResults: function () { var deferred = $q.defer(), host = 'https://ajax.googleapis.com/ajax/services/search/web', args = { 'version': '1.0', 'searchTerm': 'mean%20stack', 'results': '8', 'callback': 'JSON_CALLBACK' }, params = ('?v=' + args.version + '&q=' + args.searchTerm + '&rsz=' + args.results + '&callback=' + args.callback), httpPromise = $http.jsonp(host + params); httpPromise.then(function (response) { deferred.resolve(response); }, function (error) { console.error(error); }); return deferred.promise; } }; });
The getSearchResults()
function uses the HTTP GET method to make an HTTP request the following RESTful URI:
https://ajax.googleapis.com/ajax/services/search/web?v=1.0&q=mean%20stack&rsz=8&callback=angular.callbacks._0
Using Google Chrome’s Developer tools, we can preview the Google Web Search JSONP-format HTTP response (abridged). Note the callback function that wraps the JSON payload.
Within the DataController
, if the promise is resolved successfully, our callback function returns the response object. The response object contains a lot of information. We are able to limit that amount of information sent to the view by only assigning the actual search results, an array of eight objects contained in the response object, to the googleStuff
property of the $scope
object.
$scope.googleStuff = {}; googleFactory.getSearchResults() .then(function (response) { $scope.googleStuff = response.data.responseData.results; }, function (error) { console.error(error); });
Below is the full response returned by the The googleFactory
. Note the path to the data we are interested in: ‘response.data.responseData.results
‘.
Below is the filtered results assigned to the googleStuff
property:
The googleStuff
property is accessed from the view, using ng-repeat
, which displays individual values using Angular expressions, exactly like the previous methods.
<ul class="list-group"> <li class="list-group-item" ng-repeat="stuff in googleStuff"> <a href="{{unescapedUrl.url}}" target="_blank"><b>{{stuff.visibleUrl}}</b></a> <div class="text-muted">{{stuff.titleNoFormatting}}</div> </li> </ul>
Links
- Promise & Deferred objects in JavaScript Pt.1: Theory and Semantics
- Promise & Deferred objects in JavaScript Pt.2: Theory and Semantics
- Deferred and Promise objects in Angular js (YouTube video – excellent!)
- Deferred Promise Workshop (goes with above video)
- Angular.js Promise and Deferred Api – Implementation Explained
- Creating a Single Page Todo App with Node and Angular
- Build an Angular Todo App with a Node Backend
- Consuming REST APIs
Retrieving and Displaying Data with AngularJS and the MEAN Stack: Part I
Posted by Gary A. Stafford in Client-Side Development, DevOps, Mobile HTML Development, Software Development on March 22, 2014
Explore various methods of retrieving and displaying data using AngularJS and the MEAN Stack.
Introduction
In the following two-part post, we will explore several methods of retrieving and displaying data using AngularJS and the MEAN Stack. The post’s corresponding GitHub project, ‘meanstack-data-samples‘, is based on William Lepinski’s ‘generator-meanstack‘, which is in turn is based on Yeoman’s ‘generator-angular‘. As a bonus, since both projects are based on ‘generator-angular’, all the code generators work. Generators can save a lot of time and aggravation when building AngularJS components.
In part one of this post, we will install and configure the ‘meanstack-data-samples’ project from GitHub, which corresponds to this post. In part two, we will we will look at several methods for retrieving and displaying data using AngularJS:
- Function within AngularJS Controller returns array of strings.
- AngularJS Service returns an array of simple object literals to the controller.
- AngularJS Factory returns the contents of JSON file to the controller.
- AngularJS Factory returns the contents of JSON file to the controller using a resource object
(In GitHub project, but not discussed in this post). - AngularJS Factory returns a collection of documents from MongoDB Database to the controller.
- AngularJS Factory returns results from Google’s RESTful Web Search API to the controller.
Preparation
If you need help setting up your development machine to work with the MEAN stack, refer to my last post, Installing and Configuring the MEAN Stack, Yeoman, and Associated Tooling on Windows. You will need to install all the MEAN and Yeoman components.
For this post, I am using JetBrains’ new WebStorm 8RC to build and demonstrate the project. There are several good IDE’s for building modern web applications; WebStorm is one of the current favorites of developers.
Complexity of Modern Web Applications
Building modern web applications using the MEAN stack or comparable technologies is complex. The ‘meanstack-data-samples’ project, and the projects it is based on, ‘generator-meanstack’ and ‘generator-angular’, have dozens of moving parts. In this simple project, we have MongoDB, ExpressJS, AngularJS, Node.js, yo, Grunt, Bower, Git, jQuery, Twitter Bootstrap, Karma, JSHint, jQuery, Mongoose, and hundreds of other components, all working together. There are almost fifty Node packages and hundreds of their dependencies loaded by npm, in addition to another dozen loaded by Bower.
Installing, configuring, and managing all the parts of a modern web application requires a basic working knowledge of these technologies. Understanding how Bower and npm install and manage packages, how Grunt builds, tests, and serves the application with ExpressJS, how Yo scaffolds applications, how Karma and Jasmine run unit tests, or how Mongoose and MongoDB work together, are all essential. This brief post will primarily focus on retrieving and displaying data, not necessarily how the components all work, or work together.
Installing and Configuring the Project
Environment Variables
To start, we need to create (3) environment variables. The NODE_ENV
environment variable is used to determine the environment our application is operating within. The NODE_ENV
variable determines which configuration file in the project is read by the application when it starts. The configuration files contain variables, specific to that environment. There are (4) configuration files included in the project. They are ‘development’, ‘test’, ‘production’, and ‘travis’ (travis-ci.org). The NODE_ENV
variable is referenced extensively throughout the project. If the NODE_ENV
variable is not set, the application will default to ‘development
‘.
For this post, set the NODE_ENV
variable to ‘test
‘. The value, ‘test
‘, corresponds to the ‘test
‘ configuration file (‘meanstack-data-samples\config\environments\test.js
‘), shown below.
// set up ===================================== var express = require('express'); var bodyParser = require('body-parser'); var errorHandler = require('errorhandler'); var favicon = require('serve-favicon'); var logger = require('morgan'); var cookieParser = require('cookie-parser'); var methodOverride = require('method-override'); var session = require('express-session'); var path = require('path'); var env = process.env.NODE_ENV || 'development'; module.exports = function (app) { if ('test' == env) { console.log('environment = test'); app.use(function staticsPlaceholder(req, res, next) { return next(); }); app.set('db', 'mongodb://localhost/meanstack-test'); app.set('port', process.env.PORT || 3000); app.set('views', path.join(app.directory, '/app')); app.engine('html', require('ejs').renderFile); app.set('view engine', 'html'); app.use(favicon('./app/favicon.ico')); app.use(logger('dev')); app.use(bodyParser()); app.use(methodOverride()); app.use(cookieParser('your secret here')); app.use(session()); app.use(function middlewarePlaceholder(req, res, next) { return next(); }); app.use(errorHandler()); } };
The second environment variable is PORT
. The application starts on the port indicated by the PORT
variable, for example, ‘localhost:3000’. If the the PORT
variable is not set, the application will default to port ‘3000
‘, as specified in the each of the environment configuration files and the ‘Gruntfile.js’ Grunt configuration file.
Lastly, the CHROME_BIN
environment variable is used Karma, the test runner for JavaScript, to determine the correct path to browser’s binary file. Details of this variable are discussed in detail on Karma’s site. In my case, the value for the CHROME_BIN
is ‘C:\Program Files (x86)\Google\Chrome\Application\chrome.exe'
. This variable is only necessary if you will be configuring Karma to use Chrome to run the tests. The browser can be changes to any browser, including PhantomJS. See the discussion at the end of this post regarding browser choice for Karma.
You can easily set all the environment variables on Windows from a command prompt, with the following commands. Remember to exit and re-open your interactive shell or command prompt window after adding the variables so they can be used.
REM cofirm the path to Chrome, change value if necessary | |
setx /m NODE_ENV "test" | |
setx /m PORT "3000" | |
setx /m CHROME_BIN "C:\Program Files (x86)\Google\Chrome\Application\chrome.exe" |
Install and Configure the Project
To install and configure the project, we start by cloning the ‘meanstack-data-samples‘ project from GitHub. We then use npm and bower to install the project’s dependencies. Once installed, we create and populate the Mongo database. We then use Grunt and Karma to unit test the project. Finally, we will use Grunt to start the Express Server and run the application. This is all accomplished with only a few individual commands. Please note, the ‘npm install’ command could take several minutes to complete, depending on your network speed; the project has many direct and indirect Node.js dependencies.
# install meanstack-data-samples project | |
git clone https://github.com/garystafford/meanstack-data-samples.git | |
cd meanstack-data-samples | |
npm install | |
bower install | |
mongoimport --db meanstack-$NODE_ENV --collection components components.json --drop # Unix | |
# mongoimport --db meanstack-%NODE_ENV% --collection components components.json --drop # Windows | |
grunt test | |
grunt server |
If everything was installed correctly, running the ‘grunt test’ command should result in output similar to below:
If everything was installed correctly, running the ‘grunt server’ command should result in output similar to below:
Running the ‘grunt server’ command should start the application and open your browser to the default view, as shown below:
Karma’s Browser Choice for Unit Tests
The GitHub project is currently configured to use Chrome for running Karma’s unit tests in the ‘development’ and ‘test’ environments. For the ‘travis’ environment, it uses PhantomJS. If you do not have Chrome installed on your machine, the ‘grunt test’ task will fail during the ‘karma:unit’ task portion. To change Karma’s browser preference, simply change the ‘testBrowser’ variable in the ‘./karma.conf.js’ file, as shown below.
// Karma configuration | |
module.exports = function (config) { | |
// Determines Karma's browser choice based on environment | |
var testBrowser = 'Chrome'; // Default browser | |
if (process.env.NODE_ENV === 'travis') { | |
testBrowser = 'PhantomJS'; // Must use for headless CI (Travis-CI) | |
} | |
console.log("Karma browser: " + testBrowser); | |
... | |
// Start these browsers, currently available: | |
// Chrome, ChromeCanary, Firefox, Opera, | |
// Safari (only Mac), PhantomJS, IE (only Windows) | |
browsers: [testBrowser], |
I recommend installing and using PhantomJS headless WebKit, locally. Since PhantomJS is headless, Karma runs the unit tests without having to open and close browser windows. To run this project on continuous integration servers, like Jenkins or Travis-CI, you must PhantomJS. If you decide to use PhantomJS on Windows, don’t forget add the PhantomJS executable directory path to your ‘PATH’ environment variable to, after downloading and installing the application.
Code Generator
As I mentioned at the start of this post, this project was based on William Lepinski’s ‘generator-meanstack‘, which is in turn is based on Yeoman’s ‘generator-angular‘. Optionally, to install the ‘generator-meanstack’ npm package, globally, on our system use the following command The ‘generator-meanstack’ code generator will allow us to generate additional AngularJS components automatically, within the project, if we choose. The ‘generator-meanstack’ is not required for this post.
npm install -g generator-meanstack
Part II
In part two of this post, we will explore each methods of retrieving and displaying data using AngularJS, in detail.
Links
Discover All Properties Available to an Apache Ant Target
Posted by Gary A. Stafford in Build Automation, Java Development, Software Development on October 27, 2012
Ever waste time searching for a certain property you need to build an Ant target? Here’s a quick tip to save you some time – echoproperties
. According to The Apache Ant Project website, the echoproperties
task ” displays all the current properties (or a subset of them specified by a nested <propertyset>
) in the project. The output can be sent to a file if desired. This task can be used as a somewhat contrived means of returning data from an <ant>
invocation, but is really for debugging build files.”
Recently, I was working on a new Java Web Application Project in NetBeans IDE 7.2.1. I wanted to build an Ant target to automate the deployment of the project’s .war file to GlassFish. To do so, I needed to identify properties that could return 1) the project’s name, 2) the path to the project’s .war file, and 3) the path to GlassFish’s asadmin
utility. Calling the echoproperties
task from within the Ant target below, from within my open project, returned a list of over 90 property key/value pairs.
<target name="list-all-properties"> <echoproperties /> </target>
Although the results were enlightening, I couldn’t find the properties I was hoping to reference in the new target. Next however, I ran the Ant target again, adding the two dependency targets my GlassFish deployment target was going to need, clean
and dist
.
<target name="list-all-properties" depends="clean, dist"> <echoproperties /> </target>
Running the revised target returned almost 450 properties, all available to Ant. The new properties were a result of the clean
and dist
targets running before the call to echoproperties
. Those target’s properties were now also available. Here is a snippet of the results:
... ant.project.invoked-targets=list-all-properties ant.project.name=MySqlEntityWebDemo ant.version=Apache Ant(TM) version 1.8.3 compiled on February 26 2012 ap.cmd.line.internal= ap.proc.none.internal= ap.processors.internal= ap.supported.internal=true application.args.param= awt.toolkit=sun.awt.X11.XToolkit basedir=/home/gstaffor/NetBeansProjects/MySqlEntityWebDemo build.classes.dir=build/web/WEB-INF/classes build.classes.excludes=**/*.java,**/*.form build.compiler.emacs=true build.dir=build build.dir.to.clean=build/web build.generated.dir=build/generated build.generated.sources.dir=build/generated-sources build.meta.inf.dir=build/web/META-INF build.test.classes.dir=build/test/classes build.test.results.dir=build/test/results build.web.dir=build/web build.web.excludes=**/*.java,**/*.form client.urlPart= compile.jsps=false conf.dir=src/conf debug-args-line=-Xdebug debug-transport=dt_socket debug-transport-by-os=dt_socket debug.classpath=build/web/WEB-INF/classes\:/home/gstaffor/JavaFiles/eclipselink_2_4_1/jlib/eclipselink.jar... debug.test.classpath=/home/gstaffor/JavaFiles/eclipselink_2_4_1/jlib/eclipselink.jar... default.javac.source=1.7 default.javac.target=1.7 deploy.ant.properties.file=/home/gstaffor/.netbeans/7.2/gfv3-430621021.properties display.browser=true dist.dir=dist dist.ear.war=dist/MySqlEntityWebDemo.war dist.jar.dir=/home/gstaffor/NetBeansProjects/MySqlEntityWebDemo/dist dist.javadoc.dir=dist/javadoc dist.war=dist/MySqlEntityWebDemo.war ... j2ee.compile.on.save=true j2ee.copy.static.files.on.save=true j2ee.deploy.on.save=true j2ee.platform=1.6-web j2ee.platform.classpath=/home/gstaffor/glassfish-3.1.2.2/glassfish/modules/bean-validator.jar... j2ee.platform.embeddableejb.classpath=/home/gstaffor/glassfish-3.1.2.2/glassfish/lib/embedded/glassfish-embedded-static-shell.jar j2ee.platform.is.jsr109=true j2ee.platform.wscompile.classpath=/home/gstaffor/glassfish-3.1.2.2/glassfish/modules/webservices-osgi.jar... j2ee.platform.wsit.classpath= j2ee.server.domain=/home/gstaffor/glassfish-3.1.2.2/glassfish/domains/domain1 j2ee.server.home=/home/gstaffor/glassfish-3.1.2.2/glassfish j2ee.server.instance=[/home/gstaffor/glassfish-3.1.2.2/glassfish... j2ee.server.middleware=/home/gstaffor/glassfish-3.1.2.2 j2ee.server.type=gfv3ee6 jar.compress=false ... war.content.additional= war.ear.name=MySqlEntityWebDemo.war war.name=MySqlEntityWebDemo.war web.docbase.dir=web webinf.dir=web/WEB-INF
Reviewing the results, I was able to find all the properties I needed to build the target, below.
<target name="glassfish-deploy" depends="clean, dist" description="Build distribution (WAR) and deploy to GlassFish"> <exec failonerror="true" vmlauncher="false" executable="${j2ee.server.home}/bin/asadmin" > <arg line="--host=localhost --port=4848 --user=admin --passwordfile=pwdfile --secure=false deploy --force=true --name='${ant.project.name}' --contextroot='/${ant.project.name}' '${dist.war}'" /> </exec> </target>
Almost any properties you need to develop an Ant Target is probably available if you know where, or how to look.
Connecting Java EE RESTful Web Services to Microsoft SQL Server Using NetBeans and GlassFish
Posted by Gary A. Stafford in Java Development, Software Development on September 15, 2012
Connecting Java EE RESTful web services, hosted on GlassFish, to Microsoft SQL Server – a high level overview. Demonstrate the creation of a Web Application project in NetBeans, including a SQL Server data source, entity classes from a SQL database, and RESTful web services. Show how to test and deploy the project to GlassFish.
Introduction
In a previous post, Connecting Java EE to SQL Server with Microsoft’s JDBC Driver 4.0, I demonstrated how Microsoft’s JDBC Driver 4.0 can connect Java-based RESTful web services to Microsoft SQL Server. In a more recent post, Calling Microsoft SQL Server Stored Procedures from a Java Application Using JDBC, I demonstrated the use of JDBC to call stored procedures from a Java application. In this post, I am going to offer a high-level, end-to-end overview on how to create and connect Java EE RESTful web services, hosted on GlassFish, to SQL Server. The goals of post are:
- Demonstrate the use of Microsoft’s JDBC Driver 4.0 to connect a Java-based application to SQL Server 2008 R2;
- Demonstrate the use of NetBeans to:
- Create a SQL Server Data Source;
- Create entity classes from the SQL Server database using the SQL Server Data Source;
- Create RESTful web services using JAX-RS, which communicate with database, through the entity classes;
- Compile and deploy the data source, entities, and services to GlassFish;
- Test the RESTful Web Services locally in NetBeans, and once deployed, in GlassFish.
Setting up the Post’s Example
To demonstrate the example in this post, I have the follow applications installed, configured, and running in my development environment:
- Microsoft SQL Server 2008 R2 (www.microsoft.com/sqlserver)
- Microsoft’s Adventure Works 2008 R2 Sample Database (msftdbprodsamples.codeplex.com)
- Microsoft JDBC Driver 4.0 for SQL Server (msdn.microsoft.com/en-us/sqlserver/aa937724.aspx)
- NetBeans 7.2 Open Source IDE (netbeans.org)
- Apache Any 1.82 (installed with NetBeans or downloaded separately from ant.apache.org)
- GlassFish 3.2.2.2 Open Source Edition Application Server (installed with NetBeans or downloaded separately from glassfish.java.net)
If you have any questions about installing and configuring the Adventure Works database, please refer to my post, Convert VS 2010 Database Project to SSDT and Automate Publishing with Jenkins – Part 1/3. The post takes you through creating a SQL Server 2008 R2 instance (entitled ‘Development’), installing the Adventure Works database, and creating a database user (‘aw-dev’). Also, refer to my earlier post, Connecting Java EE to SQL Server with Microsoft’s JDBC Driver 4.0, for directions on installing the Microsoft JDBC driver in the lib directory of GlassFish. This is necessary before following along with this demonstration.
Note, since I have NetBeans, SQL Server, and GlassFish all installed on a single computer, the URLs in several of the screen-grabs switch between ‘localhost’ and my computer’s actual name. Both references are interchangeable.
The Demonstration
Here are the high-level steps I will walk-through in this post:
- Confirm the SQL Server instance, database, and user are functioning properly;
- Create a new Web Application project in NetBeans;
- Create the SQL Server data source in the project;
- Create entity classes from the SQL Server database;
- Create RESTful web services using the entity classes;
- Test the web services locally in NetBeans;
- Build and deploy the project to GlassFish;
- Test the web services on GlassFish.
SQL Server
Using Microsoft’s SQL Server Management Studio, Quest’s Toad for SQL, or similar IDE, confirm the ‘Development’ instance (or whatever you have named your instance) of SQL Server 2008 R2 is running. Confirm the Adventure Works database is installed in that instance. Lastly, confirm the ‘aw_dev’ user can connect to the Adventure Works database and view and interact with all the database objects. Confirming these items will elevate many problems you might otherwise encounter when creating the data source, next.

View of the SQL Server Instance from SSMS. Note the : 1) Server, Instance, User, 2) Database, and 3) Schema
Create New Web Application Project
Create a new Java Web Application project in NetBeans. Name the project whatever you would like; I named mine ‘JdbcSqlWebSrvTest’. Select the correct GlassFish server instance and GlassFish domain where the project will be deployed. I am deploying my project to the default ‘domain1’ domain.
Create SQL Server Data Source and Entity Classes from the Database
Right-click on the project again and select ‘New’ -> ‘Other…’. From the list of Categories, select ‘Persistence’. From the list of Persistence choices, choose ‘Entity Classes from Database’. Click Next.
Before we can choose which database tables we want from the Adventure Works database to create entity classes, we must create a connection to the database – a SQL Server Data Source. Click on the Data Source drop down and select ‘New Data Source…’. Give a Java Naming and Directory Interface (JNDI) name for the data source. I called mine ‘AdventureWorks’. Click on the ‘Database Connection’ dropdown, select ‘New Database Connection…’.
This starts the ‘New Connection Wizard’. The first screen, ‘Locate Driver’, is where we point the will instruct NetBeans to use the Microsoft JDBC Driver 4.0 for SQL Server Driver. Locate the sqljdbc4.jar file.
On the next screen, ‘Customize the Connection’, input the required SQL Server information. The host is the machine your instance of SQL Server is installed on, such as ‘localhost’. The instance is the name of the SQL Server instance in which the Adventure Works database is installed, such as ‘Development’. Once you complete the form, click ‘Test Connection’. If it doesn’t succeed, check your settings, again.
As I mentioned in an earlier post, the SQL Server Data Source forces you to select a single database schema. On the ‘Choose Database Schema’ screen, select the ‘HumanResources’ schema. The database tables you will be able to reference from you entity classes are limited to just this schema, when using this data source. To reference other schemas, you will need to create more data sources.
Back in the ‘New Entity Classes from Database’ window, you will now have the ‘AdventureWorks’ data source selected as the Data Source. After a few seconds of processing, all ‘Available Tables’ within the ‘HumanResources’ schema are displayed. Choose the four tables shown in the screen-grab, below. Actually, two are database tables and two are virtual tables, called database ‘views’. We will need to do an extra step later on, to use the two entity classes built from the database views.
On the next screen, ‘Entity Classes’, in the ‘New Entity Classes from Database’ window, give a package name to place the individual entity classes into. I chose to call mine ‘entityclasses’.
On the next screen, ‘Mapping Options’, choose ‘Fully Qualified Database Table Names’. Without this option selected, I have had problems trying to make the RESTful web services function properly. This is also the reason I chose to create the entity classes first, and then create the RESTful web services, separately. NetBeans has an option that combines these two tasks into a single step, by choosing ‘RESTful Web Services from Database’. However, the ‘Fully Qualified Database Table Names’ option is not available on the equivalent screen, using that process (at least in my version of NetBeans 7.2). I prefer the two-step approach.
Click finished. You have successfully created the SQL Server data source and entity classes.
The data source we created, which will be deployed to GlassFish, is referred to as a JDBC Resource and a JDBC Connection Pool. This JDBC information is stored in the ‘glassfish-resources.xml’ file by NetBeans.
The JPA Persistence Unit is found in the ‘persistence.xml’ file in the ‘Configuration Files’ folder. This file describes the Persistence Unit (PU). The PU serves to register the project’s four persistable entity classes, which are referred to by JPA as managed classes.
RESTful Web Services from Entity Classes
Now that have a SQL Server Data Source and our entity classes, we will create the RESTful web services. Right-click on the project and select ‘New’ -> ‘Other…’ -> ‘Persistence’ -> ‘RESTful Web Services from ‘Entity Classes’. You will see a list of four entity classes we just created, from which to choose. Add all four entity classes.
On the next screen, give a name for Resource Package to store the service classes in; I called mine ‘service’. That’s it; you now have four RESTful web services and the corresponding Enterprise Beans and Façade service classes. The service class sits between the RESTful web service and the entity class.
Click finished. You have successfully created the RESTful web services.
Adding a Primary Key to Entity Classes
If you recall, I mentioned a problem with the two entity classes we created from the database views. To avoid an error when you build and deploy your project to GlassFish, we need to make a small change to the VEmployee.java and VEmployeeDepartment.java entity classes. Entity classes need a unique identifier, a primary key (or, Entity ID) identified. Since these two entity classes are built from database views, as opposed to database tables, they lack a primary key. To fix this, annotate the ‘businessEntityID’ field with ‘@Id’ in each class. This indicates that ‘businessEntityID’ is the primary key (Entity ID) for this class. The field, ‘businessEntityID’, must contain unique values, for this to work properly. NetBeans will make the suggested correction for you, if you allow it.
Test RESTful Web Services Locally in NetBeans
NetBeans provides an easy way to test the RESTful web services, locally. Right-click on the ‘RESTful Web Services’ project folder within the main project, and select ‘Test RESTful Web Services’. Select the first option, ‘Locally Generated Test Client’, in the ‘Configure REST Test Client’ pop-up window.
NetBeans will open a web browser window and displays the RESTful URI (Universal Resource Identifier) for the services in a tree structure. There are four primary URIs, corresponding to the four services. Each primary URI has additional child URIs grouped under them. Are they URIs or URLs? I found this excellent post that does a very good job explaining the difference between the URL (how to get there) and the URI (the resource), which is part of the URL.
Click on the ‘entityclasses.employee’ URI. Choose the HTTP ‘GET()’ request method from the drop-down and click the ‘Test’ button. The service should return a status of ‘200 (OK)’, along with xml output containing information on all the Adventure Works employees. Congratulation, the RESTful web services have just returned data to your browser from the SQL Server Adventure Works database, using the entity classes and data source you created.
Click on the other URIs to familiarize yourself with the various default resources. Test the employee ‘from/to’ URI by inputting two parameters, test the ‘count’ URI, and try changing the MIME type where applicable from XML to JSON and observe the results.

A Single Employee Being Successfully Retrieved from the Adventure Works Database Using Input Parameter
WADL
Note the link in the upper right corner of the above screens, labeled WADL: ‘http://[your_server_path]/JdbcSqlWebSrvTest/webresources/application.wadl’
The WADL (Web Application Description Language) file is the machine-readable XML description of the RESTful web service(s). The WADL file is to RESTful web services, as the WSDL (Web Service Definition Language) file is to non-RESTful, SOA-/SOAP-oriented web services. The WADL provides all the information you need to understand to the various RESTful web service’s resources, and how to call them using their URIs. According to Wikipedia, in the WADL file, ‘the service is described using a set of resource elements. Each resource has param elements to describe the inputs, and method elements which describe the request and response of a resource. The request element specifies how to represent the input, what types are required and any specific HTTP headers that are required. The response describes the representation of the service’s response, as well as any fault information, to deal with errors.’ You can download the WADL file (application.wadl), and review it in an XML-friendly viewer such as Notepad++.
Deploy Project to GlassFish
Now that the RESTful web services are working properly from within NetBeans, we can deploy them to GlassFish. To deploy the project to GlassFish, right-click on the main project icon in the Projects tab and select ‘Clean and Build’. Once the project builds successfully, right-click again and select ‘Deploy’. This will instruct Apache Ant to deploy the project as a .war file to GlassFish, using the project’s default Ant deploy task. The SQL Server data source will also be installed into GlassFish.
Once the deployment is complete, switch to GlassFish and refresh the home page if necessary. Under the ‘Applications’ item on the left-hand navigation menu, you should see a new application with the same name as your project, ‘JdbcSqlWebSrvTest’.
Also, under the ‘JDBC’ -> ‘JDBC Resources’ item, you should see a resource with the same name as the data source you created in NetBeans, ‘AdventureWorks’. Under the ‘JDBC’ -> ‘JDBC Connection Pools’, you should see a pool entitled ‘microsoft_sql_AdventureWorks_aw_devPool’. The JDBC Resource, ‘AdventureWorks’, is linked to this pool. The pool is a ‘javax.sql.DataSource’ resource type, which references the ‘com.microsoft.sqlserver.jdbc.SQLServerDataSource’. This data source is identical to the data source you built in NetBeans.
Test Web Services on GlassFish
To test the RESTful web services from GlassFish, begin by clicking on the ‘JdbcSqlWebSrvTest’ application, under ‘Applications’ menu item. On the Applications page, click on the ‘Launch’ action link. GlassFish open a new web browser window, and presents you with two ‘Web Application Links’, one link is HTTP and the other, HTTPS. Click on the HTTP link. This should display the default index.jsp page’s ‘Hello World!’ message.
To call the service, append the current URL to match the resource URIs you used when testing the services in NetBeans. For example, to display all the employees again like you did in NetBeans, append the current URL, http://%5Byour_server_name%5D:%5Bport%5D/JdbcSqlWebSrvTest/, to include the following:
http://%5Byour_server_name%5D:%5Bport%5D/JdbcSqlWebSrvTest/webresources/entityclasses.employee
This URI should return the same xml content you observed when testing this same URI locally in NetBeans.
As another test, append the URI to also include the Id of a single employee, as follows:
http://%5Byour_server_name%5D:%5Bport%5D/JdbcSqlWebSrvTest/webresources/entityclasses.employee/2
This should cut the amount of data returned from the Adventure Works database to a single employee record.
One last test, remove the number two from the URI and add the word ‘count’, as follows:
http://%5Byour_server_name%5D:%5Bport%5D/JdbcSqlWebSrvTest/webresources/entityclasses.employee/count
This time, you should see a single integer returned to the browser, representing the count of all employees in the database’s employee table.
Conclusion
Congratulations, the Java EE RESTful web services have been successfully deployed to GlassFish. The services are connecting to Adventure Works SQL Server database, through the entity classes and data source, and returning data to your web browser! Next step is to create a RESTful web services client application, to display the data returned by the services and/or to perform CRUD operations on the database.