Spring Roo Tutorial: LongURL, Part 1

skeleton.roo1.8 KB

A little while back I needed to create a simple server to supply some information to some local machines, and cache that information. I realised that it was probably a project I could use Spring Roo to great effect, and that it was simple enough to provide the basis for a tutorial. Here is that Tutorial


I am processing URLs and want some way of identifying whether they are the same. Now there are reasonably well understood algorithms for normalising URLS - such as removing sessions after a semi colon, removing extra slashes, removing "/dirname/.." and so on. But many systems nowadays use URL shorteners - websites which provide a short URL which can be used in a browser to get to the longer URL web page. This is most common on Twitter where message length is restricted.

Now I could write some code which fetched each URL in turn and figured out whether it was redirected to some other web page but that would be pretty innefficient. My thought was to set up some kind of local server which acted as a memory store for all these short to long URL maps - and also figured out new ones.

I looked around for who else had done this sort of thing and found a web site called http://realurl.org/ This did most of what I wanted - but I still needed to cache its responses in one place so that I didn't ask it the same question 20 times. (You can find out more about their API at http://realurl.org/api.php )

The Design

I would need a database to store the mappings from short to long url. I would need some means of accessing those entities in a CRUD like manner, and I would need a JSON like call to fetch values from the database by specifying the "potentially" short url, and look them up on realurl.org if they were not found in our database.

I'd also cache the result whether or not the new url was shorter.

Spring Roo

I wont show you how to set up Spring Roo. There are lots of tutorials for that. But basically you need to have roo shell (or Spring Tool Suite - STS) installed so that you can run roo in a new directory.

Use your favourite database tool to create a database, and user with permission to access that database. Personally I like phpmyadmin. The new user will need to create tables so don't skimp on the permissions :-)
I used MySQL, but you are welcome to use something else in your own projects - just don't come to me looking for free support when RANDOM_WEIRD_DATABASE doesn't work.

In my example I created a database called "roo_longurl", an user called "roo".

So, start up roo...

Create the Project

Let's create the project

project --topLevelPackage uk.co.owal.longurl --java 6 --projectName longurl

Cool. Hopefully that will have created some classes and a pom.xml file (for maven) in your current directory. Note that I have chosen "uk.co.owal.longurl" as the package, and "longurl" as the project name. Later on when you see the "~" symbol Roo treats that as short hand for the package name - so I don't have to type uk.co.owal.longurl every few minutes.

Sadly it is not easy to change stuff within roo. Some things you can change manually with a text editor / programmer's IDE and roo will notice and act accordingly. But often if you mess up you will need to start again.

Add Logging

Now, let's add some logging. I'm told that logging is a good idea, but I never use it because my code always works perfectly first time.

    // Setup logging 
    logging setup --level DEBUG --package ROOT
    logging setup --level DEBUG --package PROJECT
    properties set --name log4j.properties --key log4j.appender.R.File --path SRC_MAIN_RESOURCES --value longurl.log
    properties set --name log4j.properties --key log4j.rooLogger --path SRC_MAIN_RESOURCES --value DEBUG
    properties remove --name log4j.properties --path SRC_MAIN_RESOURCES --key log4j.appender.stdout
    properties set --name log4j.properties --key log4j.logger.sample.roo.longurl --path SRC_MAIN_RESOURCES --value DEBUG1

This puts most of the logging to a file, and stops it all being pushed to stdout. I'm not happy about this and suspect I've got something wrong.

Add the Database

I picked Hibernate as my ORM, mostly because it is fairly common and well understood. Remember to plug in whatever names you used for your database.

    // Setup Database. I guess it assumes localhost and default port.... 
    persistence setup --provider HIBERNATE --database MYSQL --databaseName roo_longurl
    database properties set --key database.username --value roo
    database properties set --key database.password --value asarin
    // Sometimes I need to change the jdbc connection string found in database.properties

If you are doing this for the first time then you will probably find that Spring Roo doesn't know how to talk to MYSQL. "wtf" I hear you cry. It used to before, didn't it? Well, the ability to talk to MySQL was not deemed to be core to SpringRoo, but more of an "addon". We need to fetch addons from the public RooBot server. (Think perl CPAN, or java Maven repository)

For now I suggest you try following the instructions that Roo gives you.

Add the Entities / Table

We only have one entity in the system right now - and that is a UrlMap from short url to long url.

    // Set up main table, with two main columns, and a numeric id. 
    // To be honest the shortUrl ought to be the primarykey
    entity --class ~.domain.UrlMap 
    field string --fieldName shortUrl --column SHORTURL --notNull
    field string --fieldName longUrl --column LONGURL --notNull

Hibernate and SpringRoo seem to like numeric primary keys. Ideally I'd prefer shortUrl to be the key since it should be unique in the table. But let's leave it like that for now.

Web Scaffold

Now, let's ask Spring Roo to create the main web application for this...

    // Create Apache Tiles and Spring MVC scaffolding
    web mvc setup
    web mvc all --package ~.web

I've put it in a package called "uk.co.owal.longurl.web" (remember that ~ means the top level package).

This creates some basic jspx/html to be used in the web site.

Coming soon... testing what we have so far.