Create a restful application with AngularJS and Grails

Create a restful application with AngularJS and Grails

In this example application, I will create a simple application which basic CRUD operations, and I reused some AngularJS codes of the AngularJS CakePHP Sample.

I assume you have installed the latest JDK 7 and groovy SDK 2.1.9. And also installed Spring Groovy/Grails Toolsuite or an Eclipse based IDE plus Groovy/Grails plugin.

Create a Grails project

Download a copy of Grails distribution from Grails.org. And extract the files into your local disc.

Add /bin to the system PATH variable.

Create a project using the following command.

grails create-app 

 

 


 

 

Enter the app folder root, try to run the project in the embeded tomcat server.

cd 

 

 
  
 
  
 
grails run-app


 

 

After it is deployed and running, you should see the following like info.

|Running Grails application
|Server running. Browse to http://localhost:8080/angularjs-grails-sample

If you are using Grails 2.3.2, you maybe encounter a critical bug which will cause the above command failed under Windows system.

java.lang.instrument ASSERTION FAILED ***: "!errorOutstanding" with message transform method call failed at ../../../src/share/instrument/JPLISAgent.c line: 844

This bug had been marked as Blocker priority, and should be fixed in the upcoming 2.3.3 soon.

More info please refer to GRAILS-10756.

In the comments of this issue, there is a solution provided to overcome this barrier temporarily.

Add the following dependency in the BuildConfig.groovy.

dependencies {
// specify dependencies here under either 'build', 'compile', 'runtime', 'test' or 'provided' scopes e.g.
// runtime 'mysql:mysql-connector-java:5.1.24'


    build "org.fusesource.jansi:jansi:1.11"
}

Run grails run-app again, you should see the successful info in browser.

grails run-app

Explore the generated codes

By default, the generated project use H2 as database, and Hibernate3 for the persistence layer. The Hibernate 4 support is included Grails 2.3 and also is ready in the generated codes.

In the BuildConfig.groovy file.

runtime ":hibernate:3.6.10.3" // or ":hibernate4:4.1.11.2"

And in the DataSource.groovy file.

cache.region.factory_class = 'net.sf.ehcache.hibernate.EhCacheRegionFactory' // Hibernate 3
//    cache.region.factory_class = 'org.hibernate.cache.ehcache.EhCacheRegionFactory' // Hibernate 4

As you see, if you want to switch to Hibernate4, what is needed to do is only comment the Hibernate 3 facilities, and enable the Hibernate 4 alternatives.

Import this project as a Grails project into your IDE for the next steps.

Code the backend REST API

Create a entity Book.

grails create-domain-class Book

This command will generate Book.groovy and BookSpec.groovy test at the same time.

@Resource(uri='/books')
class Book {

    String title
    String author
    Double price

    static constraints = {
        title blank:false 
        author blank:false   
    }
}

@Resource is a Grails specific annotation, an entity annotated with it will be exposed as REST resource, the basic CRUD operation is ready for use.

URL HTTP Method Description
/books.json GET Get the list of Books
/books.json POST Create a new Book
/books/:id.json GET Get the details of a Book
/books/:id.json PUT Update a Book by id
/books/:id.json DELETE Delete a Book by id

Open BootStrap.groovy file, add some initial data.

def init = { servletContext ->
    new Book(title:"Java Persistence with Hibernate", author:"Gavin King", price:99.00).save()
    new Book(title:"Spring Live", author:"Matt Raible", price:29.00).save() 
}

Open your browser, navigate to http://localhost:8080/angularjs-grails-sample/books.json.

books-json

Grails 2.3 also includes Controller based REST resource producing, which is explained in the official document.

Build the frontend AngularJS pages

I reuse the same app structure and some codes from the AngularJS CakePHP Sample.

Book List

The template code.

 
 
 
 
  
  
  
  

Book List

ID TITLE PRICE AUTHOR
{{e.id}} {{e.title}} {{e.price|currency}} {{e.author}}  

Add Book

The BookListCtrl code.

as.controller('BookListCtrl', function($scope, $rootScope, $http, $location) {
var load = function() {
    console.log('call load()...');
    $http.get($rootScope.appUrl + '/books.json')
        .success(function(data, status, headers, config) {
        $scope.books = data;
        angular.copy($scope.books, $scope.copy);
        });
}

load();

$scope.addBook = function() {
    console.log('call addBook');
    $location.path("/new");
}

$scope.editBook = function(index) {
    console.log('call editBook');
    $location.path('/edit/' + $scope.books[index].id);
}

$scope.delBook = function(index) {
    console.log('call delBook');
    var todel = $scope.books[index];
    $http
        .delete($rootScope.appUrl + '/books/' + todel.id + '.json')
        .success(function(data, status, headers, config) {
        load();
        }).error(function(data, status, headers, config) {
    });
}

});

Add a new Book

The template code.

 
 
 
 
  
  
  
  

New Book

Title
Author
Price
Add Book

The NewBookCtrl code.

as.controller('NewBookCtrl', function($scope, $rootScope, $http, $location) {

$scope.book = {};

$scope.saveBook = function() {
    console.log('call saveBook');
    $http
        .post($rootScope.appUrl + '/books.json', $scope.book)
        .success(function(data, status, headers, config) {
        $location.path('/books');
        }).error(function(data, status, headers, config) {
    });
}
});

Edit a Book

The template code.

 
 
 
 
  
  
  
  

Edit Book({{book.id}})

Title
Author
Price
Update Book

The EditBookCtrl code.

as.controller('EditBookCtrl', function($scope, $rootScope, $http, $routeParams, $location) {

var load = function() {
    console.log('call load()...');
    $http.get($rootScope.appUrl + '/books/' + $routeParams['id'] + '.json')
        .success(function(data, status, headers, config) {
        $scope.book = data;
        angular.copy($scope.book, $scope.copy);
        });
}

load();

$scope.book = {};

$scope.updateBook = function() {
    console.log('call updateBook');
    $http
        .put($rootScope.appUrl + '/books/' + $scope.book.id + '.json',  $scope.book)
        .success(function(data, status, headers, config) {
        $location.path('/books');
        }).error(function(data, status, headers, config) {
    });
}
});

Browse the frontend UI

Open browser, navigate to http://localhost:8080/angularjs-grails-sample/app/index.html#/books.

frontend-ui

Try add a new Book and edit and delete it.

Summary

In this example application, Grails was used to produce the backend REST API, it is also simple and stupid work. Currently, I have not added security feature, maybe add it in future.

The code is hosted on https://github.com/hantsy/angularjs-grails-sample/.

你可能感兴趣的:(spring,AngularJS,REST,grails)