Fork me on GitHub

Event Flow in Jandal

ChitChat is a chat application which demonstrates event flow up and down a controller hierarchy.

T

he ChitChat example has three clients, Piggy, Kermit and Gonzo, each of which has a controller. When you post a message from one of the clients, it is fired as a child-event at their parent root controller, which then broadcasts the message back down to all the child controllers as a parent-event so that they can each display it in their local copies of the chat transcript.

Sourcecode

ChitChat.java

public class ChitChat extends Application {

    public ChitChat(ServiceSet serviceSet, Params params)
            throws JandalCoreException {
        super(serviceSet, params);
    }

    protected void onStart() throws JandalCoreException {
        this.setRootController(new ChatPageController("chatPageController"));
    }
}

ChatPageController.java

public class ChatPageController extends Controller {

    public ChatPageController(String name) throws JandalCoreException {
        super(name);
    }

    protected void onStart() throws JandalCoreException {
        this.addInitialState(new State("initialState") {

            protected void onEntry() throws JandalCoreException {
                setOutput("template", "chatPage.ftl");

                this.addChildController(new ChatClientController("gonzo"));
                this.addChildController(new ChatClientController("piggy"));
                this.addChildController(new ChatClientController("kermit"));

                addChildEventProcessor(new EventProcessor("messagePosted") {
                    protected void onEvent() throws JandalCoreException {
                        String sender = getStringParam("sender");
                        String message = getStringParam("message");
                        this.fireParentEvent("messagePosted", new Params().add(
                                "sender", sender).add("message", message));
                    }
                });

            }
        });
    }
}

chatPage.ftl

<center>
</br>
<table cellpadding="0px" cellspacing="0px" border="0px" width="570">
        <tr>
                <td width="50%" valign="top" align="right"><img src="${context.getResourceUrl("logo.jpg")}"/></td>
                <td width="50%" valign="top"><font face="Helvetica" size="+2"><b><img src="${context.getResourceUrl("title.jpg")}"/></b></font>
                </td>
        </tr>
        <tr>
                <td colspan="2">
                        </br>
These three chat clients each have a controller. When you post a message from one of them, it is
fired as a <i>child-event</i> at the root controller, which then broadcasts the message
back down to all the child controllers as a <i>parent-event</i>.
                        <br/>
                        <table cellspacing="10px" cellpadding="8px" border="0px">
                                <tr>
                                        <td>${context.getChildView("gonzo")}</td>
                                        <td>${context.getChildView("piggy")}</td>
                                        <td>${context.getChildView("kermit")}</td>
                                </tr>
                        </table>
                </td>
        </tr>
</table>
</center>

ChatClientController.java

public class ChatClientController extends Controller {

    public ChatClientController(String name) throws JandalCoreException {
        super(name);
    }

    protected void onStart() throws JandalCoreException {
        messages = new StringBuffer();

        setOutput("name", ChatClientController.this.getName());
        setOutput("messages", "(no messages yet)");

        addInitialState(new State("initialState") {
            protected void onEntry() throws JandalCoreException {
                setOutput("template", "chatClient.ftl");

                addParentEventProcessor(new EventProcessor("messagePosted") {
                    protected void onEvent() throws JandalCoreException {
                        String sender = getStringParam("sender");
                        String message = getStringParam("message");
                        messages.append(sender + ": " + message);
                        messages.append("\n");
                        setOutput("messages", messages.toString());
                    }
                });
                addViewEventProcessor(new EventProcessor("messagePosted") {
                    protected void onEvent() throws JandalCoreException {
                        fireChildEvent("messagePosted", new Params().add(
                                "sender", ChatClientController.this.getName())
                                .add("message", getStringParam("message")));
                    }
                });
            }
        });
    }

    private StringBuffer messages;
}

chatClient.ftl

${context.getFormTool().getFormOpenTag("messagePosted")}
        <table cellpadding="5px" cellspacing="0px" border="0px">
                <tr>
                        <td  align="center"><b>${context.getOutput("name")}</b></td>
                </tr>
                <tr>
                        <td bgcolor="#AACCFF" align="left"><pre>${context.getOutput("messages")}</pre></td>
                </tr>
                <tr>
                        <td align="center">
                                <input name="message" type="text" value=""/>
                                </br>
                                <input type="submit" value="Post"/>
                        </td>
                </tr>
        </table>
${context.getFormTool().getFormCloseTag()}

web.xml

<?xml version="1.0" encoding="UTF-8"?>
<web-app>
        <display-name>jandal-chitchat</display-name>

                <description>The Jandal TreeMap Demonstration Application</description>

                <!--    Set minutes that a session can remain unused before Jandal destroys it.
                                We'll make it ten minutes for this little demonstration application. -->

                <session-config>
                        <session-timeout>10</session-timeout>
                </session-config>

                <!--    You MUST have this J2EE listener - it tells Jandal when an application session expires.
                -->

                <listener>
                        <listener-class>
                                com.neocoders.jandal.ui.freemarker.session.JandalFreeMarkerAttributeListener
                        </listener-class>
                </listener>

                <!--    Here is the star of the show, the JandalFreeMarkerServlet. You can have only
                                one of these per Jandal application.
                -->

                <servlet>
                        <servlet-name>jandal-chitchat</servlet-name>
                                <servlet-class>com.neocoders.jandal.ui.freemarker.servlet.JandalFreeMarkerServlet</servlet-class>

                                <!-- Specify our Application implementation:
                                 -->

                                <init-param>
                                        <param-name>application-class</param-name>
                                <param-value>com.neocoders.jandal.examples.chitChat.ChitChat</param-value>
                                </init-param>

                                <!--    Specify our ServiceSet implementation. An empty string here
                                                causes JandalFreeMarkerServlet to use it'
s own default empty ServiceRegistry.
                                -->

                                <init-param>
                                        <param-name>service-set-class</param-name>
                                <param-value></param-value>
                                </init-param>

                                <!--    Specify the name reserved for the outputs that hold the file names of their Controller's
                                                bundled FreeMarker template for JandalFreeMarkerServlet to render them with.
                                                If this param is omitted, or if an empty string is given, JandalFreeMarkerServlet
                                                will use "template" by default.
                                -->

                                <init-param>
                                        <param-name>template-output-name</param-name>
                                <param-value>template</param-value>
                                </init-param>

                                <!--    Specify the name that the application-access tool may be accessed by in FreeMarker templates.
                                                If this param is omitted, or if an empty string is given, JandalFreeMarkerServlet
                                                will use "context" by default.
                                -->

                                <init-param>
                                        <param-name>template-context-name</param-name>
                                <param-value>context</param-value>
                                </init-param>

                                <init-param>
                                        <param-name>window-title</param-name>
                                <param-value>The Jandal ChitChat Demonstration Application</param-value>
                                </init-param>

                        <load-on-startup>1</load-on-startup>
                </servlet>

                <servlet-mapping>
                        <servlet-name>jandal-chitchat</servlet-name>
                        <url-pattern>/*</url-pattern>
                </servlet-mapping>
</web-app>