Episode 34
Talk is cheap. Show me the code.
– Linus Torvalds
I’ve talked about recruitment and clean code recently, but I haven’t shown you any (or almost any) actual code for some time. Time to fix this. In November 2014 I’ve written articles about GWT and Vaadin. Now I’d like to present you something similar on AngularJS, which seems to be the most popular JavaScript framework nowadays. And despite being JavaScript, it’s actually pretty good. Let’s take a look.
Overview
Angular is a JavaScript open source front-end, single page, web application framework maintained by Google.
It provides a standard structure for front-end project part, like GWT, much as Spring provide standard structure for back-end part. Its simplification, because you can do the front-end in Spring too via Spring MVC, and the structure for entire project is also partly defined by Maven or other convention over configuration type build tool, but it’s an idea to start with.
It is single page framework, also like GWT, meaning the front-end loads greedily, and later only contacts back-end to get necessary dynamic data, not to render entire html page as in server-side web frameworks like JSP or Vaadin. This makes web page more responsive and user friendly.
Under the Hood
The idea behind Angular is to provide a standard project structure, so you know where to expect things when you approach a new project (Principle of Least Astonishment), and do as much dirty work for the developer as possible. The classic dirty work was tons of boilerplate JavaScript and jQuery code required to manipulate DOM, listen to events, update stuff etc. Angular decouples DOM manipulation from application logic and gives you two-way data binding for free. You will see that in the example soon. Also, Angular follows declarative approach, and provides you with plenty of small components you can easily configure and use on your page to do all the work for you.
From the technical point of view – Angular is a script that interprets html page with Angular directives, performs dependency injection and gets the magic going, so that you don’t have to get your hands dirty.
Hello World
Let’s look at the actual example. I’ve created a simple project, available on my GitHub. Feel free to fork it, clone it and play with it (and give it a star if you like it :). It uses Maven for build and Spring Boot for back-end. Easiest way to run it in Eclipse:
- Clone the repository to your machine
- Import -> Existing Maven Project
- Project -> Run as -> Maven Install
- AngularIntroApplication.java -> Run as -> Java Application
- Check out at http://localhost:8080/AngularIntro/start
It’s that simple. No installing and configuration of external servers, no deployment, just one Fat Jar from Spring Boot. You have all Eclipse and non-Eclipse settings you need to work with the project out of the box, namely:
- Java compiler settings
- Deployment assembly
- Project facets
- Conversion to AngularJS project
- Spring application.properties
It is recommended to install AngularJS plugin for Eclipse for directives syntax highlighting.
Similar to GWT and Vaadin articles, we are going to display customized Hello world message travelling all the way from front-end to back-end and back again. Let’s take a look at what makes the Angular magic work.
Module.js
var angularIntro = angular.module('angularIntro',[]);
Definition of main application module and its dependencies. For now, there are none, so we pass an empty array.
Service.js
angularIntro.factory('service', function($http) { var service = this; return { getGreetings : function(name) { return $http.get('/AngularIntro/getGreetings/'+name); } } });
Basically a single method that performs http get request with single string as a name parameter, and returns a response object to grab onto.
Controller.js
angularIntro.controller('controller', function($scope, service) { $scope.greetings="loading..." service.getGreetings('world').then(function(result) { $scope.greetings = result.data.text; }); });
Controller uses Service to asynchronously fetch data from server and bind it to the $scope, so that View can display the result. At the beginning the greeting variable displays loading message, but after the call returns, the function executes, binding returned data to the variable. Since server is lazy, it will sleep for one second before responding to the request so we can observe the changing value on the View.
View.html
<!DOCTYPE html> <html ng-app="angularIntro"> <head> <meta charset="ISO-8859-1"> <title>Angular Intro</title> <link rel="icon" type="image/png" href="favicon.png"> <script src="http://ajax.googleapis.com/ajax/libs/angularjs/1.4.8/angular.js"></script> <script src="Module.js"></script> <script src="Controller.js"></script> <script src="Service.js"></script> </head> <body ng-controller='controller'> <table style="border: none; width:400px"> <tr> <td> <div style="font-size: 30px;">Angular Intro</div> by <a href="https://howtotrainyourjee.com/author/">Gvaireth</a> <hr> <b>Asynchronous data fetch from server</b> Wait for it: {{greetings}} <hr> <b>Two way data binding</b> Type your name: <input type="text" ng-model="yourName" placeholder="Enter a name here"> Hello {{yourName}}! <hr> Check out my <a href="https://howtotrainyourjee.com/2016/09/08/angular-intro/">Angular Intro</a> article for details.</td> </tr> </table> </body> </html>
Several things are going on here, let’s review all of them:
- There is an ng-app directive that tells Angular that it should wake up, parse the page and perform all its mysterious shenanigans.
- There is a <script> tag pointing to Angular engine script sitting tightly somewhere in the Google cloud. You can download it and keep locally if you are afraid that Google might collapse and close down the servers.
- There are three more <script> tags pointing to our Module, Service and Controller JavaScript definitions.
- There is ng-controller directive, telling Angular that this part of the page is backed by a specific Controller, thus sharing $scope variable with it.
- There is $scope variable greetings surrounded by quite a lot of brackets. Brackets tells Angular that it should be evaluated accordingly. Its starting value is assigned in the Controller, and it will change when the server wakes up and graciously responds.
- Finally, not really related to front-end to back-end conversations, there is a text input field with ng-model tag. It binds the DOM field to $scope variable, so when you start typing, the value will appear to the right. This is a classic example of data binding between two View entities without even bothering the Controller.
Simple, no? Let’s jump to back-end then.
AngularIntroApplication.java
This is the Spring Boot application core class, this episode is about Angular, not Spring, so let’s not get into details. Just know that you have to run this as Java application and Spring Boot will harness the power of its internal Tomcat server to host your application without giving a damn about deployment environment and all that boring stuff. It just needs Java.
MainController.java
Main Java controller maps our main, and so far only, View to context/start url, and responds to Angular Controller with simple object containing greeting line. It’s not exactly the Single Responsibility Principle example, but… Angular Episode here again, we are short on time in the back-end part. Also it’s so trivial that there is no point in creating separate Java service class just for damn string concatenation.
Final Thoughts and Some News
I used to hate JavaScript and everything around it, mostly because I’ve seen a lot of crappy JavaScript code, but after getting to know Angular I toned down a bit. I mean JavaScript is still bad as a language, but Angular helps a lot by providing conventions and eliminating tons of boilerplate code. Also, you can use TypeScript or Dart with Angular instead of pure JavaScript.
This article is meant as a starting point for the series. I’ll try to build something more using the simple example I’ve showed you as a foundation. More Angular features coming soon.
p.s.
If you happen to be in Gdańsk, Poland on September 29, you are welcome to attend my talk on Object-Oriented principles. Its free, you only need to subscribe on the even page.
p.s. 2
I’ve changed the blog domain name from HowToTrainYourJEE.com to HowToTrainYourJava.com. Old one will work too for some time.
kris
April 19, 2017 at 7:57 pm
It looks like the article is cut off in the middle :(
LikeLike
gvaireth
April 19, 2017 at 8:42 pm
Yes, there is a wonderful wordpress feature that sometimes after small edits it randomly cuts off half of this article. I reverted the previous version, thanks for the notification!
LikeLike