Chapter 3. Hello, Seedling!

Sometimes it's easiest to learn by doing. In this chapter we'll walk you through a workday with Seedling, showing you the basic workflow and design concepts step by step.

3.1. Setup

We're going to start with a fresh workspace based on the Seedling Software Development Kit. Begin by going to the Seedling Web site and downloading the latest SDK distribution.

Unpack the SDK archive and place it anywhere in your file system. Go ahead and rename the directory if you want. As you'll see, the Trellis build system on which Seedling is built provides a very self-contained workspace, you can move it around as you wish and nothing's going to break. For the purposes of this tutorial, we'll assume that your workspace is located at the path ~/tutorial. Once you've got the archive unpacked, things should look like this:

[tutorial]$ ls
LICENSE.TXT     bin/            build.xml       seedling/       src/
Welcome.html    build/          lib/            setup

Before you do any work, you need to setup your shell environment. This process defines some environment variables so the various tools know where the workspace lives. It also adds the workspace's bin directories to your path, so you can run the tools easily.

To setup the environment, just source the setup file:

[tutorial]$ source setup
Running Ant to install supporting tools and libraries...
Buildfile: build/setupTools.xml

BUILD SUCCESSFUL
Total time: 0 seconds

PROJECT_HOME is /Users/todd/tutorial
To see project targets, type 'ant -projecthelp'
[tutorial]$

OK, we're lying here. The first time you go through this process, it's going to be a bit more complicated:

  • You'll get an error saying that Ant wasn't found, along with directions about what to put where. Just do as you're told, eat your vegetables, and you'll grow up big and strong.

  • When you setup again as instructed (Sir, Yes, Sir!), the script will download and install a number of third-party packages into your workspace.

  • From then on out, the setup will look as short and sweet as we say above.

Despite our minor subterfuge, you should now be ready to run. Let's go for the gold and build the whole system:

[tutorial]$ ant modules
Buildfile: build.xml

...

module:
Building jar: /Users/todd/tutorial/target/modules/ticker/lib/ticker.jar

BUILD SUCCESSFUL
Total time: 4 seconds
[tutorial]$

Guess what? You just compiled a Seedling module! Let's run it!

[tutorial]$ runseed ticker
This is Ticker version DEV-todd-200403202332
//tasks/MemoryMonitor: Active memory: 543K/1984K (27%)
//tasks/ClockTicker: The current time is Wed Oct 20 23:18:43 PDT 2004
//tasks/ClockTicker: The current time is Wed Oct 20 23:18:44 PDT 2004
//tasks/ClockTicker: The current time is Wed Oct 20 23:18:45 PDT 2004

...and so on. You've just built and run a very simple Seedling application that prints the time every second. Not bad! As simple as it seems, at the very least you've verified that you have a functional workspace, which gives us a good baseline for much bigger things to come.

3.2. A New Module

[Warning]Warning
This is rough, sorry.
$ cp -r src/ticker src/hello

Edit build.xml:Add hello to subprojects

Edit hello/build.xml: Set project name. Clear predecessors.

Edit hello/module.properties: Update requires (if necessary).

Now wipe the main and config trees.

$ ant modules
$ runseed hello

Nothing happens! Well, of course not, our module is empty.

Let's give the module something to do: the insipid yet obligatory Hello World application. Everyone knows how to do this, right? Create a new file called HelloWorld.java inside the empty main directory of the hello module. The main directory is the root of the module's main Java code; any subdirectories here will correspond to the Java package hierarchy. For now, we'll keep things simple and just define a class in the default package.

// file: tutorial/src/hello/main/HelloWorld.java

public class HelloWorld
{
    public static void main(String[] args)
    {
        System.out.println("Hello, World!");
    }
}

Wait! Stop! No! Have you forgotten everything you learned in the last chapter? The goal here is not to write procedural applications, but to write component applications. A good component almost never has static things, and certainly shouldn't have main! Let's try again, placing the output statement in the first available place, the constructor:

// file: tutorial/src/hello/main/HelloWorld.java

public class HelloWorld
{
    public HelloWorld()
    {
        System.out.println("Hello, Seedling!");
    }
}

There now, doesn't that feel good? We have a nice little component, just waiting to be instantiated into a welcoming world.[1] Let's create another file that will cause just that to happen. The following file declares a Seedling node that will be our first component.

# file: tutorial/src/hello/config/Hello.properties

.this = new HelloWorld

Some explanation is in order.

  • This file is in the config directory, not the main source directory. The config directory is the root of the module's Seedling configuration layer. You'll learn a lot more about it as we work through this tutorial.

  • The name of the file corresponds to the name of the Seedling node it configures. This file, Hello.properties, configures a node called Hello.

  • This is a normal Java properties file. This means that comments begin with the hash character, #.

  • The only property here looks a little strange, since it starts with a period. This denotes a meta-property, meaning that it's an instruction to the container rather than a value being assigned to a property of the component.

  • The .this meta-property declares an expression that will be evaluated when this node needs to be instantiated. In this case, the Hello node will be an instance of the HelloWorld class.

This one little file with one little line is all that's necessary to enable Seedling to construct and install our component. Shall we try it? Don't forget to rebuild the module first.



[1] Yow, that's annoyingly twee, isn't it? Sorry, bad habit. Do they have a patch for that?