Archive for August, 2011

Setting up Tomcat on Ubuntu

Thursday, August 25th, 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

Monday, August 15th, 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.