AngularJS with JVx in action

Post to Twitter

Our JVx library has REST support since 2011. It's not only support for using REST libraries, it's a generic solution for action calls and storage access (e.g. database records). This means that your whole business logic is usable via REST with same security restrictions as usual.

In 2011, REST wasn't as popular as today and not supported from soo many different frameworks than today. But now, in 2015, SOAP is legacy and REST is the thing to use. I'm sure you have heard about this modern JavaScript frameworks like AngularJS.

Not sure if it's so successful because it's from Google, but it's often used and developers love working with AngularJS. So we started a simple research project to connect an AngularJS app to our JVx backend application.

AngularJS and JVx is a perfect match because Angular was designed for JS frontends and JVx provides your business logic. Sure, JVx is a full-stack framework and you could create the whole web application, based on vaadinUI, but it's also open for all other UIs.

The most important thing is that everything works out-of-the-box. No additional coding for REST services or authentication, no special knowledge needed. Here's an example service for accessing a customer table (full CRUD support):

public class Customers extends Session
{
        public DBStorage getCustomer() throws Exception
        {
                DBStorage dbsCustomer = (DBStorage)get("customer");
                if (dbsCustomer == null)
                {
                        dbsCustomer = new DBStorage();
                        dbsCustomer.setWritebackTable("customer");
                        dbsCustomer.setDBAccess(getDBAccess());
                        dbsCustomer.open();

                        put("customer", dbsCustomer);
                }
                return dbsCustomer;
        }
}

The class was copied from our DemoERP application (Login as: manager with password: manager). The source code of the whole application is available here.

Yes, there are no more methods like save, update, delete, query, ... The DBStorage encapsulates all calls for you and our generic REST service handles the communication with your business logic.

We have a simple Angular app for you (click on the pencil to edit the record):

This solution is based on AngularJS 1.4.0, Bootstrap 3.3.4 on client-side and JVx with RESTlet on server-side. Here's the JS file:

(function()
{
    var app = angular.module('contactApp', ['ngResource', 'ngRoute']);

    app.config(function($routeProvider)
    {
      $routeProvider.when('/',
      {
        controller:'ListContactsController as contactList',
        templateUrl:'list.html',
        resolve: {contacts: function (Contacts)
                            {
                              return Contacts.fetch();
                            }}
      })
      .when('/edit/:contactId',
      {
        controller:'EditContactController as editContact',
        templateUrl:'edit.html'        
      })
      .otherwise({
      redirectTo:'/'
      });
    });
   
    app.factory('ContactsFactory', ['$resource', function($resource)
    {
       var auth = 'Basic ' + btoa("manager:manager");
       
       return $resource('/demoerp/services/rest/DemoERP/Customers/data/customer/:contactId',
                        null,
                        {'get':    {method:'GET', headers: {'Authorization':auth}},
                         'save':   {method:'POST', headers: {'Authorization':auth}},
                         'update': {method:'PUT', headers: {'Authorization':auth}},
                         'query':  {method:'GET', isArray:true,
                                    headers: {'Authorization':auth}},
                         'delete': {method:'DELETE', headers: {'Authorization':auth}}});
    }]);  

    app.service('Contacts', function($q, $http, ContactsFactory)
    {
      var self = this;
     
      this.fetch = function()
      {
        var deferred = $q.defer();

        return ContactsFactory.query(function(data, status, headers, config)
        {
            self.contacts = data;
           
            deferred.resolve(data);
        },
        function(data, status, headers, config)
        {
            console.log("Error while received data.");
            deferred.reject();
        });
       
        return deferred.promise;
      };
    });

    app.controller('ListContactsController', function(contacts)
    {
        var contactList = this;
        contactList.contacts = contacts;
    });
   
    app.controller('EditContactController', function($location, $routeParams,
                                                     Contacts, ContactsFactory)
    {
        var editContact = this;

        this.fillData = function()
        {
            var idx = Contacts.contacts.reduce(function(cur, val, index)
            {
               if (val.ID == $routeParams.contactId && cur == -1 )
               {
                  return index;
               }
               
               return cur;
            }, -1);
           
            editContact.contact = Contacts.contacts[idx];
           
            editContact.save = function()
            {
                ContactsFactory.update({contactId : $routeParams.contactId},
                                       editContact.contact, function()
                {
                    $location.path('/');
                });
            }
        };
       
        if (typeof Contacts.contacts == 'undefined')
        {
            Contacts.fetch().$promise.then(this.fillData);
        }
        else
        {
            this.fillData();
        }
    });    
})();

It's a useful script because it combines REST with Basic authentication for querying and updating remote database records. Sure, it's not a fat application but this wasn't our intention :)

We have a web application archive for you, if you're interested. Simply use this war together with our DemoERP application and install both applications on e.g. Tomcat application server.

Leave a Reply

Spam protection by WP Captcha-Free