Setting up Tomcat on Ubuntu

25
Aug
2011

If you want to run a grails app (or any Java app that requires a servlet container) Tomcat is an excellent choice. You’ll need to do this if you’re hosting your app on a VPS like Linode (highly recommended) or if you’re using AWS and want a little more control than Elastic Beanstalk allows you. I preformed the following steps on an Ubuntu 10.04 server.

Before we install tomcat we should have apache and java installed on the server.

apt-get install sun-java6-jdk
apt-get -y install apache2

We should also create a new user for tomcat to run as

sudo useradd tomcat

In order to easily accomodate multiple instances of tomcat on this machine I don’t use the package manager to install tomcat but instead download it myself. You can find the closest mirror for Tomcat 7 on their site. Here’s the process I use to get my base tomcat install ready:

cd /opt
wget http://apache.mirrors.tds.net/tomcat/tomcat-7/v7.0.14/bin/apache-tomcat-7.0.14.tar.gz
tar -xvf apache-tomcat-7.0.14.tar.gz
rm apache-tomcat-7.0.14.tar.gz
ln -s apache-tomcat-7.0.14/ tomcat

This way if I want to upgrade my tomcat I simply download the new version into /opt and change the link.

Now let’s setup a separate tomcat base folder. This will contain just the folders and settings for the specific instance of tomcat. I keep my tomcat instances on a separate partition called /web so you might have to change the paths here. Here’s the steps I follow to create a new tomcat instance called tomcat-craig.

cd /web
mkdir tomcat-craig
cd tomcat-craig
mkdir conf
mkdir logs
mkdir temp
mkdir webapps
mkdir work
cd ../
cp /opt/tomcat/conf/server.xml ./conf/
cp /opt/tomcat/conf/web.xml ./conf/
sudo chown -R tomcat:tomcat tomcat-craig

Now if you have multiple instances of tomcat you need to make sure the shutdown and startup ports are unique in conf/server.xml. Here’s what my server.xml file looks like:





  
  
  
  
  

  
    
  

  

    
    

    

      

      

      
    
  

Alright now we should create a startup script (/etc/init.d/tomcat-craig) that’s going to use our tomcat base we installed in /opt/tomcat and deploy the wars found in /web/tomcat-craig. I’ve tweaked this excellent startup script to allow for multiple instances. So here’s what my startup script file looks like:

#!/bin/bash
#
# tomcat
#
# chkconfig:
# description:  Start up the Tomcat servlet engine.

# Source function library.
# /etc/init.d/functions

export CATALINA_BASE="/data/www/tomcat-craig"
export CATALINA_HOME="/opt/tomcat"
export CATALINA_OPTS="-Xms192m -Xmx256m"

TOMCAT_USER='tomcat'
SHUTDOWN_WAIT=20

tomcat_pid() {
  echo `ps aux | grep $CATALINA_HOME | grep -v grep | awk '{ print $2 }'`
}

start() {
  pid=$(tomcat_pid)
  if [ -n "$pid" ]
     then
        echo "Tomcat is already running (pid: $pid)"
     else
        echo "Starting Tomcat"
        /bin/su $TOMCAT_USER $CATALINA_HOME/bin/startup.sh
   fi

   return 0
} 

stop() {
 pid=$(tomcat_pid)
  if [ -n "$pid" ]
  then

  echo "Stoping Tomcat"
   /bin/su $TOMCAT_USER $CATALINA_HOME/bin/shutdown.sh  

   echo -n "Waiting for processes to exit ["
   let kwait=$SHUTDOWN_WAIT
    count=0;
    until [ `ps -p $pid | grep -c $pid` = '0' ] || [ $count -gt $kwait ]
    do
      echo -n ".";
      sleep 1
      let count=$count+1;
    done
    echo "Done]"

    if [ $count -gt $kwait ]
    then
      echo "Killing processes ($pid) which didn't stop after $SHUTDOWN_WAIT seconds"
      kill -9 $pid
    fi
  else
    echo "Tomcat is not running"
  fi

  return 0
} 

status() {
  pid=$(tomcat_pid)
  if [ -n "$pid" ]
  then
    echo "Tomcat is running with pid: $pid"
  else
    echo "Tomcat is not running"
  fi
}

case "$1" in
 start)
        start
        ;;
 stop)
        stop
        ;;
 restart)
       stop
       start
       ;;
 status)
       status
       ;;
*)
        echo "Usage: $0 {start|stop|restart|status}"
        exit 1
        ;;
esac
exit 0

The really cool part about this is that it attempts to shutdown tomcat gracefully, waits for a specified period of time and then just kills the process if it’s still hanging there. Also since we set the JVM heap size in the CATALINA_OPTS we can tweak the values in the script and simply restart if we ever need to bump that up. Now that we’ve got the script in place we should use it to startup tomcat

sudo /etc/init.d/tomcat-craig start

Now to have tomcat startup automatically after a server restart do the following:

sudo ln -s /etc/init.d/tomcat-craig S70tomcat-craig

In this example we setup tomcat to run on AJP port 8009 (see the server.xml file above). The last step is to have apache proxy all request to our tomcat instance, so that a request to www.yourdomain.com gets directed to tomcat.

First we install mod-jk

apt-get install libapache2-mod-jk

Next we create the file /etc/apache2/workers.properties that looks something like this:

worker.list=craig-worker
worker.craig-worker.type=ajp13
worker.craig-worker.host=localhost
worker.craig-worker.port=8009

Then the last thing we need to do is configure a site in apache that uses this worker process. Here’s a simplified version of my site found in /etc/apache2/sites-available/default

<VirtualHost *:80>
	ServerName www.craigburke.com
	JKMount /** craig-worker
</VirtualHost>

Now you’re ready to drop your war (grails or otherwise) into your tomcat webapps folder and deploy your app.

Displaying Google+ Posts in Grails

15
Aug
2011

Note The RSS feed source referenced in this article is no longer available.

I wanted to start displaying my public Google+ posts on my site, but unfortunately there’s no direct way to do this. Facebook and Twitter have fairly robust developer APIs, but Google+ still lags behind in this respect. Although by using the very excellent Plus Feed page I can easily get an Atom feed of my Google+ profile page. From there it’s pretty straight forward to use this within a grails app.

Since we’re using a remote source for this data, it makes sense to cache the results and grab them every 15 minutes or so. Our first step is to define the cache object to store our posts in conf/spring/resources.groovy like so

beans = {
  googlePlusCache(org.springframework.cache.ehcache.EhCacheFactoryBean) {
       eternal = true
  }
}

You’ll notice that I defined the cache length to be eternal so if we’re unable to grab new posts for an extended period of time, we’ll still have some older posts to display until we’re able to retrieve new ones again.

Next we define the Service that pulls the google posts and puts them into this cache object.

Here’s what your GooglePlusService.groovy file might look like:

package com.craigburke.craig

import net.sf.ehcache.Element

import java.text.SimpleDateFormat
import java.util.Date

class GooglePlusService {
    static transactional = true

	// Replace this with your Google+ id
	final String googleId = "104612033264119865482"
	final String googlePlusUrl = "http://plusfeed.appspot.com/${googleId}"

	final SimpleDateFormat atomDateFormat = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss'Z'")

	def googlePlusCache
	// This object can be anything, we just need something to uniquely identify the cache item
	Object googlePlusKey = "GOOGLEPLUS"	

	def updateCache = {
		def posts = loadPosts()
		googlePlusCache?.put(new Element(googlePlusKey, posts))
	}

	def getPosts = {
		googlePlusCache?.get(googlePlusKey)?.value
	}

    private def loadPosts = {
		def rssFeed = new XmlParser().parse(googlePlusUrl)

		def items = []
		rssFeed.entry.each {item ->	

			 items << [
				  title: item.title.text(),
				  dateUpdated: atomDateFormat.parse(item.updated.text()),
				  summary: item.summary.text(),
				  link: item.link[0].'@href'.text()
			  ]

		  }

		  items
	}

}

So you see that we have two publicly accessible methods here, the updateCache method and the getPosts method. We can use the getPosts method in our controller but we want to setup the updateCache method to get called automatically every 15 minutes. So first we need to install quartz to set this up as a scheduled job.

grails install-plugin quartz
grails install-quartz-config

Then we create our job that updates our Google cache in the grails-app/jobs folder. Here's what your GooglePlusJob.groovy might look like:

package com.craigburke.craig

class GooglePlusJob {
    def startDelay = 30000
    // Run every 15 minutes
    def timeout = (15 * 60 * 1000)

    def googlePlusService

    def execute() {
		try {
			   googlePlusService.updateCache()
		}
		catch (Exception ex) {
			log.error ex.message
		}
    }
}

Now that everything is all setup all that's left is to grab the posts in one of our Controllers. Here's a simple example:

class HomeController {

	def googlePlusService

    def index = {
	}

	def google = {
		def posts = googlePlusService.getPosts()
		[posts: posts]
	}

}

And the corresponding view for this action might look like this:

<g:each in="${posts}" var="post">
        <h3><a href="${post.link}">${post.title}</a></h3>
        <p>${post.summary}</p>
        <p>Updated: <g:formatDate date="${post.dateUpdated}" format="MMM d, yyyy" /></p>
</g:each>

This is a pretty clear and simple solution until Google releases their developer API to allow us to do this more directly.

Amazon Web Services vs. Linode

27
Jun
2011

It seems that a lot of people are talking about taking their applications to “the cloud” (uggh) and are singing the praises of services like Amazon Web Services. On paper its “pay for what you use” approach would make it seem like a much cheaper option than a VPS hosting option such as Linode where the costs are fixed. This variable model only really makes sense if your usage is truly variable though. If you’re using AWS to deploy a few dedicated servers then you might be paying too much.

Netflix is an oft cited example of a company than uses AWS to build highly scalable services in a way that isn’t cost prohibitive. People see this and assume that since the smart people at Netflix are doing things this way that they should as well. Choosing an architecture for your web application isn’t a one-size-fit-all proposition and even the bright guys at Netflix understand this. Here’s what Adrian Cockcroft had to say about what they chose not to use AWS for:

Encoding movies for streaming, log analysis, production web site and API, most everything that scales with customers and streaming usage. Easier to say what we don’t have there: most internal IT that scales with employee count, legacy stuff, DVD shipping systems, account sign-up and billing systems.

So for the stuff where the demands are pretty constant and growth is predictable, AWS doesn’t make sense for Netflix.

One nice feature of AWS is the ability to quickly and easily add or remove instances from load. So say you need 100 web servers one day and based on demand you’d like the option to drop that down to 2 running web servers the next day; it’s a scenerio like this were you really see the cost benefits of AWS. Realistically though your growth and usage might look a bit more linear than that. It’s really a question of what you’re trying to do and how much your actual demand will fluctuate.

You can use Amazon’s simple monthly calculator to try to estimate your costs but you’ll find that it’s very difficult to do this accurately. There are a lot of variables to take into account many of which you won’t know until you get billed for them. For example, if you want to backup your data, how much are your snapshots going to cost? You won’t know until you see your bill for the month. That can be a real issue if you’re trying to control costs. With AWS you can spend a lot of time reacting to and readjusting your setup based on what your bill ends up looking like.

If you’re deploying a couple dedicated servers than price-wise a VPS like Linode might make more sense. One thing I like is that you can expand your servers as needed in smaller increments. Since I’m typically deploying Grails (Java) applications that use a mySQL database, memory is one of my major concerns. With Linode I can incrementally bump my memory up (512MB -> 768MB -> 1024MB -> 1536MB etc). Whereas with AWS I’m much more limited in terms of how gradually I can bump this up (613MB -> 1.7GB -> 7.5 GB). Those are much larger jumps and I’m likely paying for more than I really need. If I only really need 768MB of memory I’ll still have to pay the 1.7GB price.

So let’s try to do an apples to apples price comparison on a single web/database server. I’ll pick a small instance (1.79 GB) for AWS. Now Linode doesn’t offer a plan with exactly this much memory so I’ll have to average out the 1536MB and a 2048MB plans that it does offer. Now assuming we need 15GB of bandwidth and 30GB of storage here’s what we’re looking at in terms of monthly costs:

Linode: $69.95/mo
AWS: $67.07/mo
Difference: $2.88

So Amazon is slightly cheaper for an instance with comparable memory. Although it should be noted if we go over our 15 GB bandwidth we’re going to get charged. Whereas with Linode we would have approximately 700GB of bandwidth included in the price. So our price with Linode is truly fixed even if we get slashdotted.

Now if we’re willing to commit to having this same size instance for at least a year this price difference is even greater:

Linode: $62.95/mo
AWS: $45.76/mo*
Difference: $17.19
* includes $252.46 upfront fee to deploy a dedicated small instance

So that’s a pretty huge difference in terms of price. Now obviously this is a pretty simple example and you’ll want to make this comparison based on what your needs and predicted growth really are. Amazon does offer a lot of nice services that you’re just not going to find with a VPS like Linode (such as its cloudfront CDN, and database management (RDS) service) but if cost is your primary concern and you’re not afraid to manage these things yourself Amazon might not make sense.

Ultimately I prefer Linode since it allows me to gradually grow and expand my servers as I need to. As with any architectural decision though what makes sense for me might not make sense for you. Ultimately choose what will work and grow with your application and don’t just choose a service because you think it’s what everybody else is doing.

Oracle Stored Procs in Grails

13
May
2011

If you find yourself in a situation where you need to wire up a legacy Oracle stored procedure to a grails controller action, groovy makes this pretty simple. In my example I have a stored procedure with a single parameter that returns results through a reference cursor. Here’s our stored proc:

create or replace procedure GRAILS_EXAMPLE
(
  v_name IN VARCHAR2,
  ref_cur1 IN OUT SYS_REFCURSOR
)
AS
begin

  OPEN ref_cur1 FOR
  SELECT UPPER(v_name) AS UPPER_NAME
  FROM DUAL;

end GRAILS_EXAMPLE;

Obviously this is a pretty contrived example. You’re not likely to call an oracle stored procedure just to transform a string to uppercase (unless you’re a complete moron), but it serves as a simplified version of what you might run into when trying to incorporate existing Oracle procs into your application.

Now, let’s take a look at a controller that calls this proc and renders the value it grabs from the cursor:

import java.sql.*
import groovy.sql.Sql
import oracle.jdbc.driver.OracleTypes

class OracleTestController {
    def dataSource

	def upperName = {
		Connection conn = dataSource.getConnection()
		Sql sql = new Sql(conn)

		String upperName;
		sql.call("BEGIN GRAILS_EXAMPLE(?,?); END;",
                [params.name, Sql.resultSet(OracleTypes.CURSOR)]) {cursorResults ->

				if (cursorResults.next()) {
                     upperName = cursorResults.getAt('UPPER_NAME');
				}

		}

		render upperName
       }

}

So first off we’re injecting the dataSource so we can make our call to the Oracle database we’re using as part of our application. You’ll also see that we can iterate through the reference cursor results by iterating over the cursorResults variable (of type GroovyResultSet) in the sql.call closure. This is how you can grab the individual values you need from your cursor.

If you need to get at a field that isn’t properly aliased in your proc you can still access it by its index. For example the follow would also work in the above controller:

upperName = cursorResults.getAt(0)

See Also: Groovy Database Features

Grails Ajax List with Paging, Sorting and Filtering

23
Jan
2011

Adding to my previous post about creating an ajax list with paging and sorting, I’m now going to extend our user list example to include filtering by the user’s name.

First we need to tweak the controller action so that it doesn’t just return all users. Unless you need to make use of some complicated hql expression, the criteria builder is the easiest way to do this. Here’s what our modified list action will look like now:

def list = {
      def query = {
           if (params.name) {
                    ilike('lastName', '%' + params.name + '%')
            }
            if (params.sort){
                order(params.sort,params.order)
            }
     }

     def criteria = User.createCriteria()
     params.max = Math.min(params.max ? params.int('max') : 20, 100)
     def users = criteria.list(query, max: params.max, offset: params.offset)
     def filters = [name: params.name]

     def model = [userInstanceList: users, userInstanceTotal: users.totalCount, filters: filters]

      if (request.xhr) {
          // ajax request
          render(template: "grid", model: model)
      }
      else {
           model
      }
}

Notice that we’re using the filter param values to build our query and passing these values back to the model inside the filters object. The last part of this action uses one of two views. The first one is the main list page (list.gsp) and second one is for ajax requests which returns just the list part (_grid.gsp) of our page. Here’s what these two views might look like:

list.gsp

<html>
    <head>
        <meta name="layout" content="main" />
        <g:set var="entityName" value="${message(code: 'user.label', default: 'User')}" />
        <title><g:message code="default.list.label" args="[entityName]" /></title>
    </head>
    <body>

	<h2><g:message code="default.list.label" args="[entityName]" /></h2>

	<g:if test="${flash.message}">
	  <div class="message">${flash.message}</div>
	</g:if>
        
        <div class="filters">
          <g:form action="list">

              <p><label for="name">Name</label>
              <g:textField name="name" value="${filters?.name}" /></p>

              <p><g:submitButton name="filter" value="Filter" /></p>

           </g:form>
        </div>
        
        <div id="grid">
          <g:render template="grid" model="model" />
        </div>
        
        <p>
          <g:link action="create"><g:message code="default.new.label" args="[entityName]" /></g:link>
        </p>
    </body>
</html>

This is very similar to what we saw in the last post, we’re just adding the filter HTML elements. Next is the grid view:

_grid.gsp

<table class="ajax">
    <thead>
        <tr>
            <g:sortableColumn property="id" title="Id" params="${filters}" />
            <g:sortableColumn property="isActive" title="Is Active" params="${filters}" />
            <g:sortableColumn property="name" title="Name" params="${filters}" />
       </tr>
    </thead>
    <tbody>
    <g:each in="${userInstanceList}" status="i" var="userInstance">
        <tr class="${(i % 2) == 0 ? 'odd' : 'even'}">
            <td><g:link action="show" id="${userInstance.id}">${fieldValue(bean: userInstance, field: "id")}</g:link></td>
            <td><g:formatBoolean boolean="${userInstance.isActive}" /></td>
            <td>${fieldValue(bean: userInstance, field: "name")}</td>
         </tr>
    </g:each>
    </tbody>
</table>

<div class="pagination">
    <g:paginate total="${userInstanceTotal}" params="${filters}" />
</div>

An important thing to note here is that we’re using our filters object and setting the params property of both the pagination tag and each sortable column. This is so these filter parameters are available between requests so we don’t lose our filter options when we sort or page.

Now our last step is to add some jQuery to turn all paging, sorting and filter requests into ajax requests. All pagination and sorting links will be turned into ajax requests. Also, any input elements you add inside the filter box (div.filters) will automatically do an ajax request and update your table.

$(document).ready(function() {
    setupGridAjax();
    setupFilterAjax();
});

// Turn all sorting and paging links into ajax requests for the grid
function setupGridAjax() {
    $("#grid").find(".paginateButtons a, th.sortable a").live('click', function(event) {
        event.preventDefault();
        var url = $(this).attr('href');

        var grid = $(this).parents("table.ajax");
        $(grid).html($("#spinner").html());

        $.ajax({
            type: 'GET',
            url: url,
            success: function(data) {
                $(grid).fadeOut('fast', function() {$(this).html(data).fadeIn('slow');});
            }
        })
    });
}

// Turn any input changes or form submission within a filter div into an ajax call
function setupFilterAjax() {
    $('div.filters :input').change(function() {
        var filterBox = $(this).parents("div.filters");
 	filterGrid(filterBox);
    });
    $("div.filters form").submit(function() {
	var filterBox = $(this).parents("div.filters");
	filterGrid(filterBox);
        return false;
    });
}

// Reload grid based on selections from the filter
function filterGrid(filterBox) {
     var grid = $(filterBox).next("div.grid");
     $(grid).html($("#spinner").html());

     var form = $(filterBox).find("form");
     var url = $(form).attr("action");
     var data = $(form).serialize();
     $.ajax({
        type: 'POST',
        url: url,
        data: data,
        success: function(data) {
            $(grid).fadeOut('fast', function() {$(this).html(data).fadeIn('slow');});
        }
     });
}

This code assumes that the grid (div.grid) is directly after the filters box (div.filters). You may need to adjust your jQuery if the structure of your page is different.

Hopefully you’ll find this helpful.

Grails Multi-Region Templates

9
Jan
2011

Grails allows you to easily create a view template for all the pages in your application through sitemesh. Making simple HTML tweaks to the default template works if you only have one main content region to your template. Oftentimes though you might want more than this (a content region and a sidebar region for example). Here’s how you can accomplish this.

First modify your main template to look something like this:
main.gsp

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
    "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<title><g:layoutTitle default="Craig Burke" /></title>
</head>
<body>
<div id="frame">

	<h1>Craig Burke</h1>

	<div id="main-content">
	    <g:pageProperty name="page.main-content" />
	    <g:layoutBody />
	</div>

	<div id="side">
	   <g:pageProperty name="page.side" />
	</div>

</div>

</body>
</html>

You’ll notice that in addition to using the pageProperty tag to denote the main content region (page.main-content), I’ve also included the layoutBody tag directly beneath this. This layoutBody tag will make sure that views that are automatically generated by scaffolded controllers will render those pages correctly as well.

Now, for any view where you’d like to use this template your code will look something like this:
index.gsp

  <g:applyLayout name="main">

  <content tag="main-content">
     <h2>Main Content</h2>
     <p>Main content goes here</h2>
  </content>

  <content tag="side">
     <h2>Side Header</h2>
     <p>Side content goes here</p>
  </content>

Pretty slick.

Grails Ajax List with Paging and Sorting

1
Jan
2011

You can easily add ajax to your grails application using standard g tags, but making a list (table) that supports ajax-enabled sorting and paging is a bit different. Here are the steps I took to make this happen.

First I started with my controller action. I’m using single action for the list page as well as the ajax request to update the table data. It’ll look something like this:

def list = {
      params.max = Math.min(params.max ? params.int('max') : 20, 100)
      def model = [userInstanceList: User.list(params), userInstanceTotal: User.count()]

      if (request.xhr) {
          // ajax request
          render(template: "grid", model: model)
      }
      else {
           model
      }
}

A regular request uses the standard list view, but an ajax request is going to use a view template that contains just the HTML for our table along with its pagination links. Here’s an example of what these views might look like:

list.gsp

<html>
    <head>
        <meta name="layout" content="main" />
        <g:set var="entityName" value="${message(code: 'user.label', default: 'User')}" />
        <title><g:message code="default.list.label" args="[entityName]" /></title>
    </head>
    <body>

        <h2><g:message code="default.list.label" args="[entityName]" /></h2>

        <g:if test="${flash.message}">
          <div class="message">${flash.message}</div>
        </g:if>

           <p>
          <g:link class="button create" action="create"><g:message code="default.new.label" args="[entityName]" />
          </g:link>
        </p>

        <div id="grid">
           <g:render template="grid" model="model" />
        </div>

    </body>
</html>

_grid.gsp

<table class="ajax">
    <thead>
        <tr>
            <g:sortableColumn property="id" title="${message(code: 'user.id.label', default: 'Id')}" />
            <g:sortableColumn property="isActive" title="${message(code: 'user.isActive.label', default: 'Is Active')}" />
            <g:sortableColumn property="name" title="${message(code: 'user.name.label', default: 'Name')}" />
       </tr>
    </thead>
    <tbody>
    <g:each in="${userInstanceList}" status="i" var="userInstance">
        <tr class="${(i % 2) == 0 ? 'odd' : 'even'}">
            <td><g:link action="show" id="${userInstance.id}">${fieldValue(bean: userInstance, field: "id")}</g:link></td>
            <td><g:formatBoolean boolean="${userInstance.isActive}" /></td>
            <td>${fieldValue(bean: userInstance, field: "name")}</td>
         </tr>
    </g:each>
    </tbody>
</table>

<div class="pagination">
	<g:paginate total="${userInstanceTotal}" />
</div>

Finally we’ll just need to add a little jQuery to turn these sorting and paging links into ajax requests.

$(document).ready(function() {
    setupGridAjax();
});

// Turn all sorting and paging links into ajax requests for the grid
function setupGridAjax() {
    $("#grid").find(".paginateButtons a, th.sortable a").live('click', function(event) {
        event.preventDefault();
        var url = $(this).attr('href');

        var grid = $(this).parents("table.ajax");
        $(grid).html($("#spinner").html());

        $.ajax({
            type: 'GET',
            url: url,
            success: function(data) {
                $(grid).fadeOut('fast', function() {$(this).html(data).fadeIn('slow');});
            }
        })
    });
}

Overall a pretty simple and elegant solution. If you’re interested in taking this example a bit further with the addition of filtering, see my post Grails Ajax List with Paging, Sorting and Filtering.

GORM Inheritance Mapping

2
Dec
2010

A really nice feature of GORM (and Hibernate) is support for inheritance in domain objects. For example if your application has different types of user accounts with specific properties then you can create distinct domain objects that inherit from a User base class that has all the common properties of a user (email, password, etc). Here’s what it might look like if you had a student user type and an admin user type:

class User {
	String email
	String password
	
	static mapping = {
		 tablePerHierarchy false
	 }
}
class AdminUser extends User {
	// Admin user specific properties
	String adminGroup
}
class Student extends User {
	// Student specific properties
	Date graduationDate
	Float gpa
}

Because of the tablePerHierarchy set in the user mapping this will result in 3 seperate tables (user, admin_user, and student). Omit this if you’d like all the fields to be contained within a single user table.

If you store the user object in session after authentication you can write code like this in your view:

<g:if test="${session.user instanceof Student}">
You are a student with a GPA of ${session.user.gpa}
</g:if>

See also:

Url Mapping in Grails

25
Oct
2010

In grails you have a lot of control over how specfic controller actions are mapped to urls through the UrlMappings.groovy file. The default behavior is for the urls to look something like this:

"/$controller/$action?/$id?"

With the ‘?’ denoting optional parts of the url. So for example the user controller actions will map to urls that look like this

/user/index
/user/show/22

These are pretty reasonable defaults but we might want to override these mappings so we have a little more control over the urls. One reason to do this is so we can map all administrative controller actions to urls that begin with /admin. Then we can easily limit access to these admin controllers easily with a filter.

To change the mapping with our previous user control example we would add the following line to the UrlMappings.groovy file:

"/admin/$controller/$action?/$id?"(controller : "user")

Or alternatively this:

"/admin/$controller/$action?/$id?"{controller = "user"}

Then we’d get urls that looks like the following:

/admin/user/index
/admin/user/show/22

Another good approach is to explicitly define all your public urls in your UrlMapping and then creating a catch all for all other actions that map to /admin/ as shown in the example below

class UrlMappings {
	static mappings = {
		// public pages
		"/"(view:"/index")
		"/auth/$action"(controller: "auth")
		"/portfolio/$action?/$id?"(controller: "portfolio")
		"/project/$action?/$id?"(controller: "project", action: "show")
                
		// protected pages
		"/admin/$controller/$action?/$id?"()
                
		"500"(view:'/error')
	}
}

Grails with jQuery

26
Jun
2010

I’ve been doing some development in Grails (think Ruby on Rails in Java) and while I can appreciate the opinionated nature of the framework I have a differing opinion when it comes to choice of javascript framework. I’m a big fan of jQuery but unfortunately Grails uses Prototype by default. You can easily change this by installing the jquery plugin. To do this run the following commands:

grails install-plugin jquery
grails install-jquery

Then change the javascript reference in your layout (main.gsp):

<g:javascript library="jquery" />

Now you can use jquery in your project without worrying about conflicts between the two frameworks or the unnecessary overhead of including both.