Grails Application with AngularJS: Calling a Rest Service – Part 5

Remember the core principle of MVC? Clean separation of model, control and view? Many MVC frameworks, but there hardly is a single framework that provides a puritanical separation between layers. In some, the view is polluted with server-side syntax (jsp, gsp, asp), its equivalents (taglib) or specialized templates (velocity, freemarker); in some others, the server-side code is interspersed with view layer abstractions (css class, href links) or its equivalent html wrappers. One way to measure good separation is how close the view layer is to html semantics itself.

In this part, let us see how we can combine the power of Angular and simplicity of Grails (mainly because of conventions) to make a better separation of model and view.

Note: For the brevity of this post, the tests are not explained, but is included in the github. Specifically, take a look at how angular-mocks provides a cool $httpBackend object that acts as a http service for unit tests and how to invoke them in the controllerSpecs.js.

Goal: Display a star catalog

Techniques Demonstrated

  1. Retrieve Star catalog from server via ajax rest call (demonstrates Rest, Ajax and Angular’s $http)
  2. Show/Hide star catalog (demonstrates Angular’s implicit scope values)
  3. Display the json model in table format (demonstrates Angular’s ng-repeat directive)
  4. Simple Grails 2.3.x Rest services (demonstrates Grails 2.3.x Rest capabilities)

Ingredients

  • Star domain class, decorated with @Resource annotation to make it Rest-enabled
  • New Angular controller to initiate an http request
  • http.get() ajax call to retrieve data from Star domain class and bind to Angular scope
  • Html table to display scope data

Step: Create Star domain class

cmd> cd c:\projects\angrails
cmd> grails create-domain-class angular.Star

Update the code as:

package angrails
import grails.rest.Resource
@Resource(uri='/starCatalog', formats=['json', 'xml'])
class Star {
String name
 String constellation
 //Bayer Designation
 String bd
 //Distance from Earth in light years
 Integer distance
static constraints = {
 }
}

There are many ways to create restful services in Grails 2.3.x, this is one of the easiest ways – create a domain object and add a @Resource annotation. Works for prototypes, demos and really simple applications. For an advanced method, you may want to use RestController and other methods.

Step: Add some seed data to Bootstrap.groovy

def init = { servletContext ->
 new Star(name: 'Aldebaran', constellation: 'Taurus', bd: 'Alpha Tauri', distance: 65).save(flush:true)
 new Star(name: 'Betelgeuse', constellation: 'Orion', bd: 'Alpha Orionis', distance: 640).save(flush:true)
 new Star(name: 'Regulus', constellation: 'Leo', bd: 'Alpha Leonis', distance: 79).save(flush:true)
 new Star(name: 'Spica', constellation: 'Virgo', bd: 'Alpha Virginis', distance: 260).save(flush:true)
 }
cmd> grails run-app
Goto http://localhost:8080/angrails/starCatalog

You should see json representation of the records from Star domain class. Grails auto-generates Rest url end point /starCatalog.

Step: Create Angular Controller and http.get ajax call

Create another controller (next to the MainCtrl) in angrailsApp.js:

angrailsApp.controller('StarCatalogCtrl',
	function ($scope, $http) {

		$scope.getStarCatalog = function () {
			$http.get('/angrails/starCatalog').
				success(function (data) {
					console.log("success: " + data);
					$scope.starCatalog = data;
				}).error(function (data) {
					console.log("error: " + data);
					$scope.starCatalog = data;
				});
		};

		$scope.getStarCatalog();
	}
);

1. As a convention, I keep Angular controller suffix as “*Ctrl”, while Grails controllers as “*Controller”.
2. Observe that one more parameter is being added to the function – $http. When Angular runs the javascript, it injects a http service object into $http automatically.
3. The $http.get() does the ajax call to the auto-generated Grails Rest endpoint
4. The result data is set to a new variable in scope – “starCatalog”. We will use this variable to display the table data

Step: Display data in table

You can run crazy with your imagination on how to display the data, but a simple step is shown here:

<div ng-controller="StarCatalogCtrl">
	<span><a href="#" ng-click="starCatalogShow = !starCatalogShow">Star Catalog</a></span>
	<div ng-show="starCatalogShow">
		<div>
			<table class="table">
				<tr>
					<th>Common name</th>
					<th>Constellation</th>
					<th>Bayer Designation</th>
					<th>Distance from Earth (light years)</th>
				</tr>
				<tr ng-repeat="star in starCatalog">
					<td>{{star.name}}</td>
					<td>{{star.constellation}}</td>
					<td>{{star.bd}}</td>
					<td>{{star.distance}}</td>
				</tr>
			</table>
		</div>
	</div>
</div>

A few points of interest here:

  • AngularJS Directives (ng-show, ng-click, ng-controller, ng-repeat) do appear to be a cleaner way of extending html behaviour.
  • Directive ng-controller=StarCatalogCtrl specifies which controller provides the scope of the data
  • How an implicit scope variable “starCatalog” hides/shows the table (within the span tag, using the ng-show directive)
  • The ng-repeat Angular directive which is the “forEach (item in itemList)” equivalent to iterate through the starCatalog
  • With this approach, the binding between client and server is a clean http call. This gives you the ability to call any rest service, as long as you can process what you get.

And before we go nuts about AngularJS, observe the syntax of the <a> tag. This type of construct was popular pre-jquery times (<a href=”#”, onclick=”javascript:openLink()”>Click me</a>). With jQuery, there was a big drive towards separation of presentation of data and manipulation of data – using $(id).onClick() syntax. But AngularJS has put the old construct right back into vogue now, but with a twist.

Does this bother you? The pendulum of imperative-declarative programming will swing on forever. Meanwhile, take a look at these articles about Remix and Innovation Recycle bin.

Grails Application with AngularJS: Tests on build server – Part 4

In the previous post, we got karma running on your local systems, as part of grails unit test plans, enabling continual test against Chrome. How do you ensure your unit tests are running in a build server like Jenkins or Bamboo?

PhantomJS is a headless webkit, ie a browser with no browser UI. Make these changes in your karma.conf.js

browsers: ['Chrome', 'PhantomJS'],
plugins: [
 'karma-jasmine',
 'karma-chrome-launcher',
 'karma-phantomjs-launcher',
 'karma-remote-reporter'
 ]

Now run the karma test again:

cmd> cd c:\projects\angrails
cmd> karma start test\javascript\config\karma.conf.js

Warning: Native modules not compiled. XOR performance will be degraded.
Warning: Native modules not compiled. UTF-8 validation disabled.
INFO [karma]: Karma v0.10.9 server started at http://localhost:8001/
INFO [launcher]: Starting browser Chrome
INFO [launcher]: Starting browser PhantomJS
INFO [Chrome 33.0.1750 (Windows 7)]: Connected on socket Tsk76f8qRWk84nVP6jlC
INFO [PhantomJS 1.9.2 (Windows 7)]: Connected on socket oMQSWXNcCW6hNOoH6jlD
PhantomJS 1.9.2 (Windows 7) LOG: ‘angrails manifest load complete.’
PhantomJS 1.9.2 (Windows 7) LOG: ‘calling’
Chrome 33.0.1750 (Windows 7) LOG: ‘angrails manifest load complete.’
Chrome 33.0.1750 (Windows 7) LOG: ‘calling’
Chrome 33.0.1750 (Windows 7): Executed 1 of 1 SUCCESS (0.352 secs / 0.029 secs)
PhantomJS 1.9.2 (Windows 7): Executed 1 of 1 SUCCESS (0.273 secs / 0.018 secs)
TOTAL: 2 SUCCESS

Notice that Karma runs tests against PhantomJS too. You can also add Firefox, IE and test your javascripts against multiple browsers simultaneously.

Additional Notes

But for your build server you need to test just against PhantomJS and not other browsers. One way to do this, is to create a copy of karma.conf.js as karma.local-conf.js. Use the local copy for your local unit tests and the default karma.conf.js for the builds (ie only PhantomJS). This way grails test-app runs against the karma.conf.js in your build server.

Remember you need to install node.js, karma and other components in the build server too.

In Part 5, we shall see how to invoke grails urls/services from AngularJS.

Grails application with AngularJS: Karma with test-app – Part 3

In Part 2, we added karma test runner to our AnGrails application. Its great that you can test your javascripts on the fly locally. What about testing it as part of your grails test-app lifecycle ?

Step: Setup JUnit/Karma integration so that karma can run via grails test-app

Edit BuildConfig.groovy

Add the following line under plugins

test ':karma-test-runner:0.2.0'

See karma-test-runner grails plugin for more information.

Create new file c:/projects/angrails/test/unit/angrails/JavaScriptUnitTestKarmaSuite.java

Add the following text:

package angrails;
import de.is24.util.karmatestrunner.junit.KarmaTestSuiteRunner;
import org.junit.runner.RunWith;
@RunWith(KarmaTestSuiteRunner.class)
@KarmaTestSuiteRunner.KarmaConfigPath("./test/javascript/config/karma.conf.js")
@KarmaTestSuiteRunner.KarmaRemoteServerPort(9876)
public class JavaScriptUnitTestKarmaSuite {
}

Run the test.

cmd> grails test-app

| Compiling 1 source files.....
Karma will be started with process builder args: [karma.cmd, start, C:\projects\angrails\.\test\javascript\config\karma.conf.js]
| Running 1 javascript test...
Starting karma result receiver server on localhost:9889
Warning: Native modules not compiled. XOR performance will be degraded.
INFO [karma]: Karma v0.10.9 server started at http://localhost:8001/
Warning: Native modules not compiled. UTF-8 validation disabled.
INFO [launcher]: Starting browser Chrome
INFO [Chrome 33.0.1750 (Windows 7)]: Connected on socket yX5XSRbnYl_IzwQp7ocG
LOG: 'angrails manifest load complete.'
LOG: 'calling'
Chrome 33.0.1750 (Windows 7): Executed 1 of 1 SUCCESS (0.248 secs / 0.03 secs)

Issues

If one of the following errors occur:

Could not load class in test type ‘javascript’
ERROR [karma]: { [Error: listen EACCES] code: ‘EACCES’, errno: ‘EACCES’, syscall: ‘listen’ }

There is some issue with how the karma is being started via test-app. I found both cmd line grails test-app and invoking via IntelliJ grails cmd window (Alt+G) yield different results. The common problem of both errors seems to be the port number that karma starts on.

Solutions

1. Change the port number in karma.conf.js to 8001 or try another number (above 1024 and available).
2. Remove line of the port number specified in JavaScriptUnitTestKarmaSuite.java: @KarmaTestSuiteRunner.KarmaRemoteServerPort(8001)

Results

With the above settings (ie karma.conf.js:port = 8001 and no port specified in the java code), the test-app works fine in both IntelliJ and command line.

During your test runs, sometimes the port binding is not released when test is shutdown. On *nix systems, you can just use kill <process-id>. For Windows, use PowerShell and do the following:

netstat -o -n -a | findstr "<portnumber>"
stop-process -Id <pid>

In Part 3, we saw how to add karma to grails test-app lifecycle.
In Part 4, lets see how to get karma tests running on your build server.

Grails application with AngularJS: Adding Karma – Part 2

Step: Install karma, karma cli and angular-mocks

cmd> cd c:/projects/angrails
cmd> mkdir test\javascript\config
cmd> mkdir test\javascript\unit
cmd> mkdir test\javascript\lib
cmd> npm install -g karma
cmd> npm install -g karma-cli
cmd> cd c:/projects/angrails/test/javascript/lib

As of this writing, angular-mocks is at v1.2.14 and does not work with angular v1.2.12. When Karma is run, it fails with following error:

Failed to instantiate module ngMock due to Unknown provider: $$rAFProvider

I had to go back to a previous version of angular-mocks v1.2.3. So install v1.2.3:

cmd> bower install angular-mocks#1.2.3

Both angular and angular-mocks will be installed in c:/projects/angrails/test/javascript/lib/bower_components. You can delete the “angular” directory, because we already included it in the grails-app/assets. You would rather not want two angular imports in your project, as you must remember to update both for version changes.

Step: Configure karma

cmd> cd c:/projects/angrails/test/javascript/config
cmd> karma init karma.conf.js

#Answer in the following manner (of course you can choose to answer differently)

Which testing framework do you want to use ?
Press tab to list possible options. Enter to move to the next question.
> jasmine
Do you want to use Require.js ?
This will add Require.js plugin.
Press tab to list possible options. Enter to move to the next question.
> no
Do you want to capture a browser automatically ?
Press tab to list possible options. Enter empty string to move to the next question.
> Chrome
>
What is the location of your source and test files ?
You can use glob patterns, eg. "js/*.js" or "test/**/*Spec.js".
Enter empty string to move to the next question.
> ../../../grails-app/assets/bower_components/jquery/dist/jquery.js
> ../../../grails-app/assets/bower_components/angular/angular.js
> ../../../grails-app/assets/javascripts/**/*.js
> ../../../test/javascript/lib/bower_components/angular-mocks/angular-mocks.js
> ../../../test/javascript/unit/**/*.js
>
Should any of the files included by the previous patterns be excluded ?
You can use glob patterns, eg. "**/*.swp".
Enter empty string to move to the next question.
>
Do you want Karma to watch all the files and run the tests on change ?
Press tab to list possible options.
> yes
Config file generated at "c:\projects\angrails\test\javascript\config\karma.conf.js".

Optionally, you can edit the karma.conf.js and set the basepath to: basePath: ‘./../../../’, and remove the ../../../ from the file includes.

Step: Start Karma

cmd> karma start karma.conf.js

You should see a chrome browser started pointing to 9876 port. There is nothing to test yet. Keep the Karma running.

Step: Add Angular code

Add a test: test/javascript/unit/controllersSpec.js

'use strict';
describe('angrailsTest', function () {
beforeEach(module('angrailsApp'));
var scope, mainCtrl;
beforeEach(inject(function ($compile, $rootScope) {
 scope = $rootScope.$new();
 }));
describe('angrailsMainCtrl', function () {
beforeEach(inject(function ($controller) {
 mainCtrl = $controller("MainCtrl", {$scope: scope});
 }));
it("should set hello text", function () {
 var helloText = 'Hello Angular Demo!';
 expect(scope.helloText).toEqual(helloText);
 });
})
});

Angular Application module: grails-app/assets/javascripts/angrailsApp.js

var angrailsApp = angular.module('angrailsApp', []);
angrailsApp.controller('MainCtrl', ['$scope',
 function ($scope) {
 $scope.helloText = 'Hello Angrails Demo!';
 }
])

Application dependencies: grails-app/assets/javascripts/application.js

Add line between angular and views:

//= require angular/angular
//= require angrailsApp
//= require_tree views

When you modify the js files, keep watching the karma window, it will run tests automatically. Currently it must have failed, because our test is incorrect:

In controllersSpec.js, change

var helloText = 'Hello Angular Demo!';

to

var helloText = 'Hello Angrails Demo!';

and watch the Karma window, it should pass.

In Part 2, We added Karma to our application. Karma can test javascripts independently. What if we want to test it as part of our grails test lifecycle?

In Part 3, lets ensure that Karma is part of the grails application test lifecycle.

Grails application with AngularJS: Setup – Part 1

There are several posts about setting up AngularJS, but a few specific to Grails environment. If you have been a Grails developer and want to explore using AngularJS framework for front-end, here is step by step guide to get started. Grails and AngularJS are both full-fledged mvc frameworks on their own. Using the positives from both can be a killer comination to build fast and modern dynamic web applications.

Notes:

  • Instructions are for Windows OS
  • Directories only for reference
  • All versions as of writing this article. Substitute with newer versions as appropriate.
  • Pre-installed: JDK 1.7.0_51: C:\Programs\Java\jdk_1.7.0_51
  • Pre-installed: Grails 2.3.6: C:\Programs\Grails\grails-2.3.6

This setup does not use the angularjs-resources Grails plugin. It replaces the resources plugin entirely with asset-pipeline plugin and uses npm/bower to manage javascript dependencies directly. AngularJS does work with grails resources plugin too, but I feel it becomes difficult to maintain when adding more angular modules.

Step: Install pre-req software

Install Node.js -> http://nodejs.org/ to C:\Programs\nodejs
Install Git -> http://git-scm.com/downloads

Ensure PATH contains: c:\programs\nodejs; c:\programs\git\cmd

Open new command prompt (new, because your PATH would have been modified)

npm install -g npm
npm install -g bower

Step: Create new Grails app

cmd> cd c:\projects
cmd> grails create-app angrails
#All commands executed from the following directory, unless specified
cmd> cd angrails

Step: Switch from resources plugin to using asset-pipeline plugin

AngularJS will work with resources plugin too, but when you start installing many javascript components, the ApplicationResources can become clumsy. Asset pipeline is the new Grails plugin (based on Rails asset pipeline) that makes it easier to manage static resources, javascript, sass/less etc.

Edit BuildConfig.groovy

delete: resources, zipped-resources, cached-resources, yui-minify-resources lines

add: compile “:asset-pipeline:1.6.1″

cmd> grails refresh-dependencies

That will create grails-app/assets/* sub-directories

cmd> move web-app\css\* grails-app\assets\stylesheets
cmd> move web-app\js\* grails-app\assets\javascripts
cmd> move web-app\images\* grails-app\assets\images
cmd> move web-app\images\skin grails-app\assets\images
cmd> rmdir web-app\css web-app\js web-app\images

Step: Fix main.gsp to use asset-pipeline

Edit main.gsp

Comment/Delete following lines:

<link rel="shortcut icon" href="${resource(dir: 'images', file: 'favicon.ico')}" type="image/x-icon">
<link rel="apple-touch-icon" href="${resource(dir: 'images', file: 'apple-touch-icon.png')}">
<link rel="apple-touch-icon" sizes="114x114" href="${resource(dir: 'images', file: 'apple-touch-icon-retina.png')}">
<link rel="stylesheet" href="${resource(dir: 'css', file: 'main.css')}" type="text/css">
<link rel="stylesheet" href="${resource(dir: 'css', file: 'mobile.css')}" type="text/css">
<g:javascript library="application"/>
<r:layoutResources/> (2 places)

Add the following lines above <g:layoutHead/>

<asset:javascript src="application.js"/>
<asset:stylesheet href="main.css"/>
<asset:link rel="shortcut icon" href="favicon.ico" type="image/x-icon"/>

Any other ${resources} images, replace with <asset:image src=”– filename –”/>

Delete ApplicationResources.groovy

Step: Add jQuery dependency

cmd> cd c:/projects/angrails/grails-app/assets
cmd> bower install jquery
cmd> bower install angular

That will create bower_components directory and the js libraries (inside grails-app/assets/bower_components)

Step: Add Javascript dependencies

Edit grails-app/assets/javascripts/application.js

Replace the content with:

//= require jquery/dist/jquery
//= require angular/angular
//= require_tree views
//= require_self
console.log("angrails manifest load complete.");

Note that when using //=require you do not specify the bower_components directory. Asset-pipeline plugin skips the first directory after grails-app/assets.

cmd> grails run-app
Goto http://localhost:8080/angrails

End of Part 1: We have installed AngularJS and asset-pipeline for a Grails app.

In Part 2, we shall install Karma Test Runner for testing AngularJS javascripts.

Grails plugin dependency issues

Ran into a few problems with Grails plugin dependencies here are some solutions.

Applies to Stack

Grails 2.3.0, cache:1.1.1, asset-pipeline:1.0.4, mongodb:1.3.0, shiro:1.2.0, hibernate:3.6.10.1, database-migration:1.3.5

Problem 1:

Conditions: Using cache:1.1.1

grails compile fails with error:

| Error Compilation error: startup failed:
Compile error during compilation with javac.
C:\Grails\MyProject\target\work\plugins\cache-1.1.1\src\java\grails\plugin\cache\web\filter\PageFragmentCachingFilter.java:46: error: package net.sf.ehcache.constructs.blocking does not exist
import net.sf.ehcache.constructs.blocking.LockTimeoutException;

Solution 1:

Add the following in the BuildConfig dependencies section (if mongodb is used by a plugin, this should go into plugin’s BuildConfig dependencies)

dependencies {
 compile "net.sf.ehcache:ehcache-core:2.4.6"
 }</code>


Verification 1:

Delete target/* from any plugin and project sources
grails compile

Problem 2:

Conditions: You are using shiro:1.2.0 + Servlet API v3.0. Shiro includes servelt-api 2.5 by default and is causing a conflict.

grails compile fails with error:

C:\Grails\MyProject\target\work\plugins\cache-1.1.1\src\java\grails\plugin\cache\web\GenericResponseWrapper.java:154: error: method does not override or implement a method from a supertype
@Override
^
C:\Grails\MyProject\target\work\plugins\cache-1.1.1\src\java\grails\plugin\cache\web\filter\PageFragmentCachingFilter.java:398: error: cannot find symbol
contentType = response.getContentType();

^
Solution 2:

To eliminate this problem, exclude servlet-api from Shiro for shiro-cas:

dependencies {
compile("org.apache.shiro:shiro-cas:1.2.2") {
excludes "servlet-api"
}
}

Verification 2:

Delete target/*
grails compile

Problem 3:

Conditions: You are using shiro:1.2.0 + mongodb:1.0.3 - hibernate:3.6.10.1 - database-migration:1.3.5 (ie hibernate and database-migration are not included)

grails compile fails with error:

| Error Fatal error during compilation org.codehaus.groovy.control.MultipleCompilationErrorsException: startup failed:
C:\Grails\MyProject\target\work\plugins\hibernate-2.2.4\.\HibernateGrailsPlugin.groovy: 18: unable to resolve class org.codehaus.groovy.grails.plugins.orm.hibernate.HibernatePluginSupport
@ line 18, column 1.
import org.codehaus.groovy.grails.plugins.orm.hibernate.HibernatePluginSupport
^

IntelliJ IDEA 13 may also throw a "IDEA hook: Grails not found!" error.

This is due to a dependency of shiro on hibernate-2.2.4 api.

Soution 3:

runtime (":shiro:1.2.0") {
excludes "hibernate"
}

Verification 3:

Delete target/*
grails compile

One way to sort out such errors is to run the grails dependency-report and look for the jar file which causes the problem. Trace back from jar file to the actual included plugin or dependency and add the excludes in either dependencies section or plugins section appropriately.

The GAME Stack

The GAME stack

Alright, you know what LAMP stack is. You may have also heard about the MEAN stack (Mongo, Express, Angular, Node), that is gaining popularity. So many stacks are popping up and I wonder when we would get a stack overflow of stack names. The advantage of MEAN is, everything is javascript and your team needs to know only one language throughout. Good and Bad, I guess. Good because your team skillset is only one language. Bad because your team skillset may have just one language. Future of software is unpredictable and if/when Javascript goes out of favor, you and your team will be considered legacy.

While all-javascript is attractive, there is already a solid base built on the server side stacks, especially around security. I’m proposing a new stack name – GAME – Grails, AngularJS, MongoDB as all of them are equally impressive. Of course, nothing novel about this and this stack is already being used by many, but not many know that the ‘E’ stands for ‘Eh?’ pronounced with a Scottish accent. So when you use this stack, you get to tell your friends – “We use GAME in our company – Grails, AngularJS, MongoDB, Eh?” (perhaps with a quirkly smile).

Though Grails and AngularJS seem to compete on what they do, I prefer to keep some things on server-side, because Grails is a joy to code with configuration and business logic. The nice thing is AngularJS syntax is very much Grails-y. There are a few good online examples of using these two, but I didnt find a step-by-step quick start guide anywhere. So if you are planning to introduce AngularJS into your Grails projects, try these steps:

Notes:

1. It is not really required to use angularjs grails plugin. You can directly use your preferred angular.js version
2. If you are using IntelliJ, enable the AngularJS plugin. This gives you intellisense for angularjs directives
3. You can use angularjs with both resources and asset-pipeline plugin. I am starting to prefer asset-pipeline plugin, because all dependencies are kept within js itself (instead of ApplicationResources.groovy). The asset-pipeline gsps are a bit simpler to use than the resources.

Step 1: BuildConfig.groovy

plugins {
runtime “:asset-pipeline:1.0.4″
}

Step 2: Asset-pipeline directories

grails refresh-dependencies will create grails-app/assets/* directories. Move your existing resources from web-app into this directory appropriately.

Step 3: Add angularjs library and application.js

grails-app/assets/images/*
grails-app/assets/javascripts/angular/angular-1.0.8.js //AngularJS library
grails-app/assets/javascripts/my-angular.js //My AngularJS code (controllers, unit test etc)
grails-app/assets/javascripts/application.js //Application.js that wires all JS libraries

application.js

In asset-pipeline, all dependencies can be declared within the js itself. Here is the application.js (the root of js files):

//=require jquery
//=require angular/angular-1.0.8.js
//=require angular/my-angular.js
//=require_tree views
//=require_self

Step 4: Update main.gsp layout page

The layouts, main.gsp is slightly different using asset tags.

<head>
… meta tags …
<asset:link rel=”shortcut-icon” href=”favicon.ico” type=”image/x-icon”/>
<asset:link rel=”apple-touch-icon” href=”apple-touch-icon.png” />
<asset:link rel=”apple-touch-icon” href=”apple-touch-icon.png” sizes=”114×114″/>

<asset:javascript src=”application.js” />
<asset:stylesheet href=”main.css”/>
<asset:stylesheet href=”mobile.css” />
<g:layoutHead/>
</head>

<div id=”grailsLogo” role=”banner” style=”float: left”>
<asset:image src=”mylogo.jpg” alt=”MyLogo” height=”100″ />
%{–<img src=”${resource(dir: ‘images’, file: ‘grails_logo.jpg’)}” alt=”grails-logo” height=”100″/>–}%
</div>

Step 5: Add sample angularjs code:

grails-app/assets/javascripts/my-angular.js

function HomeController($scope) {
$scope.myDate = new Date();
}

grails-app/views/angularsample/index.gsp

<%@ page contentType=”text/html;charset=UTF-8″ %>
<html ng-app>
<head>
<meta name=”layout” content=”main”>
<title></title>
</head>

<body>
<div id=”page-body” role=”main”>
<div ng-controller=”HomeController” >
{{myDate}}
</div>
</body>
</html>

Step 6: Verify

Goto http://localhost:8080/app/angularsample/index

Validating Map values using Grails constraints

In a recent Grails project, we came up with a requirement where we could collect arbitrary input data from a form and validate them in the Grails controller.

There are several validation techniques and initially I was thinking of creating various standard validation closures (like isEmpty, isNull, hasLength etc) on the map key name and execute them at runtime. By my coworker proposed an idea to use the Grails constraints directly instead of standard validation closures. I liked the idea, because a) it allows reuse of existing constraints and validate it the “Grails-way” and b) It is trivial to create custom constraints.

CommandObject

@Validateable
class DynamicFields {
  Map responses = [:]
}

Controller

class DynamicFieldsController {
def submit() {
  DynamicFields fields = new DynamicFields()
  fields.responses.putAll(params)

  //for illustration, imagine the fields.responses has a key called "firstName" whose value has to be validated
  ConstrainedProperty constrainedProperty = new ConstrainedProperty(DynamicFields, "firstName", String)
  constrainedProperty.applyConstraint("blank", false)
  constrainedProperty.validate(fields, params.firstName, fields.getErrors()) //getErrors() is available  because of @Validateable
  fields.errors.each { println it }
}
}

Problem

The (pseudo) execution stack now is validate() -> processValidate() -> AbstractConstraint.rejectValue -> BeanWrapperImpl.getPropertyValue() -> java.beans.PropertyDescriptor.getMethod() that throws a “NotReadablePropertyException”.

Obviously the java beans framework cannot find the firstName property. I tried several variations on the DynamicFields class: propertyMissing(), @Override getProperty(), setProperty(), metaclass.getProperty(), even AbstractConstraint.metaClass.rejectValue() – none of them were respected by the java beans. Well obviously, because the Grails magic does all this via GroovyObjectSupport, but the underlying Java Beans framework does not know about it.

Solution

Remember that Errors and BindingResult are interfaces and the concrete implementation is provided by AbstractBindingResult and its subclasses. By default Spring uses the BeanPropertyBindingResult for tying back the validation error to the field. From the hierarchy of these classes, I saw the MapBindingResult class, which binds the validation to a target map. Just what I wanted.

So I changed the controller to

DynamicFields fields = new DynamicFields()
fields.responses.putAll(params)
fields.setErrors(new MapBindingResult(fields.responses, DynamicFields.class.getName()))

This cleanly tied the errors to the individual map keys.

Displaying the errors also is trivial:

<g:hasErrors bean="${fields?.errors}">
<g:eachError><p>${it}</p></g:EachError>
</g:hasErrors/>

A cleaner solution is probably to create an AST that ensures that the setErrors (MapBindingResult) is done always or a better way of injecting MapBindingResult into Errors.

In fact, even without Map responses object, using Groovy’s Expando, one can directly store values in the DynamicFields class and validate them. Power of dynamic programming – ensuring valid data is collected even for “non-existent” attributes !

IntelliJ Idea 13 EAP and Grails 2.3.0

While the news is that IntelliJ 12.x will support Grails 2.3.0 sooner or later, right now the best bet is to use IDEA 13 EAP release. But the release has a few issues, which is good to be aware of while developing for Grails 2.3.0.

Problem 1: Migrating to Grails 2.3.0

While the built-in upgrade does a decent job of setting the Idea settings, you must ensure the following:

1. Add this to BuildConfig.groovy

grails.project.dependency.resolver = “maven” // or ivy

2. Set the tomcat version in plugins section

build “:tomcat:7.0.42″

3. Set the correct hibernate version in plugins section
runtime “:hibernate:3.6.10.1″ // or “:hibernate4:4.1.11.1″

These do not rely on $grailsVersion anymore. If you are using scaffolding, you have to specify that as a dependency too:

compile “:scaffolding:2.0.0″

Problem 2: Running in Debug Mode

1. Edit Configurations, set command line to: run-app -debug
2. Goto BuildConfig.groovy and comment out the run portion of jvm settings:
//run: [maxMemory: 768, minMemory: 64, debug: false, maxPerm: 256, forkReserve:false],
3. Click on debug icon

Problem 3: Tomcat does not start and ends up with error

java.util.concurrent.ExecutionException: org.apache.catalina.LifecycleException: Failed to start component [StandardEngine[Tomcat].StandardHost[localhost].StandardContext[/project1]]

This one was a real tough nut to crack, because of an accidental mistake. Tomcat refused to start, and I didnt know what setting I had really changed.

It turns out that in the Edit Configurations… window, I had accidentally turned on the “Add –classpath” checkbox. This added the maven related servlet-2.5 api classes, that gave the above error. I was hunting the wrong path for quite sometime (switching between 2.5 and 3.0, clean-all, refresh-dependencies) and several other guesses. Finally when I turned off this checkbox, the application started fine.

The lite at the end of webservice tunnels

In the last post, I alluded to how shifting complexity from one area to another can actually improve perceived simplicity. Here is a concrete example of how we got rid of scores of wsdl-client generated jaxb classes and brought in a fresh wave of simplicity to our Grails applications.

Problem

One or more of our Grails application uses several our own plugins and each of them talk to several web services that share a lot of xsd schemas, the java client generation of which end up proliferating duplicated jaxb classes in each of our plugins and also in the applications which use them, thus resulting in multiple classpath conflicts.

Also we dont like the date conversions from Date to Calendar to GregorianCalendar to XmlGregorianCalendar or other conversions from Byte to Int to Shorts. Also jaxb does some non-intuitive magic with some of the xsd:any types in the schemas. If xsd schemas want strict type checking, fine. We from the “def” world, just look everything as plain data. And finally the jaxb classes look ugly.

Solution

With a combination of groovy-wslite, grails wslite plugin and MarkupBuilder and Config, the code become pretty straight-forward, almost.

From the grails command prompt, run install-plugin wslite

def grailsApplication

public def amazonBookListMania() {
  WsliteConnector.instance.withSoap(serviceURL: grailsApplication.config.amazonBookListManiaServiceUrl) {
    def soapResponse = send(SOAPAction: grailsApplication.config.amazonBookListManiaSoapAction) {
      //Get the namespaces, which is a simple Groovy map
      //['xmlns:amz':'http://www.amazon.com/ListMania']
      envelopeAttributes grailsApplication.config.amazonBookListManiaNamespaces
      body {
        //Get the raw xml and slap it into soap body
        mkp.yieldUnescaped(createXmlRequest())
      }
    }
    //Wslite automatically xmlslurps the result and gives you the closure
    def response = soapResponse.body.bookListManiaResponseRoot
    println response.Items.count()
  }
}

The “withSoap” is a DSL, that is supposed to be injected automatically into controllers, but on other classes it didnt seem to work. I tried using WsliteEnhancer, but that didnt help either. So the direct call to withSoap using WsliteConnector singleton.

The example shows all params injected from grailsApplication config, to allow webservice urls for different environments.

The interesting aspect is the envelopeAttributes, which is a map of namespaces. Since we are not using generated client classes, whcih does the work for us, the namespace prefixes must be specified somehow in the xml itself as part of soap request. Adding namespaces to envelopeAttributes will append the namespaces to the soap-env tag. No need to include the namespace for soap-env itself. The wslite plugin does that.

public String createXmlRequest() {
    def writer = new StringWriter()
    def builder = new MarkupBuilder(writer)
    builder.'amz:ListMania' {
      //tag attributes
      'amz:credentials'(username: 'vasya10', password: 'yeahright')
      //tag value
      'amz:dateRequested'(new SimpleDateFormat('yyyy/MM/dd').format(new Date()))
    }
    //Returns <amz:ListMania><amz:credentials username='vasya10' password='yeahright'></amz:credentials><amz:dateRequested>2013/01/01</amz:dateRequested></amz:ListMania>
    return writer.toString()
}

With the complexity of creating the xml shifted into MarkupBuilder, creating soap requests become trivial, even more so with the withSoap DSL.

Wsdl import generated classes
Pros
No need to worry about namespaces
Set and Get of values use Java-like syntax
Setting values does not matter as xml marshalling happens at a later time than setting the values
Setting tag attribute or tag value is no different (ie code doesn’t care)

Cons
Every minor change in wsdl forces wsdl client generation
Duplicated client generated classes could cause classpath conflicts
The hierarchy of the xml elements is not apparent in the code, the only way to know the hierarchy is to look at the xml samples

WSLite + MarkupBuilder
Pros
No confusion about which client to use: there are scores of them and each have some unique issue (jax-ws, jax-b, cxf and so on)
No wsdl import client generated sources and jars
No crazy xerces, xalan and other marshalling runtime errors, especially if deploying to different app servers (tomcat, weblogic etc)
If there are trivial changes to elements (saying adding a new optional element), will still work without changing client code (if that element is not used)
Creation of xml is very straight-forward
Code documents the hierarchy of the xml!
Response returns XmlSlurped data, so dot-notation can directly be applied on the objects

Cons
Code must be namespace-prefix aware
Must know tag attributes and tag values to create the xml correctly (this must be a Pro)
Code must generate xml in the same sequence of elements; blocks of elements can still be called out-of-order, but the final xml body must be created in a sequence
Unvalidated namespace prefixes increases testing time
Extra testing time for un-type-checked variables

Compared to our previous jaxb code (with ObjectFactory, creation of new Objects etc.), the code is now 40% smaller, and additionally got rid of the client sources too.

Follow

Get every new post delivered to your Inbox.

Join 129 other followers