$URL: svn+ssh://christianc@svn.forge.objectweb.org/svnroot/barracudamvc/Barracuda2/trunk/WEB-INF/src_docs/quick_reference/index.html $ - $Revision: 125 $

Hello World 1

This is a very simple Hello World example that demonstrates how to use the BTemplate component to populate a screen.

ComponentGateway Background

First of all, it's important to at least vaguely understand what is going on behind the scenes in the ComponentGateway servlet. In a nutshell, the ComponentGateway:

  1. determines the appropriate ViewCapabilities settings
  2. create an empty root component
  3. gives our HelloWorld servlet a chance to add in any components
  4. renders the component hierarchy
  5. renders the DOM page returned by our HelloWorld servlet

Looking at the HelloWorld1 Servlet

Ok, so let's take a look at the actual servlet. Here's the basic flow:

  1. We start by loading the XML generated DOM object:

    XMLObject page = xmlcFactory.create(HelloWorld1HTML.class);

     

  2. Next we look for the specific node we wish to bind our component to:

    Node node = page.getDocument().getElementById("HelloWorld");

    this grabs a reference to the <html> element that is identified by the "HelloWorld" id in the XMLC template :

    <html id="HelloWorld">

     

  3. Once we have a reference to the node we can now create a View. The code looks something like this.

    TemplateView tv = new DefaultTemplateView(node);

     

  4. The next step is to actually create the model:

    TemplateModel tm = new HelloWorldModel();

     

  5. Now we can actually create the template component and bind it to the view and the model:

    BTemplate templateComp = new BTemplate(tm);
    templateComp.setView(tv);

    In this case we are implementing the model just like we would in Swing, by using an inner class. We'll look at the specifics a littler further on. For now, just remember that the model's responsibility is to provide data for the component. By binding a component to a view, we are saying that the component is going to assume responsibility for rendering everything that exists below the particular node that backs the view.
     

  6. Ok, we're almost done! The final step is to add our template component to the root component, and then return the DOM page that the ComponentGateway should render once the component hierarchy has been rendered. The code looks like this:

    root.add(templateComp);
    return page;

    That's it! The ComponentGateway will invoke render() on the root component, which in turn will cause our template component to render. Once that finishes, the ComponentGateway will render the DOM structure that we provided. The resulting page is returned to the client browser.

Implementing the Model

Alright, now let's look at what it takes to implement the model. BTemplate uses the TemplateModel interface. Note that unlike Swing components (and unlike the rest of the Barracuda components too!), the template component can take any number of models. When a model is added to the component, it queries the model to determine its name. This is important so that when the component processes directives in a template, it can tell which model it should query to actually retrieve the data.

We should also note that the Model does not have to be implemented using an inner class; we just do it that way because it's convenient and that's how you usually do it in Swing.

The TemplateModel interface defines a number of methods, but by extending from AbstractTemplateModel we only need to implement two:

public String getName()
public Object getItem(String key)

For the getName() method, we return the String "HelloWorld". Now, when the component encounters a directive in the template, it can map the directive to the model name HelloWorld and ask it for data.

When we implement the getItem() method, we simply look at the requested key and return the appropriate data. The BTemplate is smart enough to handle several kinds of data coming back from the model: Nodes, BComponents, and Strings. There may be occasions however where you'd like to return a complex block of HTML or another BComponent, but in most cases, it will be simplest just to return Strings (as we do here).

A Quick Look at Directives

Now is a good chance to look at the actual HTML template, since when dealing with a BTemplate, the template is responsible for telling the component what data is needed where. So how do we identify which parts of the template need to by dynamically populated?

Well, in HTML we can use directives embedded in element's class attribute field. A directive is any String that follows a well defined format:

Dir::<command>.<model>.<key>.<data>

So let's look at the template, what directives do we see? In the case of the HelloWorld template, there are several:

<title class="Dir::Get_Data.HelloWorld.Title">[Title]</title>
<h2 class="Dir::Get_Data.HelloWorld.Title">[Title]</h2>
<p class="Dir::Get_Data.HelloWorld.Descr">[Descr]</p>
<p class="Dir::Get_Data.HelloWorld.Hello">[Hello]</p>

From this we can see that all the directives use the same command: "Get_Data". This tells the template component that it needs to try and get data for the key in question and bind it to the particular node containing the directive. So, as each directive is encountered the component looks up the model specified (in this case "HelloWorld") and then queries the model for the key. The model returns the data and the component places it in the template.

Note that if we want to rearrange the page, all we have to do is update the template and then recompile using XMLC; it doesn't matter how much we change the page -- we don't have to modify the component or our model unless the designer wants to actually include new keys which are not currently supported.

Pretty neat, huh?

Miscellaneous Notes

There are a couple of other things worth noting. First, there are three or four other directives that will be addressed in subsequent tutorials. Second, if you don't like the idea of putting directives into your HTML, not to worry: they can be stored separately (either in a file or programmatically). Third, if you don't like the idea of directives at all, have no fear: you can accomplish the same thing using other components (although none of them are quite as easy to use as BTemplate!).


$Date: 2006-01-02 15:59:13 -0500 (Mon, 02 Jan 2006) $