GuestBookTileTutorial

THIS PAGE IS A WORK IN PROGRESS. THE TUTORIAL IS NOT YET COMPLETE.

Introduction

This tutorial will go over creating a simple GuestBook? Tile for Brix.

For the purposes of this tutorial I will be writing code directly inside brix-demo project because it makes it trivial to try out the tile in action. You may do the same or create a seperate project.

Storing Entries in JCR

GuestBook? will store its entries inside the JCR. It is helpful to decide on how the data will be stored, for the purposes of this tutorial we will go with a very simple format:

GuestBook Tile Node
  Entry
    Message
    Author
    Timestamp
  Entry
    Message
    Author
    Timestamp

Implementation

Getting Started

First step of creating a tile in Brix is creating a class that implements the brix.plugin.site.page.tile.Tile interface. Below is first cut at such a class:

public class GuestBookTile implements Tile
{
    public String getDisplayName()
    {
        return "Guest Book"; // #1
    }

    public String getTypeName()
    {
        return "brix.tile.GuestBook"; // #2
    }

    public TileEditorPanel newEditor(String id, IModel<BrixNode> tileContainerNode)
    {
        return new EmptyTileEditorPanel(id); // #3
    }

    public Component newViewer(String id, IModel<BrixNode> tileNode)
    {
        return new EmptyPanel(id); // #4
    }
  1. getDisplayName() returns the tile name the user will see in the list of available tiles
  2. getTypeName() returns a UUID string that represents the tile type. This is how Brix identifies which tile type is at which jcr node.
  3. newEditor() returns a panel that is used to configure the tile instance. For now we return an empty panel.
  4. newViewer() return s a panel that renders the tile content. For now we return an empty panel. The second step of creating a tile is letting Brix know it is there. The following snippet of code registers the tile with Brix:
public class DemoBrix extends Brix
{
    public DemoBrix(BrixConfig config)
    {
        super(config);
        config.getRegistry().register(Tile.POINT, new GuestBookTile()); // #1
        ...
    }
}
  1. Registers the tile in Brix’s ExtensionRegistry? Now if we start the demo we will be able to add a “Guest Book” tile to any page. At this point we have a complete, albeit useless, Brix tile.

Creating The GuestBook Interface

As with most Wicket components we start by creating a Wicket panel:

public class GuestBookPanel extends Panel
{
    public GuestBookPanel(String id, IModel<BrixNode> model)
    {
        super(id, model);
    }
}

GuestBookPanel.html

<wicket:panel>I am a guestbook tile</wicket:panel>

The next step is to tie the panel to the tile:

public class GuestBookTile implements Tile
{
    ...
    public Component newViewer(String id, IModel<BrixNode> tileNode)
    {
        return new GuestBookPanel(id, tileNode); // #1
    }
}
  1. Uses the GuestBookPanel as the viewer for the tile Now if we navigate to a Brix page that has this tile we will see “I am guestbook tile” where we placed the tile in the markup.

Creating New Entries

First, lets create a simple bean that will represent an entry in the guest book:

public class Entry implements Serializable
{
    public String name;
    public String message;
    public Date timestamp;
}

Now, lets create a Wicket form that will be used to submit data:

private class MessageForm extends Form
{
    private Entry entry = new Entry(); // #1

    public MessageForm(String id)
    {
        super(id);
        add(new TextField("name", new PropertyModel(this, "entry.name")));
        add(new TextArea("message", new PropertyModel(this, "entry.message")));
    }

    @Override
    protected void onSubmit()
    {
        onMessage(entry); // #2
        entry = new Entry(); // #3
    }
}

It is important to note that MessageForm is an inner class of the GuestBookPanel we created earlier.

  1. Instance of Entry that will be used to bind values from the form
  2. GuestBook?#onMessage callback that handles submitted entry
  3. Clear the previously submitted values so they do not remain in the form To setup the form we need to add it to our GuestBookPanel:
public GuestBookPanel(String id, IModel<BrixNode> model)
{
    super(id, model);
    add(new MessageForm("form"));
}
<form wicket:id="form">
author: <input wicket:id="name"/><br/>
message: <textarea wicket:id="message" cols="30" rows="3"></textarea><br/>
<input type="submit"/>
</form>

Now that we have the form working we need to persist submitted Entry into tile’s JCR node:

public class GuestBookPanel extends Panel {
...
  protected void onMessage(Entry message)
  {
    JcrNode tile = (JcrNode)getDefaultModelObject(); // #1

    JcrNode entry = tile.addNode("entry"); // #2
    entry.setProperty("name", message.name);
    entry.setProperty("message", message.message);
    entry.setProperty("timestamp", System.currentTimeMillis());

    tile.getSession().save(); // #3
  }
}
  1. retrieve the root tile node from the model object of the GuestBookPanel. This is the model that was passed into GuestBookPanel’s constructor by Brix
  2. create a new node under the root tile node and save the entry into it
  3. save the jcr session so our changes are persisted ## Displaying Entries A guest book is pretty useless if noone can see the entries made by others. The first thing we need to do is create a Wicket model that will produce a list of Entry objects. The model below is an inner class of the GuestBookPanel just like the MessageForm above.
private class EntriesModel extends LoadableDetachableModel<List<Entry>>
{
    @Override
    protected List<Entry> load()
    {
        JcrNode tile = (JcrNode)getDefaultModelObject(); // #1
        JcrNodeIterator entryNodes = tile.getNodes("entry"); // #2
        ArrayList<Entry> entries = new ArrayList<Entry>((int)entryNodes.getSize());

        while (entryNodes.hasNext())
        {
            JcrNode entryNode = entryNodes.nextNode(); // #3
            Entry entry = new Entry();
            entry.name = entryNode.getProperty("name").getString();
            entry.message = entryNode.getProperty("message").getString();
            entry.timestamp = new Date(entryNode.getProperty("timestamp").getLong());
            entries.add(entry);
        }
        return entries;
    }
}
  1. Retrieve the tile root node from the GuestBookPanel’s model.
  2. Create JCR node iterator over entry nodes
  3. Convert a JCR entry node into Entry object Now that we have a model that can generate the list of entries we have to create Wicket components to display it:
public class GuestBookPanel extends Panel
{
    public GuestBookPanel(String id, IModel<BrixNode> model)
    {
        super(id, model);

        add(new MessageForm("form"));
        add(new PropertyListView<Entry>("entries", new EntriesModel())
        {
            @Override
            protected void populateItem(ListItem<Entry> item)
            {
                item.add(new Label("name"));
                item.add(new Label("message"));
                item.add(new Label("timestamp"));
            }

        });
    }
}
<table>
<tr wicket:id="entries">
        <td><span wicket:id="timestamp"></span></td>
        <td><span wicket:id="name"></span></td>
        <td><span wicket:id="message"></span></td>
</tr>
</table>
```#

This is a unique website which will require a more modern browser to work!

Please upgrade today!