<< October 2007 | Home | December 2007 >>

Spring MVC: Null or an Empty String?

Wondered why Spring MVC converts an empty field to an empy string instead of null?

Spring MVC converts your empty fields to an empty string instead of null by default. This is often not what you want when you persist your entities. The reason for this behavior is that Spring MVC uses Java's default property editor for strings when binding the request to your domain object.

A better alternative is to use the StringTrimmerEditor that removes surrounding white space from the field values and optionally converts an empty value to null instead of an empty string.

Just override the initBinder method of your SimpleFormController:


protected void initBinder(HttpServletRequest request, 
  ServletRequestDataBinder binder) throws Exception
{
  // bind empty strings as null
  binder.registerCustomEditor(String.class, new StringTrimmerEditor(true));
}

References

Tags :

Adding Presence to Your Website

Showing Jabber status messages

You might have noticed the small green, yellow or gray icon next to my name in the about section on the right. It shows my XMPP status and my status message. This is done by including a small JavaScript snippet in the template of my blog:


<script type="text/javascript" 
  src="/js/presence.js?uid=stefan.reuter&nick=Stefan%20Reuter">
</script>

The presence.js script is in fact a PHP script that retrieves the XMPP presence from the presence plugin of my Openfire server:


<?php
ini_set('display_errors', false);

$uid = $_GET['uid'];
if (! preg_match('/^[A-Za-z0-9_\.-]+$/', $uid))
{
        echo "document.write('Invalid uid parameter.');";
        die;
}
if (isset($_GET['nick']))
{
        $nick = $_GET['nick'];
}
else
{
        $nick = $uid;
}
if (! preg_match('/^[A-Za-z0-9_\. -]+$/', $nick))
{
        echo "document.write('Invalid nick parameter.');";
        die;
}
$imgtag = "<img src=\"/status/".$uid."\"/>";
$url = "http://openfire:9090/plugins/presence/status?jid="
        .$uid."@reucon.com&type=text";
$text = rtrim(implode(file($url, FILE_SKIP_EMPTY_LINES)));
$text = str_replace("\n","",nl2br(htmlspecialchars($text)));
?>
document.write('<table class="xmpp-status"><tbody>');
document.write('<tr valign="center">');
document.write('<td><?php print $imgtag; ?></td>');
document.write('<td><?php print $nick; ?></td>');
document.write('</tr>');
<?php if ($text != 'null') { ?>
document.write('<tr>');
document.write('<td> </td>');
document.write('<td><?php print $text; ?></td>');
document.write('</tr>');
<?php } ?>
document.write('</tbody></table>');

References

Extracting Jira Worklogs from Subversion

Time tracking through Subversion Commit Messages

We are using Atlassian's Jira for issue and time tracking.
Time tracking discipline has been varying mainly because it interrupts your flow if you have to leave the IDE to log work done. As we already include the corresponding Jira issue key in all our Subversion commit messages the natural idea was to just add the time spent to the commit message.

The worklog above is created from the first line of this commit message:

[BAS-70] Added README file (20m)
[BAS-61] Removed old stuff and did so
 much that it doesn't fit on a line (1w2d4h)

svn-worklog.rb is the Ruby script I wrote to extract worklog information from commit messages and attach them to the associated Jira issue. It is called from the post-commit hook.

Read more...

Using Kernel-based Virtualization

KVM on Ubuntu Gutsy Gibbon 7.10

Recently I stumbled upon KVM (for Kernel-based Virtual Machine) which allows you to leverage the virtualization features built into modern processors.

This blog entry got me started. I am running Ubuntu Gutsy Gibbon 7.10 on an AMD Athlon(tm) 64 X2 Dual Core Processor so I installed qemu and kvm, loaded the kernel module and created a disk image for my virtual machine:

sudo apt-get install qemu kvm
sudo modprobe kvm-amd
qemu-img create node1.img -f qcow2 6G

Next I added myself to the kvm group to access /dev/kvm. As an alternative you can temporarily loosen the permissions (sudo chmod 666 /dev/kvm) but don't forget to fix that later on.
I grabbed the iso image of the server edition of Ubuntu 7.10 and was ready to boot the vm and start the installation:

kvm -m 750 -cdrom ubuntu-7.10-server-amd64.iso -boot d -std-vga node1.img

Wow! That was easy:

I installed Ubuntu just like on every other computer. Once the installation was done the automatic reboot failed as expected and I closed the qemu window and started it again (this time with only 500MB of RAM which is still plenty):

kvm -no-acpi -m 500 node1.img

I booted a fully running Ubuntu system - even networking automagically worked.

This looks like a great alternative to the bloated VMware server especially as it is extremly easy to just copy or move the virtual machines if you want to play with clustering for example.

Read more here and here (yes, you can also run Windows this way). Cool stuff!

Clustering Jira with Terracotta DSO

Sourcesense has added clustering to Jira using Terracotta DSO and released it under an Open Source license.

Clustering for Jira has been a long requested feature by Atlassian's customers. While Atlassian provides clustering for their enterprise wiki product Confluence they voted for different priorities for their issue tracker.
Jira comes with full source code for its enterprise customers and integrators and it seems to be quite well engineered if a third party could easily add such a low level feature by simply providing a plugin. Another interesting aspect is that Sourcesense chose Terracotta DSO over Oracle's Coherence which is used by Confluence and many other enterprise products in that category. Terracotta allows distributing the plugin under an Open Source licence which Coherence disallows.

The beta plugin is available from the Jira plugin pages.

I wonder what it would take to implement the clustering features of the enterprise edition of Openfire using Terracotta DSO instead of Coherence ;)

Updates for Openfire 3.4.1

New versions of Asterisk-IM, Open Archive and the User Status Plugin

A few days ago Openfire 3.4.1 has been released.

More than 30 new features and more than 30 bugs were fixed. Personal Eventing via Pubsub was added so you can now publish your geo-location, music you are listening to and let subscribers be alerted. From the admin console you can manage users roster. Moreover, it is now possible to retrieve photos from LDAP and use them as users avatars. The complete set of changes can be found here. Openfire 3.4.1 is available for download from ignite realtime.

The new version includes a few incompatible changes to the API so I have released new versions of the plugins that I maintain:

Open Archive and the plugins are released under the terms of the GPL.

Accessing Jira from Ruby

Soap4R and Jira4R

On Ubuntu I've installed ruby, the interactive Ruby shell irb and rubygems through apt-get and performed a gem update:

apt-get install ruby irb rubygems ruby1.8-dev
gem update --system

Gem is to Ruby what apt-get is to Ubuntu and Debian or CPAN to Perl: A package manager with support for dependencies providing and easy way to install extensions.

As with Java I prefer to us the native tools of the language to manage libraries and extensions so I only used apt-get to install the base and added the remaining dependencies through gem:

gem install rake
gem install soap4r

Rake is Ruby's make or ant and allows to build applications from source. Soap4R is a soap library for Ruby.

Now it's time to install Jira4R. I've used the latest version from their subversion repository:

cd /usr/local/src
svn co http://svn.rubyhaus.org/jira4r/trunk/ jira4r
cd jira4r
gem build jira4r.gemspec
gem install *.gem

Using Jira4R is quite simple:

require 'rubygems'
require 'jira4r/jira_tool'

jira = Jira4R::JiraTool.new(2, "http://jira.atlassian.com")
jira.login("soaptester", "soaptester")

issue = Jira4R::V2::RemoteIssue.new
issue.project = "DEMO"
issue.type = "1"
issue.summary = "Test from Ruby"
issue.assignee = "soaptester"

jira.createIssue(issue)

You can find more examples on the Jira4R page and in Jira's SOAP API.

If you access your Jira instance through SSL you can add

jira.driver.options["protocol.http.ssl_config.verify_mode"] = nil

before the call to login so that Soap4R does not try to verify the SSL certificate. If you don't you will encounter errors like

.../httpclient.rb:1039:in `connect': certificate verify failed (OpenSSL::SSL::SSLError)

Empty Windows in Swing Applications on Ubuntu 7.10

Java 6 on gutsy has problems with compiz

Using Java applications on Ubuntu 7.10 (gutsy) sometimes show empty windows. I've encountered this mainly with LDAP Browser/Editor and IDEA 7.0. It does not occur too often and mainly with small dialog windows. I guess Java 6 has some problems with Compiz which is enabled by default since gutsy.

The solution is to upgrade to Java 7 which is currently available as an early access version from the JDK 7 project at Sun.

This fixed my problems with LDAP Browser/Editor but IDEA complained with a "Java Version Mismatch" error. IDEA 7.0 officially requires Java 5 or Java 6, but also works with the EA of JDK 7. You can disable the check for the correct Java version by adding the following line to idea.vmoptions:

-Didea.no.jdk.check=true

Update

As eivindw wrote in the comments you may also be able to make IDEA work with Java 6 by setting the following environment variable:

export AWT_TOOLKIT="MToolkit"

MToolkit switches to the Motif implementation of AWT which was removed for Java 7. On my 64-bit version of Gutsy using MToolkit with Java 6 resulted in a core dump.

Update