Home Overview Demos/Webs News Download/Install Docs/Support Investors/Partners Commercial Tutorial: Simple ItsNat (Core) Application Tutorial: Simple ItsNat (Core) STATELESS Application Tutorial: Single Page Interface SEO Compatible Web Site With ItsNat STATEFUL Using HASHBANGS Tutorial: Single Page Interface SEO Compatible Web Site With ItsNat STATELESS Using HASHBANGS Tutorial: Single Page Interface SEO Compatible Web Site With ItsNat STATEFUL Using HISTORY API Tutorial: Single Page Interface SEO Compatible Web Site With ItsNat STATELESS Using HISTORY API Tutorial: Hybrid Client-Server Centric Programming
Tutorial: Single Page Interface SEO Compatible Web Site With ItsNat STATELESS Using HASHBANGS

Last update: 2015, Sept. 27  

Introduction

Introduction/Setup
SPI, SEO compatiblity and Stateless relationship
Web application set-up
Creating the ItsNat servlet
Main page processing
Main page processing stateless
Main page processing and hashbangs
Infrastructure of fundamental states
Conclusion
Download and Online Demo

This tutorial shows the stateless SPI web site version of this stateful using hashbangs tutorial, reading the stateful version first is highly recommended, main ItsNat concepts are not going to be repeated in this tutorial and some parts of the stateless version are identical to stateful.

The objective of this tutorial is to make a Single Page Interface SEO Compatible Stateless using Hashbangs website. It is based on the stateless mode introduced in ItsNat v1.3. When we say stateless we mean there is no need of server affinity or session data sharing, in this mode ItsNat does not use the built-in web session system of your Java app server, therefore client requests of the same page can target any node in a cluster of symmetric nodes with the same ItsNat website.

To understand this tutorial some basic knowledge of ItsNat is required, especially the stateless mode.


SPI, SEO compatiblity and Stateless relationship


The SEO compatibility of ItsNat has not very much to do with stateful or stateless modes, the key feature is fast-load mode (the default mode), when the initial page (based on a pure HTML template) is being loaded, any DOM change performed in server is not sent as JavaScript, DOM rendering to generate the initial HTML page being sent to the client, is done after the user code in server is executed. Hence the same developer code manipulating DOM can generate JavaScript or plain HTML depending on the phase is executed, when an event is received (JavaScript) or on load time of the initial page (HTML).


Web application set-up


ItsNat does not require special set up or application servers, any servlet container supporting Java 1.6 or upper is enough. Use your preferred IDE to create an empty ItsNat web application, this tutorial uses spistlesshashbangtut as the name of the web application.


Creating the ItsNat servlet


Create a servlet as explained in stateful hashbang tutorial.

According to this setup the URL accessing our servlet is (8080 is supposed):

http://localhost:8080/spistlesshashbangtut/servlet

Because our web site is SPI we would like a prettier URL like

http://localhost:8080/spistlesshashbangtut/

Configuration of web.xml is the same as stateful hashbang tutorial:

  1. Add the servlet as the welcome file
  2. Add a simple index.jsp (this file is usually by default the "welcome file") with this content:

Now replace the generated code of the servlet class with this code:

It is very similar to the stateful version but with some subtle differences:

  • No interest in sessions, for instance no need to specify the number of max sessions like itsNatCtx.setMaxOpenDocumentsBySession(4);.
  • No global event listener is registered, this code itsNatServlet.addEventListener(new SPITutGlobalEventListener()); is missing because the purpose of SPITutGlobalEventListener was to ask users what to do when session is lost.
  • Events of "main" documents are explicitly disabled by calling docTemplate.setEventsEnabled(false);, this is required to make this page stateless (page/document is loaded but not retained in server in sync with client), this call is needed because by default is stateful.

In this example the default URL is:

http://localhost:8080/spistlesshashbangtut/

The main page of our web site is loaded as explained in the stateful hashbang version.


Main page processing


Returning to the servlet:

This call registers with the name "main" the page template file main.html (saved in WEB-INF/pages/):

<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml" xmlns:itsnat="http://itsnat.org/itsnat">
<head>
    <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
    <meta http-equiv="Pragma" content="no-cache" />
    <meta http-equiv="expires" content="Wed, 1 Dec 1997 03:01:00 GMT" />
    <meta http-equiv="Cache-Control" content="no-cache, must-revalidate" />
    <title id="titleId" itsnat:nocache="true">Tutorial: Single Page Interface SEO Compatible Web Site With ItsNat STATELESS Using Hashbangs
    <link rel="stylesheet" type="text/css" href="css/style.css" />
    <script type="text/javascript" src="js/spi_hashbang.js?timestamp=2015-08-18_01"></script>
    <script type="text/javascript">
    function setState(state_name,state_secondary_name)
    {
        if (typeof document.getItsNatDoc == "undefined") return; // Too soon, page is not fully loaded
        var userEvt = document.getItsNatDoc().createEventStateless();
        userEvt.setExtraParam('itsnat_doc_name',"main");
        userEvt.setExtraParam('state_name',state_name);
        if (state_secondary_name) userEvt.setExtraParam('state_secondary_name',state_secondary_name);
        document.getItsNatDoc().dispatchEventStateless(userEvt, 3 /*XHR_ASYNC_HOLD*/, 1000000);
    }
    window.spiSite.onBackForward = setState;

    function removeById(id)
    {
        var elem = document.getElementById(id);
        if (!elem) return;
        elem.parentNode.removeChild(elem);
    }
    </script>
</head>
<body>

<div class="main">
    <table style="width:100%; height:100%; padding:0; margin:0;" border="0px" cellpadding="0" cellspacing="0">
    <tbody>
    <tr style="height:50px;">
        <td>
            

Tutorial: Single Page Interface SEO Compatible Web Site With ItsNat STATELESS
Using Hashbangs

</td> </tr> <tr style="height:40px;"> <td> <table style="width:100%; margin:0; padding:0; border: #ED752A solid; border-width: 0 0 2px 0; "> <tbody> <tr class="mainMenu" itsnat:nocache="true"> <td id="menuOpOverviewId"> Overview </td> <td id="menuOpDetailId"> Detail </td> <td> </tr> </tbody> </table> </td> </tr> <tr style="height:70%; /* For MSIE */"> <td id="contentParentId" itsnat:nocache="true" style="padding:20px; vertical-align:super;" > </td> </tr> <tr style="height:50px"> <td style="border-top: 1px solid black; text-align:center;"> SOME FOOTER </td> </tr> </tbody> </table> </div> <iframe id="googleAnalyticsId" itsnat:nocache="true" src="?ganalyt_st=" style="display:none;" ></iframe> <script> (function(i,s,o,g,r,a,m){i['GoogleAnalyticsObject']=r;i[r]=i[r]||function(){ (i[r].q=i[r].q||[]).push(arguments)},i[r].l=1*new Date();a=s.createElement(o), m=s.getElementsByTagName(o)[0];a.async=1;a.src=g;m.parentNode.insertBefore(a,m) })(window,document,'script','//www.google-analytics.com/analytics.js','ga'); ga('create', 'UA-2924757-6', 'auto'); ga('send', 'pageview'); </script> </body> </html>

This template is very similar to the stateful example, the main difference is the JavaScript code:

The setState method sends an "ItsNat stateless event" to server (take a look to the call dispatchEventStateless(...) call) providing the necessary info to generate a new state in server to propagate back to client. A stateless event is an extension of W3C DOM Events defined by ItsNat and is fired calling some public ItsNat methods from JavaScript like dispatchEventStateless(...).

Because the stateless nature of this example, the server does not remember any data sent by client, just generate the according Javascript code and markup to change the state in client and forget the request. The result is the same as the stateful hashbang example but with a different (stateless) approach based on the stateless capabilities of ItsNat.

Stateless events are used in this tutorial to notify the server about the next fundamental state to be loaded (in the stateful example stateful custom user events were used), any received stateless event in server will load a document specified by itsnat_doc_name parameter and will be processed by an event listener in server previously registered in the just loaded document.

Back to the servlet we also register a load listener for the main template:

The SPITutMainLoadRequestListener class is the same as the stateful hashbang example.

In stateless the SPITutMainLoadRequestListener.processRequest(…) method will be called in two different scenarios:

  1. When the servlet receives a new load request of this template that is when initially loading the page, conventional use
  2. When a stateless event has been received in server specifying the template of this document (load phase of stateless event processing)

In this tutorial the same template is going to be used for the initial load and for stateless event processing, this is the simplest (not mandatory) option, in this case is appropriated because the template is very simple, everything is in the same position when the page is loaded and when processing stateless events, there is no need of locById attributes in this tutorial (please read first about how ItsNat support stateless apps in Manual, a tutorial about using stateless mode exists).

A new SPITutMainDocument instance is created per call (load request), this instance holds an ItsNatHTMLDocument object which represents the client document (page) being loaded as usual.

Unlike the stateful mode, SPITutMainDocument objects are not going to be retained in server because the page template was registered "stateless" calling docTemplate.setEventsEnabled(false);, and when a SPITutMainDocument is created to dispatch a stateless event, this document object is ever stateless (not retained in server) because the nature of stateless event processing.

The class SPITutMainDocument inherits from SPIStlessHashbangMainDocument the main class of the mini-framework to create SPI SEO compatible stateless based on hashbang web sites under the package org.itsnat.spistlesshashbang.

Again we are using a mini-framework in this tutorial:

  1. org.itsnat.spi: generic classes, same as all other SPI web site tutorials

    Classes: SPIMainDocumentConfig, SPIMainDocument, SPIState, SPIStateDescriptor

  2. org.itsnat.spistless: stateless specific

    Class: SPIStlessMainDocument

  3. org.itsnat.spistlesshashbang: stateless and hashbang processing specific

    Classes: SPIStlessHashbangMainDocument

We are not going to explain the classes of the package org.itsnat.spi because they are the same as seen in stateful hashbang tutorial. Note there is no SPIStlessState class (not needed).


Main page processing stateless


Now is time to step down to describe how the mini-framework manages a stateless web site.

There is only one class into the package org.itsnat.spistless: SPIStlessMainDocument.

Some parts of this class are very similar to the stateful example, others are very different.

For instance:

The method isCreatedByStatelessEvent() is used to distinguish conventional load page from stateless event processing, in case of document load for stateless event processing we must register a listener going to be called inmediatelly after the load phase of the document created by the stateless event, because a new special stateless event is again (and automatically) fired.

Some things are different when processing a stateless event, the client page is loaded to be modified generating JavaScript in the event listener dispatch phase but the document loaded may differ from the client state, for instance, this is the reason of this DOM cleaning in client to prepare the client to receive the new inserted markup of the new state, take a look to the code of changeState():

Some explanation is needed: the method changeState is going to be called in three different phases:

  1. When the initial page loads (isLoading() is true): markup of the fragment content is inserted as markup (because fast-load mode is enabled)
  2. When the document for processing a stateless event loads (isLoading() is true): markup of the fragment content is inserted as DOM, no JS is generated in this load phase (normal behavior when processing a stateless event)
  3. When the stateless event is being dispatched by the registered event listener ((isLoading() is false): modified DOM generates JavaScript to be sent to client, this is the reason of custom code to clean the current content in client, because the no initial content is defined in the document loaded to process the stateless event.

This event ItsNatEventDOMStateless itsNatEvt is dispatched by the event listener that was registered on load time when the document is loaded by a stateless event, and executed just after the load phase, this stateless event transports the necessary data sent by the client to change the state in client, because this is the stateless event in dispatching phase any change to the DOM will generate JavaScript DOM code to do the same in client to bring the just loaded document to the required state in client.


Main page processing and hashbangs


Time to another step down to know how to manage hashbangs.

The package org.itsnat.spistlesshashbang has only one class SPIStlessHashbangMainDocument, yes this class inherits from SPIStlessMainDocument and specifies how to manage hashbangs in this stateless context.

Code is basically the same as stateful but the sentence if (!itsNatDoc.isCreatedByStatelessEvent()), because this code only apply to normal page loading, not for stateless event processing (even in load phase).

Everything explained in stateful hashbang tutorial about Google AJAX Crawling specification is also applied here.

Because this tutorial uses hashbangs, the JavaScript library spi_hashbang.js is the same as the stateful version.


Infrastructure of fundamental states


Now is the time to deep inside a concrete example using our mini-framework. We must to define the fundamental states being used as examples in this SPI web site.

This is the source code of the concrete SPITutMainDocument inherited from SPIStlessHashbangMainDocument:

Code is similar to the stateful version but not the same, in stateless we need to provide the necessary data from client to recreate in server the client state and perform the required operations to change the client to a new state.

For instance:

State definition is very different in stateless, in stateful we can easily remember in server the current state in client, in stateless is not possible unless you make some custom use of session, we are not going to use sessions in no way, so we need the necessary data from client, this is the reason of the state_secondary_name parameter received for instance to insert and manage the "detail" state and "more detail" substate, whether "more detail" must be "shown" or "hidden".

This is the detail.html link used to change from "show" to "hide" and viceversa:

    Hide|More Detail

The attribute action is defined to save in client the current state of the page, and used to send to the server the current state to change accordingly. In this example we only need a second parameter, more complex seb sites will require a more complex context captured to send to server.

This code is different to the stateful version, we know the new menu item to activate but we do not know what is the current selected (remember it is stateless), therefore we clear all menu items and select the new active (this method is called by the base class for all menu items).

This is the SPITutStateDetail:

States are inherited from org.itsnat.spi.SPIState, no need of dispose method (necessary in stateful).

In stateless there is less automatic management of client state and some custom JavaScript is convenient, for instance:

This code calls the auxiliary JavaScript method removeById defined in client to remove the "more detail" content, this is needed because by default our stateless document do not include a "more detail" fragment DOM, in practice you usually do not need automatically generated JavaScript from server to remove code in client because removing code is a very easy task in client, ItsNat helps you a lot in stateless for inserting big and complex parts of markup in client usually mixed with data loaded in server, but removing client DOM is trivial with custom JavaScript.

The state "overview" including a popup ("overview.popup") is an example of how we can make a limited use of ItsNat components also in stateless:

Remaining classes SPITutGlobalLoadRequestListener, SPITutMainLoadRequestListener are the same as stateful hashbang counterparts. In stateful has no sense a SPITutGlobalEventListener as explained before.


Conclusion


This tutorial has shown a generic example of how to build SPI stateless using hashbangs web sites with ItsNat similar to page based counterparts without sacrificing the typical features of the page paradigm like bookmarking, SEO, JavaScript disabled, Back/Forward buttons (history navigation), page visit counters etc. Use the mini-framework to build your SPI sites using this approach if you want.


Download, Online Demo and Links


See running online (try to clear cookies to check there is no need of keep client state in server)

Download source code in GitHub.




Terms of Use Privacy Statement Contributor Agreement Add to deli.cio.us Single Page Interface logo ItsNat logo Innowhere logo