Home Overview Demos/Webs News Download/Install Docs/Support Investors/Partners Commercial
Tutorial: Simple ItsNat (Core) Application
Introduction/Setup
Create a new servlet
Designing the page template
Registering the page template
Testing the template with a link or URL
Adding behavior

Last update: 2010, April 23  

Introduction/Setup

We are going to create a simple Single Page Interface AJAX based web application using the "core" part of the framework (without components).

First of all you need to download and decompress the ItsNat distribution and create a new web application with your favorite IDE, the name is not important, we will use "itsnat" in this tutorial. Follow the instructions explained in the download section, specifically the section What does any new ItsNat based web application need?


Create a new servlet

ItsNat does not provide a framework servlet, the main reason is because init(ServletConfig) method must be used to setup the ItsNatHttpServlet object (ItsNat wrapper of your servlet) and register used templates. Any servlet request must be dispatched to ItsNatHttpServlet wrapper. To simplify this ItsNat provides an abstract servlet: HttpServletWrapper, the source code is very simple and useful to understand how the layering works:

    public abstract class HttpServletWrapper extends HttpServlet
    {
        protected ItsNatHttpServlet itsNatServlet;

        public HttpServletWrapper()
        {
        }

        /**
         * Returns the ItsNat servlet wrapping this servlet.
         *
         * @return the ItsNat servlet.
         * @see ItsNatHttpServlet#getHttpServlet()
         */
        public ItsNatHttpServlet getItsNatHttpServlet()
        {
            return itsNatServlet;
        }

        /**
         * Initializes the ItsNat servlet wrapping this servlet. Overload this method
         * to initialize the ItsNat servlet (setup properties, register templates etc).
         */
        public void init(ServletConfig config) throws ServletException
        {
            super.init(config);

            this.itsNatServlet = (ItsNatHttpServlet)ItsNatBoot.get().createItsNatServlet(this);
        }

        /**
         * Processes requests for both HTTP <code>GET</code> and <code>POST</code> methods
         * and forwards them to the {@link ItsNatHttpServlet}.
         * 
         * @param request servlet request object.
         * @param response servlet response object.
         */
        protected void processRequest(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException
        {
            getItsNatHttpServlet().processRequest(request,response);
        }

        /**
         * Handles the HTTP <code>GET</code> method.
         * 
         * @param request servlet request
         * @param response servlet response
         */
        protected void doGet(HttpServletRequest request, HttpServletResponse response)
        throws ServletException, IOException
        {
            processRequest(request, response);
        }

        /**
         * Handles the HTTP <code>POST</code> method.
         * 
         * @param request servlet request
         * @param response servlet response
         */
        protected void doPost(HttpServletRequest request, HttpServletResponse response)
        throws ServletException, IOException
        {
            processRequest(request, response);
        }

        /**
         * Returns a short description of the servlet.
         */
        public String getServletInfo()
        {
            return "ItsNat Servlet";
        }
    }
    

When the servlet is first loaded an ItsNatHttpServlet layer object is created wrapping the real servlet object (init method).

As you can see in the line:

       getItsNatHttpServlet().processRequest(request,response);
    

Any request received by this servlet is redirected to the ItsNat servlet wrapper.

The easiest way to create your application servlet is to inherit from HttpServletWrapper. Use your favorite IDE to create a new servlet, we will use the name "servlet" but this name is not mandatory, and replace the source code with:

    public class servlet extends HttpServletWrapper
    {
        public void init(ServletConfig config) throws ServletException
        {
            super.init(config);
        }
    }
    

No special configuration is required in the web.xml archive to register the servlet (use the typical default code generated by your IDE).

A typical ItsNat application only needs one servlet, anyway multiple ItsNat based servlets may be deployed and they may cooperate because the same ItsNatSession and ItsNatServletContext objects are shared.


Designing the page template

ItsNat supports HTML and XHTML files, in our example we are developing a XHTML file like the following:


    <!-- <?xml version="1.0" encoding="UTF-8"?> -->
    <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
        "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
    <html xmlns="http://www.w3.org/1999/xhtml">
        <head>
            <title>ItsNat Core Example</title>
        </head>
        <body>
            <h3>ItsNat Core Example</h3>

            <div itsnat:nocache="true" xmlns:itsnat="http://itsnat.org/itsnat">
                <div id="clickableId1">Clickable Elem 1</div>
                <br />
                <div id="clickableId2">Clickable Elem 2</div>
            </div>
        </body>
    </html>
    

The standard XML header (<?xml…?>) is optional.

The isnat:nocache attribute (and the XML mandatory itsnat namespace declaration) set to true, tells the framework to avoid caching the <div> content, because page caching is enabled by default (can be disabled). <head> and <h3> elements will be cached automatically, for instance, at the server DOM, <head> contains a text node with a cache mark as the only child node, <h3> is not touched actually because the framework detects there is no saving (only contains and very small text).

This file will work as a template, and can not be accessible directly with a public URL, so will be saved below the standard WEB-INF folder, for instance:

<WebAppRoot>/WEB-INF/pages/manual/core_example.xhtml


Registering the page template

Now we need to bind the template with ItsNat with the following instructions (inside init() method):

        ItsNatHttpServlet itsNatServlet = getItsNatHttpServlet();
        ItsNatServletConfig itsNatConfig = itsNatServlet.getItsNatServletConfig();

        String pathPrefix = getServletContext().getRealPath("/");
        pathPrefix += "/WEB-INF/pages/manual/";

        ItsNatDocumentTemplate docTemplate;
        docTemplate = itsNatServlet.registerItsNatDocumentTemplate("manual.core.example","text/html",
                    pathPrefix + "core_example.xhtml");
        docTemplate.addItsNatServletRequestListener(new CoreExampleLoadListener());
        

ItsNat identifies the template with the specified name, manual.core.example, this name uses a Java-like format; this format is not mandatory but is highly recommended.

In this example no special configuration technique or framework is used and a hard coded file name is used in the code, if you think this approach is not elegant use the configuration technique you like more (.properties, custom XML, Spring …), the easiest way is to use .properties archives using the template names as keys.

Why a XHTML file is registered with a text/html MIME? Mozilla/Firefox, Safari, Opera etc accept application/xhtml+xml header but Microsoft Internet Explorer (MSIE) 6-8 does not, this is the most compatible declaration and is the main reason why the MIME type must be explicitly declared when registering.


Testing the template with a link or URL

Inside any static html, JSP etc add the following relative link:

<a href="servlet?itsnat_doc_name=manual.core.example">Core Example</a>
        

or type the following URL in your browser:

http://<host>:<port>/<yourapp>/servlet?itsnat_doc_name=manual.core.example


A page like this will be loaded in your browser:

This page is the template page with no "user defined" processing. If you inspect the source code the page is not exactly the original template, some non-intrusive JavaScript code was added automatically at the end of the page, this JavaScript, mostly the "unload" event listener, controls the page lifecycle notifying when the page is unloaded.


Adding behavior

We need to intercept any request to the manual.core.example page, to achieve this we need to register a "load listener" to the ItsNatDocumentTemplate object of the page:

        docTemplate.addItsNatServletRequestListener(new CoreExampleLoadListener());
        

The CoreExampleLoadListener source code:

    public class CoreExampleLoadListener implements ItsNatServletRequestListener
    {
        public CoreExampleLoadListener()
        {
        }

        public void processRequest(ItsNatServletRequest request, ItsNatServletResponse response)
        {
            ItsNatHTMLDocument itsNatDoc = (ItsNatHTMLDocument)request.getItsNatDocument();
            new CoreExampleDocument(itsNatDoc);
        }
    }
    

The processRequest method mimics HttpServlet.doGet/doPost methods, but using ItsNat object layers (in fact request and response are ItsNatHttpServletRequest and ItsNatHttpServletResponse objects). This method is called every time the page is requested to load by the client; the same page can be loaded several times and several times this method is called.

The ItsNatHTMLDocument object is the ItsNat object layer wrapping the Java W3C DOM HTMLDocument object. The HTMLDocument instance is initially clone of the template; every loaded page has a different ItsNatHTMLDocument/HTMLDocument object pair, then any modification made on an HTMLDocument while loading only affects to the concrete page loading. Any ItsNatHTMLDocument/HTMLDocument object pair lives during the lifecycle of the page and keeps the page state in server, any subsequent AJAX based event is targeted to the concrete document object in server.

ItsNatHttpServletRequest and ItsNatHttpServletResponse are unique per request and must not be saved beyond the request (load or AJAX-event request).

To isolate the document load processing and save any desired per loaded page state, a CoreExampleDocument auxiliary object is created; this object does not need to be saved (registered etc).

    public class CoreExampleDocument
    {
        protected ItsNatHTMLDocument itsNatDoc;
        protected Element clickElem1;
        protected Element clickElem2;

        public CoreExampleDocument(ItsNatHTMLDocument itsNatDoc)
        {
            this.itsNatDoc = itsNatDoc;
            load();
        }

        public void load()
        {
            HTMLDocument doc = itsNatDoc.getHTMLDocument();
            this.clickElem1 = doc.getElementById("clickableId1");
            this.clickElem2 = doc.getElementById("clickableId2");

            clickElem1.setAttribute("style","color:red;");
            Text text1 = (Text)clickElem1.getFirstChild();
            text1.setData("Click Me!");

            Text text2 = (Text)clickElem2.getFirstChild();
            text2.setData("Cannot be clicked");

            Element noteElem = doc.createElement("p");
            noteElem.appendChild(doc.createTextNode("Ready to receive clicks..."));
            doc.getBody().appendChild(noteElem);
        }
    }
    

The load method modifies the document changing text nodes and adding a final element, using pure Java W3C DOM because the page DOM tree page is in the server as a Java W3C DOM tree. Any change to the original template is sent to the client.

Redeploying and reloading:

If you click the “Click Me!” text nothing happens, we must add a remote W3C DOM event listener:

    public class CoreExampleDocument implements EventListener
    {
        ...

        public void load()
        {
            ...
            ((EventTarget)clickElem1).addEventListener("click",this,false);
        }

        public void handleEvent(Event evt)
        {
            EventTarget currTarget = evt.getCurrentTarget();
            if (currTarget == clickElem1)
            {
                removeClickable(clickElem1);
                setAsClickable(clickElem2);
            }
            else
            {
                setAsClickable(clickElem1);
                removeClickable(clickElem2);
            }

            ItsNatEvent itsNatEvt = (ItsNatEvent)evt;
            ItsNatServletRequest itsNatReq = itsNatEvt.getItsNatServletRequest();
            ItsNatDocument itsNatDoc = itsNatReq.getItsNatDocument();
            HTMLDocument doc = (HTMLDocument)itsNatDoc.getDocument();
            Element noteElem = doc.createElement("p");
            noteElem.appendChild(doc.createTextNode("Clicked " + ((Element)currTarget).getAttribute("id")));
            doc.getBody().appendChild(noteElem);
        }

        public void setAsClickable(Element elem)
        {
            elem.setAttribute("style","color:red;");
            Text text = (Text)elem.getFirstChild();
            text.setData("Click Me!");
            ((EventTarget)elem).addEventListener("click",this,false);
        }

        public void removeClickable(Element elem)
        {
            elem.removeAttribute("style");
            Text text = (Text)elem.getFirstChild();
            text.setData("Cannot be clicked");
            ((EventTarget)elem).removeEventListener("click",this,false);
        }
    }
    

The call ((EventTarget)clickElem1).addEventListener("click",this,false); adds a remote event listener listening for click events in client. In client automatically a proxy event listener is registered, when the symmetric element in client is clicked the native event is transported by AJAX to the server and converted in a Java W3C DOM Event, this event is dispatched to the registered Java EventListener in server. Only client events are transported to the server when some listener is registered in server listening this event type and node.

Redeploying and reloading again our web page now receives clicks and sends client events to the server using AJAX (in asynchronous-hold mode, the declared mode by default). Now both DOM elements are enabled/disabled to receive events every time the appropriate element is clicked.

The code fragment:

            ItsNatEvent itsNatEvt = (ItsNatEvent)evt;
            ItsNatServletRequest itsNatReq = itsNatEvt.getItsNatServletRequest();
            ItsNatDocument itsNatDoc = itsNatReq.getItsNatDocument();
            HTMLDocument doc = (HTMLDocument)itsNatDoc.getDocument();
    

Is used to show how the DOM Event object is implemented by ItsNat and can be used to obtain the ItsNatServletRequest object (ItsNatHttpServletRequest actually). Of course the returned ItsNatDocument is the same object as the itsNatDoc field.

The following image shows the client page state after the user clicks the first element:

We have finished our first ItsNat AJAX based web application!!

This example shows the basics, ItsNat provides many more things see the Reference Manual and JavaDoc for more info.

Terms of Use Privacy Statement Contributor Agreement delicious icon Add to delicious