Saturday, 27 March 2010

License Project in NetBeans

I resurrected an old project last week, with the intention of sharing some of the code. Specifically I wanted to add a GPL license to the project but it's not uncommon to want to add some sort of standard header to source code files. Achieving that with NetBeans 6.8 threw up some interesting aspects of NetBeans itself, its interaction with Maven and a nice trick with Bash scripting ...

Licenses in NetBeans

I think Templates in NetBeans are fairly well known and commonly modified. Perhaps less well known is the default inclusion of a license statement which can be configured on a project by project basis.

If you go to Tools -> Templates and open the template for a Java class file, you'll find this little section at the top:

<#assign licenseFirst = "/*">
<#assign licensePrefix = " * ">
<#assign licenseLast = " */">
<#include "../Licenses/license-${project.license}.txt">

Out of the box, the project.license variable is set to a default license, which produces this, which you will have no doubt seen if you use NetBeans:

/* 
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */

If you are using a standard NetBeans project, by editing the nbproject/project.properties file in your NetBeans project directory, you can modify the license applied to each new file. (In the rest of this post, where I'm using shell commands, I'm going to assume you are working in your project directory).

Edit nbproject/project.properties with your favourite text editor, or a quick way if you are using a Unix is:

$ echo "project.license=gpl30" >> nbproject/project.properties

The variable is set to gpl30 in this case for GPL 3.0. The other licenses are listed under Tools -> Templates -> Licenses. Note that NetBeans automatically prefixes "license-" and appends ".txt", so just specify the middle part.

Now when you create new source files, NetBeans will, where appropriate, add the license comment that you specified.

If you aren't quite happy with the format, you can edit the license template itself. This can be used in conjunction with the User.properties template in Tools -> Templates -> User Configuration Properties.

User.properties
user=Your Full Name
email=yourEmail@yourDomain
company=Your Company
license-gpl30
<#if licenseFirst??>
${licenseFirst}

${licensePrefix} Copyright (c) ${company} ${date?date?string("yyyy")}
${licensePrefix}
${licensePrefix} This program is free software: you can redistribute it and/or modify
...
${licensePrefix} Please refer any queries to ${user} <${email}>

But what if you are using Maven? (If not, why not?) In this case, there is no nbproject/project.properties file. The solution is actually quite simple. Edit your POM and add a new properties section, or extend an existing one, with this hint:

pom.xml
...
<properties>
    <netbeans.hint.license>gpl30</netbeans.hint.license>
</properties>
...

Obviously it would be nice if you could configure these licenses into your project using NetBeans project properties, but for now, you have to edit nbproject/project.properties or pom.xml.

Adding License Header to Existing Code using Bash

N.B. I'm using Ubuntu, other Unix variants that don't use Bash or Bourne shell deriviatives will be slightly different.

My first thought was to use a combination of find and cat to prepend the license, stored in a text file, to all the Java files in my project. Something like this:

$ find . -name '*.java' -exec cat $HOME/Documents/gpl.txt {} > {} \;

But it doesn't work. Aside from the possibility that such a command would clobber the input file before it was even read, I could find neither documentation nor examples of using shell redirection within the -exec.

So I took the easy way out and made a simple Bash script to prepend the GPL license to a list of files on the command line. Default on Ubuntu is to add $HOME/bin to your path. Don't forget to:

$ chmod +x $HOME/bin/prepend_gpl

$HOME/bin/prepend_gpl
#!/bin/bash

# Use Ubuntu's auto-mounted RAM disk for temporary files
TMP=/dev/shm

# Use GPL environment variable if set, otherwise use default
if [ ! $GPL ]; then
    GPL=$HOME/Documents/gpl.txt
fi

# Check the license file exists
if [ ! -e $GPL ]; then
    echo $GPL not found
    exit -1
fi

# Prepend the license to each file listed on the command line
while [ $1 ]; do
    cat $GPL $1 > $TMP/prepend_gpl.tmp 
    mv $TMP/prepend_gpl.tmp $1 
    shift
done

Nothing too tricky there, making use of a temporary file to hold the composited file and renaming back to overwrite the original. Note the /dev/shm mount point on Ubuntu, which is an auto-mounted RAM disk in shared memory, ideal for temporary files.

$ prepend_gpl *.java

That deals with all .java files in a directory. To apply to a whole project, it can be used with find from the root of the project:

$ find . -name '*.java' -exec prepend_gpl {} \;

Job done, but I was still curious if I could do it in a one-liner and found this neat trick of redirecting a command into a Bash loop structure. This uses a while loop, but other constructs work in a similar way.

$ while read f; do cat $HOME/Documents/gpl.txt "$f" > /dev/shm/addgpl.tmp && mv /dev/shm/addgpl.tmp "$f"; done < <(find . -name '*.java')

Does it count as a one-liner? Will I be able to recall the syntax off the top of my head? I'll leave you to decide!

Monday, 22 March 2010

Apache and Tomcat on Ubuntu

I've had a frustrating time today, getting Tomcat working behind Apache on Ubuntu. Frustrating because there are a lot of conflicting HOWTOs, blog posts, forum posts and documentation around. Here's another! ;)

Anyway, while I remember, here's how I got it working ...

Versions

I think part of the documentation problem is down to differences between versions, so, for the record:

  • Ubuntu 9.04 Jaunty Jackalope
  • Tomcat 6.0.18
  • Apache 2.2.11
  • Java 1.6.0.16
  • mod_jk 1.2.26

All packages installed using apt-get from the Jaunty repositories.

EDIT [15th April 2010]

Since posting this, I've had a chance to confirm these instructions on Ubuntu 10.04 Lucid Lynx and, generally speaking they work OK. Differences are covered in italics at appropriate points in the text, these being the versions:

  • Ubuntu 10.04 Lucid Lynx
  • Tomcat 6.0.24
  • Apache 2.2.14
  • Java 1.6.0.18
  • mod_jk 1.2.28

Prerequisites

I'm going to assume that you have Tomcat up and running on the default port of 8080 and serving requests. Also that you have installed and tested Apache on the default port of 80, keeping the default configuration of virtual hosts as provided by the Ubuntu repositories.

Installing Apache on Ubuntu Installing Tomcat on Ubuntu

Requests are delegated from Apache to Tomcat by Tomcat listening on port 8009 for AJP1.3 requests and Apache being configured to divert some request URIs through "workers". In our case, the worker is Tomcat.

Setting up Tomcat

I've used mod_jk to connect Apache to Tomcat. It's not the only way. See the Tomcat WIKI for information on which is the recommended connector protocol.

The Ubuntu-supplied Tomcat doesn't listen for for AJP1.3 requests on port 8009 by default, so edit /var/lib/tomcat6/conf/server.xml, search for "8009" and uncomment the AJP1.3 connector module:

/var/lib/tomcat6/conf/server.xml
...
<!-- Define an AJP 1.3 Connector on port 8009 -->
<Connector port="8009" protocol="AJP/1.3" redirectPort="8443" />
...

Restart Tomcat, giving it time to start the listeners, and check that it is listening on port 8009:

$ sudo /etc/init.d/tomcat6 restart
 * Stopping Tomcat servlet engine tomcat6                                [ OK ] 
 * Starting Tomcat servlet engine tomcat6                                [ OK ] 
$ sudo netstat -ln | grep :8009
tcp6       0      0 :::8009                 :::*                    LISTEN     

For Lucid, restart Tomcat with $ sudo service tomcat6 restart.

If the listener is listening, Tomcat should be good to go.

Setting up Apache

To get Apache to talk to Tomcat, the first step is to install the AJP1.3 connector module mod_jk:

$ sudo apt-get install libapache2-mod-jk2

For Lucid, package is libapache2-mod-jk.

With the default Ubuntu packaging, this is all set up and should be loaded without any further intervention. The key to this is that /etc/apache2.conf includes all modules listed in /etc/apache2/mods-enabled. There's no need to add the LoadModule directive to apache2.conf as you might see quoted in some places. Such as the Tomcat documentation for example.

Then it's just a matter of configuring Apache to route some requests through to Tomcat.

The core of the Apache configuration looks like this on a default Ubuntu setup:

JkWorkersFile /etc/apache2/workers.properties
JkShmFile     /var/log/apache2/mod_jk.shm
JkLogFile     /var/log/apache2/mod_jk.log
JkLogLevel    error
JkLogStampFormat "[%a %b %d %H:%M:%S %Y] "
JkMount /MyWebApplication/* tomcat

You have a choice at this point. You can configure this within the default virtual host that Ubuntu's Apache comes with, or globally.

If you want to configure just for the virtual host, add the above section to the bottom of /etc/apache2/sites-available/default.

If you want to configure the forwarding globally, add the above section to the bottom of /etc/apache2/apache2.conf. In this case, you also need to add an extra line to the sites-available file to get the virtual site to read the mounts. Immediately under DocumentRoot is a reasonable place.

/etc/apache2/sites-available/default
...
DocumentRoot  /var/www
JkMountCopy   On
...

The final part of the jigsaw is to set up the worker.properties file now referred to in the Apache config files. So make a new file ...

$ sudo touch /etc/apache2/workers.properties

... and edit it. With sudo of course

/etc/apache2/workers.properties
worker.list=tomcat

worker.tomcat.type=ajp13
worker.tomcat.host=localhost
worker.tomcat.port=8009

Look back at the lines we added to the Apache config files and note that the JkMount directives refer Apache to entries in workers.properties. If you had multiple Tomcat servers, you could achieve some simple application-level load balancing by routing different applications to different servers:

/etc/apache2/workers.properties
worker.list=tomcat_a, tomcat_b

worker.tomcat_a.type=ajp13
worker.tomcat_a.host=hosta
worker.tomcat_a.port=8009

worker.tomcat_b.type=ajp13
worker.tomcat_b.host=hostb
worker.tomcat_b.port=8009

Anyway, I digress. Restart Apache and you should be up and running.

$ sudo /etc/init.d/apache2 restart

For Lucid, restart Apache with $ sudo service apache2 restart.

Thursday, 11 March 2010

It's been a while!

I can't believe it's been almost a year since I posted anything on this blog! I feel as though I should make excuses but, hey, I've just been doing other things and it's gone to the back of my mind. It happens I guess.

I'm still going strong with Ubuntu. My laptop is upgraded to Ubuntu 9.10 and NetBeans 6.8 and that's where I do most work in terms of examples for training courses. My old desktop machine is currently running Xubuntu 9.10 until I get round to a much-needed motherboard and CPU upgrade. That will probably become a test bed for Ubuntu 10.04. The headless server box is on Ubuntu 9.04 with all of the GUI stripped back so it's more like Ubuntu Server. It was running Oracle XE and Glassfish v2 but I replaced those with MySQL and Tomcat as I've not been doing much with EJB. Most of the work done by that box is RAID1 file service, DNS and Subversion

I've nothing against Microsoft operating systems per se but I don't miss the rebooting and what always seemed a painful process of upgrading on Vista. ;)

The past few weeks have been spent looking at Spring 3.0, particularly Spring MVC. I am really liking the new features, especially the simplified web development, and I'll try and get a few posts together over the next month or so.

ps. Just discovered an unpublished draft post from last October about Hibernate and multiple bags. There was probably a good reason why I didn't publish it at the time but it seemed to make sense, so up it went.

Followers