authors are vetted experts in their fields and write on topics in which they have demonstrated experience. All of our content is peer reviewed and validated by Toptal experts in the same field.
Denys (MSc) is a seasoned software scalability engineer, project manager, and entrepreneur with 12+ years of experience. Java is his focus.
PREVIOUSLY AT
Choosing the right tool for the right purpose goes a long way, especially when it comes to building modern web applications. A lot of us are familiar with AngularJS and how easy it makes developing robust web application front-ends. Although many will argue against the use of this popular web framework, it certainly has plenty to offer and can be an appropriate choice for a wide array of needs. On the other hand, the components that you use on the back-end will dictate a lot about the web application’s performance, as they have influence on the overall user experience. Play is a high velocity web framework for Java and Scala. It is based on a lightweight, stateless, web-friendly architecture and follows MVC patterns and principles similar to Rails and Django.
In this article, we will take a look at how we can use AngularJS and Play to build a simple blog application with a basic authentication mechanism and the ability to make posts and comments. AngularJS development, with some Twitter Bootstrap goodies, will allow us to power a single-page application experience on top of a Play based REST API back-end.
AngularJS and Play apps will reside in client and server directories accordingly. For now, we shall create the “client” directory.
mkdir -p blogapp/client
To create an AngularJS application skeleton, we will use Yeoman - an amazing scaffolding tool. Installing Yeoman is easy. Using it to scaffold a simple skeletal AngularJS application is probably even easier:
cd blogapp/client
yo angular
Running the second command will be followed by a few options that you need to pick from. For this project, we do not need “Sass (with Compass)”. We will need Boostrap along with the following AngularJS plugins:
At this point, once you finalize your selections, you will start seeing NPM and Bower output on your terminal. When the downloads are complete and the packages have been installed, you will have an AngularJS application skeleton ready to be used.
The official way of creating a new Play application involves the use of the tool Typesafe Activator. Before you can use it, you have to download and install it on your computer. If you are on Mac OS and use Homebrew, you can install this tool with a single line of command:
brew install typesafe-activator
Creating a Play application from command line is super easy:
cd blogapp/
activator new server play-java
cd server/
To import the application in an IDE such as Eclipse or IntelliJ, you need to “eclipsify” or “idealize” your application. To do that, run the following command:
activator
Once you see a new prompt, type either “eclipse” or “idea” and hit enter to prepare the application code for Eclipse or IntelliJ, respectively.
For brevity, we will only cover the process of importing the project to IntelliJ in this article. The process of importing it to Eclipse should be equally simple. To import the project to IntelliJ, start by activating the “Project from existing sources…” option found under “File -> New”. Next, select your build.sbt file and click “OK”. Upon clicking “OK” again on the next dialog, IntelliJ should start importing your Play application as an SBT project.
Typesafe Activator also comes with a graphical user interface, which you can use to create this skeletal application code.
Now that we have imported our Play application into IntelliJ, we should also import our AngularJS application into the workspace. We can import it either as a separate project or as a module to the existing project where Play application resides.
Here, we will import the Angular application as a module. Under the “File” menu, we will select the option “New -> Module From Existing Sources…”. From the dialog, we will choose the “client” directory and click on “OK”. On the next two screens, click on “Next” and “Finish”, respectively.
At this point, it should be possible to start the AngularJS application as a Grunt task from the IDE. Expand your client folder and right click on Gruntfile.js. In the pop-up menu select “Show Grunt Tasks”. A panel labelled “Grunt” will appear with a list of tasks:
To start serving the application, double click on “serve”. This should immediately open your default web browser and point it to a localhost address. You should see a stub AngularJS page with Yeoman’s logo on it.
Next, we need to launch our back-end application server. Before we can proceed, we must address a couple of issues:
To work around both of these issues, all we need to do is use a Grunt proxy so that all AJAX requests to the Play application are proxied. With this, in essence both of these application servers will be available at the same apparent port number.
Let us first change the port number of the Play application server to 9090. To do this, open the “Run/Debug Configurations” window by clicking on “Run -> Edit Configurations”. Next, change the port number in the field “Url To Open”. Click on “OK” to approve this change and close the window. Clicking on the “Run” button should start the dependency resolution process - logs of this process will start appearing.
Once it is done, you can navigate to http://localhost:9090 on your web browser, and in a few seconds you should be able to see your Play application. To configure a Grunt proxy, we first need to install a small Node.js package using NPM:
cd blogapp/client
npm install grunt-connect-proxy --save-dev
Next we need to tweak our Gruntfile.js. In that file, locate the “connect” task, and insert the “proxies” key/value after it:
proxies: [
{
context: '/app', // the context of the data service
host: 'localhost', // wherever the data service is running
port: 9090, // the port that the data service is running on
changeOrigin: true
}
],
Grunt will now proxy all requests to “/app/*” to the back-end Play application. This will save us from having to whitelist every call to the back-end. Furthermore, we also need to tweak our livereload behavior:
livereload: {
options: {
open: true,
middleware: function (connect) {
var middlewares = [];
// Setup the proxy
middlewares.push(require('grunt-connect-proxy/lib/utils').proxyRequest);
// Serve static files
middlewares.push(connect.static('.tmp'));
middlewares.push(connect().use(
'/bower_components',
connect.static('./bower_components')
));
middlewares.push(connect().use(
'/app/styles',
connect.static('./app/styles')
));
middlewares.push(connect.static(appConfig.app));
return middlewares;
}
}
},
Finally, we need to add a new dependency “’configureProxies:server” to the “serve” task:
grunt.registerTask('serve', 'Compile then start a connect web server', function (target) {
if (target === 'dist') {
return grunt.task.run(['build', 'connect:dist:keepalive']);
}
grunt.task.run([
'clean:server',
'wiredep',
'concurrent:server',
'autoprefixer:server',
'configureProxies:server',
'connect:livereload',
'watch'
]);
});
Upon restarting Grunt, you should notice the following lines in your logs indicating that the proxy is running:
Running "autoprefixer:server" (autoprefixer) task
File .tmp/styles/main.css created.
Running "configureProxies:server" (configureProxies) task
Running "connect:livereload" (connect) task
Started connect web server on http://localhost:9000
We will begin by creating a sign-up form for our blog application. This will also allow us to verify that everything is working as it should. We can use Yeoman to create a Sign-up controller and view in AngularJS:
yo angular:controller signup
yo angular:view signup
Next we should update routing of our application to reference this newly created view, and remove the redundant auto-generated “about” controller and view. From within the file “app/scripts/app.js”, remove references to “app/scripts/controllers/about.js” and “app/views/about.html”, leaving it with:
.config(function ($routeProvider) {
$routeProvider
.when('/', {
templateUrl: 'views/main.html',
controller: 'MainCtrl'
})
.when('/signup', {
templateUrl: 'views/signup.html',
controller: 'SignupCtrl'
})
.otherwise({
redirectTo: '/'
});
Similarly, update the “app/index.html” file to remove the redundant links, and add a link to the signup page:
Also, remove the script tag for “about.js”: