A Simpler Angular Client for JEE REST Service

P.Madhanasekaran

Introduction:

Earlier we saw how an Angular client accessed different web services: JEE, ASP Net Web API and Node. You can also recall that the client used “angular-seed”, a skeleton project which has an elaborate directory structure to maintain separation of concerns- different folders and files for different artefacts- modules, controllers, services etc. It has also tools like NPM, Bower to simplify downloading necessary JavaScript libraries and files and also testing tools like Karma. But having seen articles on Backbone and Reactive it was felt that it is better to show that angular can also be used to code a page in a simpler way; that is without using any skeleton and with a smaller number of files created from scratch.   

Angular and Backbone compared:


NetBeans IDE uses Backbone.js for generating a RESTful JavaScript client for a Restful web service. They say Backbone is just a library not a full-fledged framework, as it provides only minimalist services and uses JQuery and Underscore for other features. It is flexible and does not impose any structure and you are free to design your apps in the way you want. If your app has more DOM manipulation it may be suitable as it gives structure to JQuery code.  But you have to write / the IDE generates more JavaScript code. There is no separate controller and the functionality is diffused between view and route.   The advantage of Angular is its two way data-binding with the use of built-in directives/tags. The view is just HTML interspersed with directives- just like a JSP page. The code you have to write is comparatively less. As mentioned above, Backbone view uses JQuery and Underscore libraries. One can choose between a familiar MVC pattern (which is similar to the one used in Spring MVC or ASP Net MVC where ViewModel is used) with Angular; or One can have a flexible pattern to suit his needs with Backbone. We will stick to Angular which we have seen in more than one article. But this time instead of using a skeleton-project like Angular-Seed we will start from the scratch and show coding with Angular is simple.

Core Constructs in Angular

Model is the data received from the server or user input. It has to be stored in the $scope of the controller for the view to access it. $scope is the glue between controller and view. View makes use of directives “ng-model” to store data in $scope and “ng-bind” to read data from the $scope.

View :  It is only HTML interspersed with directives that are nothing but hooks for the artefacts we create in the JavaScript code and for attaching some behaviour to the DOM elements. You can bear in mind that in Backbone view, Underscore is used as a template technology and JQuery for accessing and manipulating the HTML/DOM elements.  

Module: You know that in most of the languages main() is used as an entry point of / to bootstrap the  application. In Angular we have to use a custom module object for the purpose, passing its name to the “ng-app” directive in <html> element of the view.  But Angular provides us the module class from which the module object can be easily instantiated. See how it is done below:

angular.module(‘myApp’,[]);

The constructor of module class takes two arguments. 1) name of the instance to be created 2 ) an array specifying the other modules it depends on (here it is empty-but it cannot be omitted).As mentioned above, the name of the module is used in ng-app directive in <html> element of the page. Now the framework will start executing from this module and it also creates a $rootScope for the module. A module object is a chunk of self-contained code and can use the services of/depend on other modules specified in the constructor. The main module itself can invoke the methods provided by Angular in module class to attach other components like controller, factory, filter etc. Or those objects can be created in separate modules and those modules can be passed as dependencies to the main/bootstrapping module. For a simple app this may not be necessary; but when we use a build tool like Yeoman or start with a skeleton app like “Angular-seed” for our project, we will be doing things in that way only.

Controller
In Angular every view requires a separate controller, the name of which is specified in ng-controller directive. The controller object is instantiated by Angular when it comes across “ng-controller” directive from the controller/constructor function defined by us. Angular also creates a child scope from the $rootscope. In the controller function we should attach properties and methods to this $scope for the view to see it. Hence the controller function should take $scope as one of the arguments. The view can see the model/data stored in $scope through ng-bind directive or expressions. The input data specified with ng-model directive in view is also stored as model in the $scope of the controller. Thus there is a two-way data binding. Whenever the model data in $scope changes, the view updates itself to reflect the change. When the value of the view component changes, the model in $scope is also updated. This two way data binding saves a lot of code and makes it ideal for data-driven web apps/services.

Services:
Angular provides a number of built-in services like $log, $http, $location etc. You can code a custom “services” component within a module by invoking its factory() or service() method. As the controller can have only presentation logic and the business logic can be put in a “services” component. It can contain the repetitive code pertaining to accessing an external web service or database service; as it is a singleton it can be shared by/ invoked by more than one controller.

Directives : We can use directives/hooks  like “ng-app”, “ng-controller” etc. provided by Angular to bind various elements in the html/DOM to the above artefacts we create with Angular in JavaScript .There are directives- “ng-bind”, ”ng-model” which hook data in controller $scope to view elements. There are directives which manipulate DOM elements-“ng-show”, ”ng-hide”  We can also code custom directives.

The above are considered as “Core constructs”, as you cannot code an Angular app without them.

In the earlier article Angular Client for CORs-enabled “Applications”,                                                                                           
You can also have look at the construct $routeProvider( it is contained in the module ‘ngRoute’ in sub-project ‘angular-route’ )  and the directive “ng-view” which are required when the single page is composed from more than one view/template.

Steps in Brief: Before creating a Java EE REST service project,  Create a database in MySQL , say blogDB, and create a table ‘blog’ with the following schema:

id INT AUTO_INCREMENT PRIMARY KEY,
name VARCHAR(50),
content VARCHAR(50
).

Insert a few records. It is easier to use Netbeans or any other GUI tool to add a record rather than mysql console client, as the Id column has AUTO_INCREMENT attribute. In the Services window of the IDE expand Drivers and right click on “MySQL (Connector/JDriver)” and choose “Connect Using” .In the new connection wizard as in Figure-1, change the Database to “blogDB” and give the password (in my case default ‘mysql’) and click “Test Connection”. If you get “Connection succeeded” message, you can click “Finish”. You can also add the mysql driver in Glassfish installation to glassfish/domains/domain1/lib.

Figure-1

Now we can create the sample. In Project window, choose        
Fileà New Project-> Java Web ->Web Application.

Give the Project name and click Next and in the Server and Settings Wizard,     as in Figure-2, ensure that Glassfish Server is selected, as it comes with reference implementations for  EJb3 and Jersey, which are used by our Restful web Service. (Otherwise and use TomEE or Wildfly which are open-source implementations of JEE).We don’t need any other framework. Create a Java Package, say ‘ram’ under ‘Source Packages’. Right click on your Java package and choose New->Entity Class from Database. In the “New Entity Class From Database” Wizard, you can expand “Data Source” and choose New Data Source. In the Create Data Source wizard you can give the JNDI name as ‘jdbc/blogDB’ and in the Database Connection choose blogDB(in Figure-1 the value in JDBC URL).The New Entity Classes from Databases Wizard as in Figure-3 showing in the Available Tables “blog”. If you select it, “Add” button will be enabled. Click on the button. It will appear in the Selected Tables. Click “Next” and then “Finish”. The entity class will be generated by the IDE. Now we can right click on the package “ram” and choose New->RESTful Web Services from Entity classes. In the New RESTful Web Services from Entity Classes wizard in “Available Entity Classes” you can see “ram.blog”. Select it and Add it to “Selected Entity Classes”. Click “Next” and then “Finish”. Now you can see in “ram.services” folder the following files:

1) AbstractFacade.java- general service façade implemented with JPA 
 2) BlogFacadeRest.java – a stateless session implementation of the abstract service facade.
In other words when we generate a RESTful web service from an entity class the IDE generates a stateless session bean and exposes it as a REST service. This is done through use of a few annotations:

  1. @Path: Our RESTful web services needs to be invoked via its Unique Resource Identifier (URI). This URI is specified by the @Path annotation, which we need to use to decorate our RESTful web service resource class. Here we can change the value given to @Path from “ram.blog” to “blogs”.
  2. The annotations are used in this class to map service methods to various HTTP Request methods. The JAX-RS API provides four annotations that are appropriately named @GET, @POST, @PUT, and  @DELETE. We can decorate a method in our web service with one of these annotations. Additionally, each method in our service must produce and/or consume a specific MIME type  The MIME type that is going to be produced needs to be specified with the @Produces annotation; similarly, the MIME type that is going to be consumed is specified with the @Consumes annotation.

 ApplicationtionConfig.java. To deploy Rest service on a server, the service class has to be registered in a class extending ”javax.ws.rs.core.Application”. This Application object can be configured in “web.xml” as a Servlet. Here, as no web.xml is used and the configuration is done through annotations, the annotation @ApplicationPath serves the above purpose. The generated value for the @ApplicationPath can be changed from “webresouces’ to “rs” to enable us to give a simpler url in the browser.

The generated code for “create” and findAll() which we will be using is given below:

Extract from AbstractFacade.java

public void create(T entity) {
getEntityManager().persist(entity);
}
.....
public List<T> findAll() {
javax.persistence.criteria.CriteriaQuery cq = getEntityManager().getCriteriaBuilder().createQuery();
cq.select(cq.from(entityClass));
return getEntityManager().createQuery(cq).getResultList();
}



Extract from BlogRestFacade.java

@POST
@Override
@Consumes({"application/xml", "application/json"})
public void create(Blog entity) {
super.create(entity);
}

......

@GET
@Override
@Produces({"application/xml", "application/json"})
public List<Blog> findAll() {
return super.findAll();
}

You can see that the advantage of exposing an EJB stateless session bean as a REST service includes:

  • Injection capabilities: we can easily inject other EJBs, EntityManagers, If we want we can also inject JMS-resources, DataSources or JCA connectors

The other advantages include:

  • Transactions: all changes made in a REST-call will be automatically and transparently synchronized with the database.
  • Single threading programming model -> the old EJB goodness.
  • Monitoring: an EJB is visible in JMX.
  • Vendor-independence: EJB 3 runs on multiple containers, without any modification (and without any XML in particular :-))

Deploy:  You can deploy the application .When you get the “successfully deployed” message, go to the services window and right click on it and choose “Open in Browser”. The index.html will open in the Browser. If you add “/rs/blogs” to the navigation bar, you may see Figure-3.

Client-File
You can create a HTML –5 project in NetBeans, if you want. But we won’t create a separate project but use the generated “index.html”, when the Java Web project was created. We will use the earlier downloads of angular and angular-resource. Create a folder “js” under Site Root and copy the angular and angular-resource.js files available in your system.

The code for index.html is given below:

index.html

<!DOCTYPE html>
<html ng-app="myApp">  //------1)
<head>
</head>
<body>

      <!-- View -->
<div ng-controller="bgContrl ">    //-----2)
<h1>There are {{blogs.length}} blogs</h1>
<ul>
<li ng-repeat="blog in blogs">  //-----3)
{{blog.name}}  //--------4)
{{blog.content}}
</li>
</ul>
<form ng-submit="save()">  //-----5)
<input type="text" placeholder="Blog name" ng-model="blogName"> </input>
<input type="text" placeholder="Blog content" ng-model="blogContent"> </input>
<span>{{notification}}</span>
<button type="submit">Add</button>
</form>
</div>
<script src ='js/angular.min.js'></script> // ------6)
<script src ='js/angular-resource.min.js'></script>
<script src ='js/app.js'></script>

 </body>
</html>

  • Being specified in <html> with ng-app directive, ‘myApp’ not only becomes the bootstrapping module but also will also manage the whole page.
  • ‘bgContrl’ becomes controller for the <div> and will be instantiated by the framework from the controller() function we will code in a separate js file.
  • ‘ng-repeat’ is similar to ‘For Each’ in other languages.
  • ‘ng-bind’ or Expressions can be used to access data in the $scope of the controller. Here expressions are used to access $scope.blogs.
  • ‘ng-submit’ will ensure that the method $scope.save() is triggered, when the form is submitted.

In <script> element you can specify not only the JavaScript libraries but also your custom js files for the view to use.

JavaScript file: Under “js” create a JavaScript file “app.js”. It can be filed up as under:

app.js

'use strict';

var app = angular.module('myApp', ['ngResource']); //------1)& 2)

app.factory('Blog',function ($resource) {    //----------3)
return $resource('http://localhost:8080/BlogPro/rs/blogs/:id');
}
);
app.controller('bgContrl', ['$scope', 'Blog', function ($scope, Blog) {  //-----4)
$scope.blogs = [];

      Blog.query(function (response) {     //--------5)
$scope.blogs = response;
});
$scope.name = '';
$scope.content = '';
$scope.save = function () {
Blog.save({ name: $scope.blogName, content: $scope.blogContent }, function (response) {  //----------------6)
if (response) {
$scope.notification = 'Blog is saved';
$scope.blogName = '';
$scope.blogContent = '';
} else {
$scope.notification = 'Blog is not saved';
}
})
};

  }]);

  • The value for the name parameter in the module constructor will be used in “ng-app” directive in view, while the return value assigned to “var” will be used to invoke the module instance methods. Some will say we are polluting JavaScript Global Name Space with new a new “var”. They can use any book on Angular for alternative syntax chaining various method calls, without creating a global ‘var’.
  • ”ngResource” is a module in the sub-project “angular-resource”. It is built upon “$http” services provided by Angular and makes use of the “$http” services. By using $resource service we can code with Class, objects and methods in place of promises and other lower level details. If you want you can use “Promises” also.
  • As you can see, you need to pass the full endpoint URL to the $resource()function. Its return value is a $resource class representation and you can invoke the “class” methods in $resource.You can also instantiate this “Blog” like any other class and invoke instance methods available in $resource.
  • To the controller, the factory “Blog” is passed. The method query() is one of the ‘class’ methods available $resource class The function query() issues a GET request to /blogs (notice there is no :id) and it returns an empty array (not a simple object). We have passed a call-back to query(),which is called once the data comes from the server and it populates the empty array with the data received from the server and sets it in $scope model .
  • See above 4.
  • Another class method in $resource class is save(). It serializes the JSON data given to it and sends it as POST body. So the create() method in the REST service, which is annotated with @POST is invoked.

Conclusion:

We have chosen to use the facilities in NetBeans to generate the artefacts necessary for a JEE Restful web service. Java EE 7 with JAX-RS 2.0 brings several useful features, which further simplify development and lead to the creation of even more-sophisticated, but lean, Java SE/EE RESTful applications. EJB 3.1 and JSR-311 (REST) fit perfectly together. You can expose EJB 3.1 directly as REST-facades and gain single-threaded programming model, transactionality etc. The dependency  to the EJB 3.1 API is very low –a few annotations. But injection by the container of other EJB resources like Entity Managers is made possible by it. If REST is all that you need, it is the simplest and leanest approach. Using JAX-RS 2.0 together with other Java EE 7 APIs brings the most convenient (=no configuration) and most productive (=no re-invention) way of exposing objects to remote systems. There are no additional libraries needed - everything is already included in a Java EE 6/7 container (in Glassfish v3 the whole EJB 3.1 container is < 1 MB...) Though IDE can generate RESTful JavaScript client with Backbone, we chose to code the same with Angular, as we have done it earlier and it is easy for a JEE programmer to understand and apply the constructs in Angular while coding. Its two-way data binding also reduces the size of our code.

Figure-2

Figure-3








}