Sencha Integration

 Overview

Nowadays writing a web application from scratch is not an easy task, that's why before starting any kind of development the application should be clearly planned and also should be selected a good client and server side application framework that allows creating reusable, scalable and fast web applications. jWebSocket proposes a web application development environment that can be used not only by the most skilled developers, but also the beginners.
Both, the client and the server side of jWebSocket can be theoretically integrated or embedded in any kind of technology.

In the server side:
A clear example of flexibility are the jWebSocket Engines that are based on a pure Java technology so, they can be adapted to other existing environments like Tomcat and Jetty, or can embed other environments like pure Java NIO, Grizzly, among others, to reuse from them the communication mechanism. The jWebSocket server can run multiple engine intances running on different ports. Each jWebSocket server support as many applications as required(websocket plug-ins).

In the client side:
At the client happens almost the same, as it is totally JavaScript based application, can be simply integrated to any kind of JavaScript framework, for example, jQuery, jQueryMobile, PhoneGap, Sencha Ext JS, Sencha Touch, and at the same time jWebSocket can reuse all the other frameworks and tools capabilities making it a consistent web applications development strategy.

Also in the client side each application with a processToken method can be added to the jWebSocket client side  library as a new plug-in that will be called inside a chain whenever a new message comes from the server. This makes the  jWebSocket framework a very flexible framework in both, client and server side to develop the most known real-time RIA(Rich Internet Applications) which can be reused and configured for any user or technology, getting a complete open source framework  to create their applications.

In this paper will be explained how to create a fully jWebSocket server-side application using Sencha Ext JS and Sencha Touch in the client-side as web application frameworks. At the end of this document the reader will know how to develop it's own applications and how to mix the capabilities of these amazing frameworks with a powerful real-time communication infrastructure.

What is Sencha?

Since the beginning of HTML5 and its associated technologies the web has totally been revolutioned, all the browsers automatically joined into the race to support the new specifications (WebStorage, WebSockets, Rich Media, Device Access, and many others). At the same time JavaScript developers started implementing their own mechanisms and frameworks to provide a set of tools to create applications using the new HTML5 technologies and be the first competitors.

Sencha is one of these companies that spends a lot of energy in implementing cross-browsers HTML5 and CSS3 application frameworks, providing support to the latest web technologies for mobile and stationary applications.

The name Sencha comes from the japanese "Green Tea" which since about 1200 years ago was highly valued and treasured as precious medicine is highly known around all the world. Since 2007 a small developers team under the name of Ext JS were working hardly on this product and after a lot of great improvements and auge, on June 15th, 2010, Ext JS merged all their forces with JQTouch and Raphael JS and by the first time was announced forming a new organisation called Sencha Inc.

Since 2008 Sencha has built a great reputation as leader in HTML5 Applications Development framework, so that many enterprises are encouraging to use Sencha products in order to make their development more organized and quick.

Sencha products

Sencha focuses its products in the design, development and deployment of desktop and mobile applications for the web.
The following is the list of products shown in the
Sencha website:

  • Sencha Complete
  • Sencha Touch Bundle
  • Sencha Architect
  • Sencha Touch
  • Sencha Ext JS
  • Sencha Desktop Packager
  • Sencha GXT
  • Sencha Animator
  • Sencha.io

Among other tools and products Sencha Touch and Sencha Ext JS play a fundamental role as web development platforms nowadays, slowly they have become the most complete JavaScript Application Frameworks, Sencha Touch for Mobile and Browser (Webkit based) applications and Ext JS for Web Desktop Applications. 

Sencha Ext JS


Ext JS is a pure JavaScript application framework for building interactive web applications using the latest HTML5 standards. It provides a rich set of typical UI (user interface) components in a well formed structure that are totally separated from the data management components but at the same time totally synchronized. Ext JS was originally built as an add-on library extension of
YUI (Yahoo User Interface), since it's beginning they clearly focused on implementing features more similar to those traditionally associated with desktop applications. Since the version 2.0 they included a new user documentation, an API documentation, and a lot of samples and demos to show the technology. 

Sencha Ext JS is the leading standard for business-grade web application development. With over 100 examples, 1000 APIs, hundreds of components, a full documentation suite and built in themes, Ext JS provides the tools necessary to build robust desktop applications. 

 

Some of the Ext JS 4.x features announced in Sencha website:
  • Most advanced charting and graphing capabilities of any JavaScript framework.
  • New way to build client applications, by introducing the popular MVC pattern
  • Browser independent vector graphics. Draw without worrying about SVG or VML, in IE6+ to Chrome.
  • With a well structured Data Package scalable, enterprise grade web apps can be built.
  • Grids Enhancement: locking, editing, Infinite Scrolling, Row and Cell Editors with beautiful inline edits.
  • Renders high performance DOM for each browser.
  • Powerful Theming using SASS and Compass, your whole app can be quickl themed.
  • New Class System, an object-oriented design for your applications.
  • Cross-browser layout system, allowing dock layouts, also can be applied to forms allowing more freedom in the design.
  • With Compat.js get your from 3.x project running under 4.0.
  • New Documentation API for browsers.
  • Encapsulated Architecture: Apps only bring the minimum JavaScript they need with new Ext JS 4 architecture; starting at just 100KB.
  • Select and filter Components from a Component tree, or an Array—similar to CSS selectors.
  • Improved focus manager lets users breeze through applications with their keyboard.
  • Z-Index Manager: Manage and set the z-index of windows, or any Ext JS component.


Sencha Touch

Sencha Touch is a user interface JavaScript framework built for the Mobile Web with a fully based on web standards such as HTML5, CSS3 and JavaScript development model, is intended for use by web developers to develop hight-performance HTML5 web applications that look and feel like native applications on mobile devices like iOS, Android, BlackBerry, Windows Phone, and more.
The first release of Sencha Touch, version 0.90 beta, was made available on July 17th, 2010 with support for Android, and iOS (on iPhone, iPod touch, iPad).
The last version released of these framework is Sencha Touch 2.2 which includes a lot of new features mentioned below:

  • A new Component DataView to build beautiful interfaces based on a Model and a Store.
  • Pull to Refresh and Load More plug-ins, deliver a fantastic List experience out of the box.
  • Almost any configuration of any component can be changed at run time, with a consistent and predictable API.
  • AJAX - Sencha Touch provides full AJAX support, including CORS and JSON-P.
  • DOM manipulation - Full DOM manipulation support available.
  • Feature Detection - Automatically detects the presence of features like geolocation, canvas and orientation support.
  • Geolocation - Provides a simple wrapper around geolocation on devices that support it.
  • Icons - 300 icons included.
  • Example apps - 8 full example apps included.
  • Touch events - Provides a full range of touch events and gestures like tap, swipe and pinch.
  • Sencha Touch 2 builds on the class system from Ext JS 4.
  • Back button and history-aware, you can provide a deep link to any part of your application.
  • Data-bound Carousel supporting an infinite number of items.
  • Sencha Touch 2 Device Support: (Apple, BlackBerry, Windows, Android 2.3+)
Why an integration of jWebSocket with Sencha touch and Sencha Ext JS?

Sencha Touch and Sencha Ext JS offers the most comprehensive mobile and browser application development features, all included in two easy, extendable and totally configurable frameworks.

An important percent of our community is composed by users that use these frameworks.

 
Proceeding with the integration process:
The data package

In both frameworks, Ext JS and Sencha Touch, the data package used is the same. It is composed by a set of main classes that allow the applications to persist the data in the server using a Proxy. The Proxy is used by the store to save or load data in instances of a defined Model before the information flows from the client to the server or viceversa. Each instance of the model will be accessible from the Store (Ext.data.Store), the store is the closest layer to the user interface because this one will be used by the UI components directly. The Figure 1 shows the data package used in Ext JS and Sencha Touch:


Figure1: Sencha Data Package

Proxies

The proxies are divided in two different types, Client and Server.
The Client Proxy can be divided in two main parts:
  • Memory Proxy: Stores and read data from the browser's memory with the inconvenient that the data stored here will be lost when the user refresh the browser.
  • Local Storage Proxy: Stores and loads data from the HTML 5 local storage, in case that this feature is supported by the browser.
  • Session Storage Proxy: Saves its data to a sessionStorage, in case that the browser supports it.

Sencha also includes Server Proxies are used for retrieving or sending data to the server using different communication mechanisms, some of them are:

  • Ajax: The proxy sends requests to a server on the same domain
  • JsonP: Uses JSON-P to send requests to a server on a different domain
  • Direct: Is intended to streamline communication between the client and server by providing a single interface that reduces the amount of common code typically required to validate data and handle returned data packets (reading data, error conditions, etc).

The most interesting capability that Sencha offers to the community is that any object can be easily extended, so, if you intend to create a new proxy you can simply extend Ext.data.proxy and create your own implementation, for example, a long-polling or a WebSocket proxy.

jWebSocket PlugIn for Sencha Touch & Sencha Ext JS

As Sencha doesn't include any WebSocket implementation inside it's data Model, jWebSocket Team decided at the end of 2010 to create the first implementation of a PlugIn that allowed the communication between jWebSocket server and an jWebSocket Client wrapped inside an Ext JS proxy. The first implementation of this PlugIn was called jwsExtJSPlugIn. This PlugIn since that time included not only a Proxy for jWebSocket,  but also an implementation of the Basic Form Actions (Load and Submit). Giving a WebSocket implementation to this actions the users not only were able to load the data in a Store using a Proxy, but also to communicate the Form Components with the server by executing a Load or a Submit method.
After some time of the creation of the PlugIn the jWebSocket Team decided to continue in the development and improvement of this PlugIn, so that it can also be used by Sencha Touch framework.
The last implementation of jWebSocket Sencha PlugIn was released on May, 2013, with the name jWebSocketSenchaPlugIn. The Figure 2 shows the Sencha PlugIn Class Diagram:

Figure2: jWebSocket Sencha PlugIn class diagram

Description of the packages:

A namespace for the PlugIn was required from the beginning because Sencha Touch does not include implementation for Ext.form.action.Load and Ext.form.action.Submit. All the dependencies are separated within the Ext.jws namespace, so, the user can decide which library to include and use depending on his application requirements.

  • Ext.jws.Client: Class that acts as a wrapper mechanism for the jWebSocketTokenClient class. It allows Sencha Touch and Ext JS to use the jWebSocket Client inside the Ext.jws namespace. Fires all incoming websocket messages as Events inside this class.
  • Ext.jws.data.Proxy: Implementation of an ExtJS proxy using the jWebSocket Client, opens the connection if the user forgets to invoke the open method, requires the Ext.jws.Client class.
  • Ext.jws.data.ChunkableCompressionProxy: mplementation of an ExtJS proxy using the jWebSocket connection, zip compression and chunking, in case that you wish to use compression you have to include the following files in your html file (jszip.js, jszip-deflate.js, jszip-inflate.js, jws/jszip-load.js). These files can be downloaded here https://github.com/Stuk/jszip.
  • Ext.jws.form.action.Submit: Implementation of the default Submit action of the form using the Ext.jws.Client class. This package is only to be included in Sencha Ext JS because in Sencha Touch doesn't exist anymore the Ext.form.action.Submit Class.
  • Ext.jws.form.action.Load: Implementation of the default Load action of the form using the Ext.jws.Client class. This package is only to be included in Sencha Ext JS because in Sencha Touch doesn't exist anymore the Ext.form.action.Load Class.
The Client Class (Ext.jws.Client):

In order to achieve successful integration, firstly must be wrapped the most important class of jWebSocket Client (jWebSocketTokenClient) within a namespace of Sencha. This allows the users to have direct contact from Sencha with jWebSocket Client using this class, also access the most important methods of jWebSocket Client without worrying about the complexity of it.
To make this possible was necessary to create a class called Client that will be contained inside the namespace Ext.jws. As this client should fire events whenever a new WebSocket event or message arrives, this class was extended from Ext.util.Observable which is the base class that provides a common interface for publishing events.
The class diagram shown in the Figure 3 shows a detailed representation of Ext.jws.Client class.

Figure 3: Ext.jws.Client class diagram

This class wraps the complete jWebSocket.js JavaScript library, which contains the complete implementation for the jWebSocket JavaScript Client Side.

How to include in Sencha Ext JS


The first step is including the required libraries:

<!-- Include the jWebSocket JavaScript File in your HTML -->
<script type="text/javascript" src="../../res/js/jWebSocket.js"></script>

Include in your Ext JS or Sencha Touch the path from which should load the PlugIn and then with a call to Ext.require function the loader will know  to load the Ext.jwsClient class.

// Say to Ext.Loader class from which path it should load
// the dependencies to the jWebSocketSenchaPlugIn
  Ext.Loader.setConfig( {
	enabled: true,
	paths: {
		'Ext.jws': 'path/to/your/jWebSocketSenchaPlugIn/'
	}
  } );
  // Require the client to be loaded with the Ext.Loader
  Ext.require( [
	'Ext.jws.Client'
] );

How to include in Sencha Touch:

There are two important dependencies to load, the Ext.jws.Client class and the jWebSocket.js script. The difference to include between a Sencha Touch application and an Ext JS application is almost nothing. In your Touch applications you will include the jWebSocket file inside your app.json file which contains all configurations and dependencies of your applications:

{
	"name": "myApp",
	"indexHtmlPath": "index.html",
	"url": null,
	"js": [
    // Add to your js section the new jWebSocket.js file 
    // to be loaded at startup
         {
		"path": "../../../../res/js/jWebSocket.js",
		"update": "delta"
		}//,{...}
//{...}
}

And then in your app.js file you say to the loader from which path it will automatically load the namespace Ext.jws:

//<debug>
Ext.Loader.setPath({
   'Ext': '../../../../lib/sencha/senchaTouch/src',
   // Defining the path to your jWebSocketSenchaPlugIn
   'Ext.jws': '../../../../lib/ExtJS/jWebSocketSenchaPlugIn',
   'myApp': 'app'
});
//</debug>

And then require the client in your application definition:

Ext.application({
    name: 'myApp',

    requires: [
        //...,
	'Ext.jws.Client'
        //,...
    ],
//...
How to use

The first thing the user should know is that a WebSocket connection stays opened until the user closes or updates the browser tab, invokes the close function or in the case that the server has a close timeout will close it when the timeout be over.
In both, Sencha Touch and Sencha ExtJS if they are MVC applications, you can bind the application initialization method in the same way, by listening the application.launch event to be fired:

Ext.application({
 //...
  launch: function() {
       // Adding the listeners
      Ext.jwsClient.on( {
        // fired when the connection is opened
	'open': function() {
		Ext.Logger.info( "connection Opened" );
	},
	//Adding a connection closed listener
	'close': function() {
		Ext.Logger.info( "connection Closed" );
	},
	// when the user autheticated with the server
	'logon': function( aEvent, aToken ) {
		Ext.Logger.info( "Successsfully authenticated" );
		console.log( aToken );
	},
	// When the user logout from the server
	'logoff': function( aEvent, aToken ) {
		Ext.Logger.info( "Successsfully deauthenticated" );
		console.log( aToken );
	},
	// When a message arrives from the server
	'message': function( aEvent, aToken ) {
		console.log( "new message arrived" );
		console.log( "type: " + aToken.type );
		console.log( "namespace: " + aToken.ns );
		// The detailed token from the server
		console.log( aToken );
	}
       } );
       // Finally we invoke the open method which will 
       // open the connection with the server
       // you can pass your own url of your jwebsocket server
       // Ext.jwsClient.open("ws://jwebsocket.org:8787/jWebSocket/jWebSocket")
       Ext.jwsClient.open();
       // The connection can also be closed by invoking
       // Ext.jwsClient.close();
       //...
    }
//,...
})

You can also do the same process in a normal Ext JS application by listening the Ext.onReady event:

Ext.onReady( function() {
    //...
    // Register the listeners
    // ...
    // Open the connection
    Ext.jwsClient.open();
    //...
})

Note: The Sencha Client can be used from both, Ext.jws.Client or directly from Ext.jwsClient because Sencha allows defining a class with an alternate name, so, for more facility when working with Ext.jws.Client was decided to give to this class in the alternateClassName property, the value Ext.jwsClient.

Sencha jWebSocket Proxy

One of the most important classes implemented for the PlugIn is Ext.jws.data.Proxy. As mentioned before in the proxies section, the proxy has the responsibility to get the data from the server and save it back to the server after the user makes some modifications. For the current solution was required to extend the ServerProxy class because it is the superclass for JsonPProxy, AjaxProxy and other proxy server implementations. The Figure 4 shows a Class Diagram of jWebSocket Proxy for Sencha.

Figure 4: Sencha jWebSocket Proxy Class Diagram

The Proxy requires the class Ext.jws.Client to establish the communication with the server, is highly recommended that the Ext.jws.Client open the connection itself from the application by calling the function Ext.jws.open(), however, the jWebSocket Proxy identifies if there is no connection with the server and opens the connection in it's constructor if the attrib autoOpen is set to true, by default this option is false.

jWebSocket Proxy requires two important configuration attributes, ns (Namespace) and api.

When creating a jWebSocket PlugIn in both, the server and the client side must always be set a namespace within every message interchanged. With this parameter, the PlugIns will know if the incoming messages belong or not to it and it decides how to process them.
If the user tries to create a jWebSocket Proxy and doesn't provide the ns parameter for the proxy, this will fire an Exception in the constructor of the Proxy.

Another important parameter to keep in mind is the api, it defines the specific token type to be sent to the server or to process a server response on each CRUD action methods, "create", "read", "update" and "destroy".

api: {
    create  : undefined,
    read    : undefined,
    update  : undefined,
    destroy : undefined
}

For every new jWebSocket Proxy created, the user should provide these parameters depending on the server side which type of tokens will process the incomng request, for example, in a user CRUD application the api and the namespace in the client side should be provided in the proxy:

ns: "org.jwebsocket.plugins.sencha",
api: {
    create  : "createUser",
    read    : "getUserList",
    update  : "updateUser",
    destroy : "removeUser"
}

And the server side PlugIn in JAVA should process the incoming token type by overriding the processToken method:

@Override
public void processToken(PlugInResponse aResponse, WebSocketConnector aConnector, Token aToken) {

	if (aToken.getNS().equals("org.jwebsocket.plugins.sencha")) {
		if (aToken.getType().equals("create")) {
			proccessCreate(aResponse, aConnector, aToken);
		} else if (aToken.getType().equals("read")) {
			proccessRead(aResponse, aConnector, aToken);
		} else if (aToken.getType().equals("destroy")) {
			proccessDestroy(aResponse, aConnector, aToken);
		} else if (aToken.getType().equals("update")) {
			proccessUpdate(aResponse, aConnector, aToken);
		}

	}
}

The parameters included in the request are automatically sent to the server by the Ext Components, for example if the proxy is being used in a Grid Panel, a call to the destroy method will automatically be done with the id of the selected user wanted to be removed or if the grid has a pagination option, the first call to the server will be done with a read method with the parameters start = 0, limit = 25 and in the server side you must provide an implementation to process these incoming parameters and return the corresponding page.

In every request to the server (create, read, update and destroy), the jWebSocket Proxy overrides the method doRequest changing the parameters sent from a normal Ext Component to a JSON object and including them inside the jWebSocket request parameters.

The doRequest method uses the setupDataForRequest method as auxiliary to convert a normal Request object into a jWebSocket Token. The action to be performed by the server will be the same defined in the api proxy configuration parameter. The send action is normally done using the jWebSocket Client by calling the Ext.jwsClient.send method, this method internally sends the data to jWebSocket Server and keeps the callbacks and the scope until the jWebSocket OnResponse method be executed when the server responds to the previous request. On every response from jWebSocket server will be sent a code to the client, this code indicates the state of the response, code==0: success or code == -1: failure.

The response for a previous request from the proxy will execute the method processResponse with the data received from the server and a boolean result from the success response, true or false, this will internally synchronize with the Ext Components that are waiting for the response.

Using jWebSocket Proxy

In both, Sencha Touch and Sencha Ext JS, the proxy can be included in your application in the same way is included the Ext.jws.Client:

 // The proxy requires both, the client and the proxy classes
  Ext.require( [
	'Ext.jws.Client',
	'Ext.jws.data.Proxy'
] );

After all dependencies are included in our application, is important to know how to use the proxy and define the root from which the reader will read and decode the incoming data within the token:

var lJWSProxy = new Ext.jws.data.Proxy({
	ns: "org.jwebsocket.plugins.sencha",
	api: {
		create: "createUser",
		read: "getUsers",
		update: "modifyUser",
		destroy: "deleteUser"
	},
	reader: {
               // The implementation in jWebSocket Server
               // should send the response with the 
               // name 'data' inside the token
		root: 'data',
		totalProperty: 'totalCount'
	},
        autoOpen: true  // open jWebSocket connection automatically,
                        // this option is not required, false by default
});

Once the proxy is configured you can use it in any component, first you define a model to give some structure to the data that the server will send:

Ext.define( 'User', {
	extend: 'Ext.data.Model',
	fields: ['id',
		'name',
		'email',
                'age']
} );

Then the proxy can be used by any kind of store:

var lStore = new Ext.data.Store( {
//		autoSync: true,
		autoLoad: true,
		pageSize: 10,
		model: 'User',
		proxy: lJWSProxy
	} );

With the option autoSync: true, the store will automatically save the changes in the server after any row in the store is changed. With the autoLoad option set to true, the proxy will automatically load the data from the server when the store be instantiated.
With jWebSocket Sencha Proxy the user will have the same capabilities as with any other proxy, making the jWebSocket communication transparently for the UI components and reaching in his application a Real-Time communication mechanism.

Taking a look to the Figure 5 can be appreciated the first request made by the Proxy to the server in the websocket section from the network console viewer. As the store has an autoload property set to true, the proxy automatically asks for the first page of data to the server with the configured parameters in the store:

Figure 5: WebSocket requests made by the Sencha Proxy to the server. 

jWebSocket Chunkable Compression Proxy

One of the major requirements of the web today is to send and receive large amounts of data in the shortest time possible without any loss of information. JWebSocket Chunkable Compression Proxy for Sencha is designed to be used in case of the data to be transmitted is very big. jWebSocket server defines a timeout to write the data to the user, if this timeout is over, then the server won't send this data to the client, to avoid this, is necessary to split the information in little pieces of a certain type of stream, this stream will be transmitted from the server to the client or viceversa until the last stream arrives. Every chunk will have the following structure:

{
	"chunkType": "stream0",
	"data": "", // the data can be something like this: 
                  // "UEsDBBQACAgIAEmNvEIAAAAAAAAAAAXXLk1.......=", 
	"ns": "org.jwebsocket.plugins.sencha", 
	"type": "getTreeStructure", 
	"isChunk": true, 
	"isLastChunk": false 
}

jWebSocket Chunkable Compression proxy will allow to the users to receive big amounts of data that will be loaded into the stores and the UI components automatically when the last chunk arrives from the server. The Chunkable Compression Proxy is an extension of Sencha jWebSocket Proxy that allows not only to send and received chunked data from the server, but also to compress the data to be sent or uncompress the data from the server. jWebSocketChunkableProxy supports two different types of compression mechanisms at the moment:

  • zip
  • zipbase64

Both types of compression can be passed to the proxy configuration in its constructor but with the condition that they require the files jszip.js, jszip-deflate.js, jszip-inflate.js and jszip-load.js, in case that the user does not configure the proxy to compress the data, then these files won't be a requirement anymore and the data will be chunked and sent without compression.

The ChunkableCompressionProxy is also delivered in the package jWebSocketSenchaPlugIn, within the namespace Ex.jws.data, the Figure 6 shows   class diagram shows more clear the implemented Proxy and it's dependencies.

Figure 6: jWebSocket Chunkable Compression Proxy for Sencha.

For more information, there is a detailed explanation of the jWebSocket fragmentation mechanism here.

How to use the Chunkable proxy

The proxy depends on both, the server and the client side, for this example is used the server implementation made for the fragmentation article in our documentation, it can be found here.
Change the loader configuration to load the namespace Ext.jws from our PlugIn root folder:

  Ext.Loader.setConfig( {
	enabled: true,
	paths: {
		'Ext.jws': 'path/to/your/jWebSocketSenchaPlugIn/'
	}
  } );

Then in the client side will be necessary to include the dependencies of the Chunkable Proxy:

// The proxy requires both, the client and the proxy classes
  Ext.require( [
	'Ext.jws.Client',
	'Ext.jws.data.Proxy',
        'Ext.jws.data.ChunkableCompressionProxy'
] );

And then create an instance of the proxy:

var lUsersProxy = new Ext.jws.data.ChunkableCompressionProxy( {
		ns: "",
		// compression types
		//    * zipbase64
		//    * zip
		//    * none 
		// Note: zipbase64 and zip require (jszip.js, jszip-deflate.js, 
		//       jszip-inflate.js, jws/jszip-load.js)
		// in case you set "none" or you omit this field compression won't be required
		compression: 'zipbase64',
		api: {
			read: 'getUsers'
		},
		reader: {
			chunks: true, //This means that the data will be read in chunks
			root: 'data',
			totalProperty: 'totalCount'
		}
	} );

In case that the user wants to send the data to the server also in chunks then will be necessary to configure in the writer a new parameter, chunks: true:

writer: {
	chunks: true, //This means that the data will be sent
                     // in chunks to the server
		}

Sencha Form Actions

Sencha provides not only a communication via proxy, there are some other parts in our application that is required to send our data to the server or load data from the server. The forms are a clear example of that, since they were created was thought how to send the data to the server, the html form itself has it's own basic submit method that allows sending the data to a form processing agent which generally is in the server side. The w3c Recommendation website offers a clearer explanation of what is an html form action and its parameters. 

Today there are many other techniques to send data to the server, not only using a normal http request, that's why Sencha implemented a new way to load and send data from the client to the server, they included other communication mechanisms within the submit and the load methods of their form panel components. 

In both, Ext JS and Sencha Touch the process to submit and load data into an Ext.form.Panel component is handled in a different ways. Today jWebSocket brings to the community a total integration with the form submit and load actions based in a WebSocket communication.
Basically a Sencha action is composed by almost the same parameters, the user sends his formulary to the server, specifying an url, a method to send the data, the form data to be processed and waits for the server response by providing implementations for the callbacks, success and failure.

Form actions in Ext JS

Ext JS provides a beautiful data structure to deal with the form actions. An Ext JS form action is a class that extends from Ext.form.action.Action. The subclasses of this abstract instance provide actions to perform upon Ext.form.Basic Form, the instances of this class will only be created when the form needs to perform a certain action, load or submit.

For a better understanding of the Ext JS actions, the Figure 7 shows the requirements, inheritance and some other relations between the classes Ext.form.action.Action and Ext.form.Basic.

Figure 7: Ext.form.action.Action and Ext.form.Basic class diagram.

The Ext.form.Basic class using the doAction method instantiates the required action classes depending on the passed action in the configuration of the submit or the load method of the form. The following example shows how to create a normal submit action using an Ext.form.Panel created by the user:

myFormPanel.getForm().submit({
    clientValidation: true,
    url: 'updateConsignment.php',
    params: {
        // These are aditional params you may need to send
        // the form fields are included internally in the request
        newStatus: 'delivered'
    },
    success: function(form, action) {
       Ext.Msg.alert('Success', action.result.msg);
    },
    failure: function(form, action) {
        switch (action.failureType) {
            case Ext.form.action.Action.CLIENT_INVALID:
                Ext.Msg.alert('Failure', 
               'Form fields may not be submitted with invalid values');
                break;
            case Ext.form.action.Action.CONNECT_FAILURE:
                Ext.Msg.alert('Failure', 'Ajax communication failed');
                break;
            case Ext.form.action.Action.SERVER_INVALID:
               Ext.Msg.alert('Failure', action.result.msg);
       }
    }
});

The previous example was taken from the official Ext JS Documentation.

 
Using jWebSocket in Form Actions

After seeing the previous explanation of Ext JS actions, the user can realize that with an extension of a new type of submit and load actions is easy to use another type of communication to exchange the data with the server. jWebSocket Sencha PlugIn offers an override mechanism for both, load and submit actions, in the Figure 8 you can see how a normal action can be extended using other communication, in this case is aided by jWebSocket token client to send data to the server. Moreover it is necessary to overwrite the prototype of the methods load and submit from the class Ext.form.Basic, this action must be performed after all the Ext components are loaded, otherwise it won't work and will generate an error. 

Figure 8: Class diagram for Sencha Ext JS Form Actions jWebSocket based.




How to make the form actions work in Ext JS with jWebSocket transparently for the users?

1- Dependencies:

Ext.Loader.setConfig({
	enabled: true,
	paths: {
		'Ext.jws': 'path/to/your/jWebSocketSenchaPlugIn/'
	}
});
Ext.require([
	'Ext.jws.Client',
	'Ext.jws.form.action.Load',
	'Ext.jws.form.action.Submit'
]);

2- Tell to the new form that will use jWebSocket to load and submit data. For every form that the user wants to use jWebSocket will have to use the property jwsSubmit:

var lFormPanel = Ext.create('Ext.form.Panel', {
                // with this property enabled, each submit or load will be 
                // done with jWebSocket
		jwsSubmit: true,
                // ...
		items: [{
				xtype: 'hidden',
				name: 'id',
				id: 'id'
			}, {
				xtype: 'textfield',
				name: 'name',
				id: 'name'
                                // validations, etc..
			}, {
				//...
			}]
                });
                       

3- The namespace and the tokentype:
As explained previously, each request to jWebSocket server instead of an URL requires a namespace and a tokentype, so, the server side will automatically know which PlugIn will process the request from the client. The user can provide the namespace and tokentype in two different places:

  • In the form configuration attributes:
var lFormPanel = Ext.create('Ext.form.Panel', {
      jwsSubmit: true,
      ns: 'org.jwebsocket.plugins.sencha',
      tokentype: 'create'
      // ...
    });
  • As parameters when run the Submit or Load methods from the form:
var lForm = lFormPanel.getForm();
var lAction = {
	ns: 'org.jwebsocket.plugins.sencha',
	tokentype: 'read',
	params: {
	      id: 1  // The user id to load from the server side
	}
};

lForm.load(lAction);

4- Loading and Submitting data:

The load method

Normally the data is not so often required to be loaded directly from the server into the form, that's why sencha touch doesn't include support for this method anymore. Instead of this, the user can use a proxy that loads all the required information from the server and then select from the store one of the rows and load it into the form: 

var lRecord = lStore.getAt(lIndex);
lForm.loadRecord(aRecord);

However, jWebSocket also supported the Ext JS load method, so is possible to load the data from the server into your form. The Ext.jws.form.action.Load class is never used directly, this class will be instantiated by the internal doAction method of the form.

var lAction = {
	ns: 'org.jwebsocket.plugins.sencha',
	tokentype: 'read',
	params: {
	      id: 4
	},
        // Optional
		// Optional
	success: function(aForm, aToken) {
		console.log("success");
		console.log(aToken);
	},
	failure: function(aForm, aToken) {
		console.log("failure");
		console.log(aToken);
	}
};

Ext.getCmp("myForm").load(lAction);

When the request comes from the server, the success method is fired with the incoming token, the console log is shown in the Figure 9:

Figure 9: Result of a console.log in the success callback of the form.load action 

In the server side implementation for the load action should be like this:

public class SenchaDemoPlugIn extends TokenPlugIn {

    public static final String NS_SENCHA_DEMO =
JWebSocketServerConstants.NS_BASE + ".plugins.sencha";

	@Override
	public void processToken(PlugInResponse aResponse,
			WebSocketConnector aConnector, Token aToken) {
		if (aToken.getNS().equals(getNamespace())) {
                     if (aToken.getType().equals("read")) {
				proccessRead(aConnector, aToken);
			}
		}
	}

  private void proccessRead(WebSocketConnector aConnector, Token aToken) {
		try {
			Token lResult = createResponse(aToken);
			FastList<Token> lResultList = new FastList<Token>();
			Integer lId = aToken.getInteger("id");
                        // this is the case, the client is sending an id
			if (lId != null) {
				User lUser = mUsers.getCustomer(lId);
				if (lUser != null) {
					Token lAuxToken = TokenFactory.createToken();
					lUser.writeToToken(lAuxToken);
					lResultList.add(lAuxToken);
				} else {
					lResult.setString("msg", "The user with id: " + lId
							+ " does not exist in the server");
					lResult.setCode(-1);
				}
			} else {
		         // If no parameter id is provided is because the client 
                         // wants a list of users, check jWebSocketSenchaPlugIn for 
                         // more details of the server side implementation
			}

			lResult.setList("data", lResultList);

			getServer().sendToken(aConnector, lResult);
		} catch (Exception aException) {
			getServer().sendErrorToken(aConnector, aToken, -1, "The following "
					+ "error was captured in the server: " + aException.getMessage());
		}
	}

The submit method

Replaces the normal submit form action with a jWebSocket Submit if the user sets to the form the property jwsSubmit: true, the following example shows how to create a user in the server:

var lNamespace = 'org.jwebsocket.plugins.sencha';
var lFormPanel = Ext.create('Ext.form.Panel', {
      jwsSubmit: true,
      ns: 'org.jwebsocket.plugins.sencha',
      tokentype: 'create',
      items: [{
	xtype: 'hidden',
	name: 'id',
	id: 'id'
}, {
	xtype: 'textfield',
	name: 'name',
	id: 'name',
	fieldLabel: 'Name',
	allowBlank: false,
	emptyText: 'required...',
	blankText: 'required',
	minLength: 2
}, {
	xtype: 'textfield',
	name: 'email',
	id: 'email',
	fieldLabel: 'email',
	vtype: 'email',
	allowBlank: false,
	emptyText: 'required...'
}, {
	xtype: 'textfield',
	name: 'age',
	id: 'age',
	fieldLabel: 'Age',
	vtype: 'num',
	emptyText: 'required...',
	allowBlank: false
}, {
	xtype: 'button',
	text: 'Add User',
	id: 'submit_button',
	width: 120,
	handler: function() {

	   var lForm = this.up('form').getForm();
	   var lAction = null;
	   if (lForm.findField('id').getValue() != "") {
		lAction = {
			ns: lNamespace,
			tokentype: 'update',
			params: {
				updateForm: 'yes'
			}
		}
	} else {
		lAction = {
			ns: lNamespace,
			tokentype: 'create'
		}
	}
	lAction.failure = function(aForm, aAction) {
		if (aAction == 'undefined') {
			var message = "Please you have errors in the form";
			console.log( message);
		} else {
			console.log( aAction.response.message);
			}
	}
	lAction.success = function(aForm, aAction) {
		Ext.getCmp('submit_button').setText('Add User');
		aForm.reset();
		console.log("token received with code: " + aAction.response.code + 
                            ", and message: " + aAction.response.message);
	}

	 if (lForm.isValid()) {
           // submitting the form data to the server
	   lForm.submit(lAction);
           } else {
		console.log( "Please you have errors in the form" );
	   }
	}
    }]
});
Form actions in Sencha Touch

Sencha Touch does not include support anymore for Ext.form.Basic, and doesn't include the Ext.form.action.Action, the submit process is implemented locally in the submit method inside the Ext.form.Panel class, currently there are two types of submit allowed, standard submit or ajax submit. As there are no actions to extend anymore, it was necessary to create a structure that overrides the default submit method from the form, the Figure 10 shows a detailed class diagram where the user can see the simplicity of this implementation.

Figure 10: Implementation of Ext.jws.form.Panel overriding the submit method from Ext.form.Panel class.

Such like in the Ext.form.Basic.submit, the Ext.form.Panel submit action implements it's own way to handle the submit types, that's why it was necessary to override only the submit class, Sencha allows overriding a whole class or only some of it's methods, that's why in this case was created the class Ext.jws.form.Panel that contains the override for the submit method using jWebSocket.
As well as in the Ext JS forms, there is a new parameter for the forms created with Sencha Touch to allow sending using jWebSocket or not, the property name is jwsSubmit, with a boolean value, false by default.
Maybe you are wondering, but how is this possible? Ext allows overriding any class or method of a class, by using the magic word override when defining a new class.

Ext.define('Ext.jws.form.Panel', {
	override: 'Ext.form.Panel',
        requires: ['Ext.jws.Client'],
	alternateClassName: 'Ext.jwsFormPanel',
	ns: undefined,
	tokentype: undefined,
	submit: function//...

How to use the Ext.jws.form.Panel.submit action in a Sencha Touch application?
First include point the loader to load the dependencies from the jWebSocket Sencha PlugIn root folder:

Ext.Loader.setPath({
	'Ext': 'touch/src',
	'Ext.jws': '../../../lib/ExtJS/jWebSocketSenchaPlugIn',
	'myApp': 'app'
});

And then require all the dependencies to override the form.submit action transparently using jWebSocket:

Ext.application({
	name: 'myApp',
	requires: [
                //...
		'Ext.form.*',
		'Ext.jws.Client',
		'Ext.jws.form.Panel'
	],
//...

The last step is create the form and submit it :)

Ext.define("myApp.view.user.Edit", {
  extend: 'Ext.form.Panel',
  xtype: 'useredit',
  id: 'userEdit',

  jwsSubmit: true,
  ns: 'org.jwebsocket.plugins.sencha',
  tokentype: 'update',

config: {
  items: [{
		xtype: 'textfield',
		name: 'name',
		label: 'Name'
	}, {
		xtype: 'emailfield',
		name: 'email',
		label: 'Email'
	}, {
		xtype: 'numberfield',
		name: 'age',
		label: 'Age'
	}, {
		xtype: 'button',
		name: 'Submit',
		text: 'Submit',
		handler: function() {
		  this.parent.submit({
		      params: {
			 // This is just for test purposes, normally the id 
			 // field can be provided in the form parameters 
			// within a hidden field
			id: 4
		      },
		      success: function(aForm, aToken) {
			  console.log("success");
			  console.log(aToken);
		     },
		     failure: function(aForm, aToken) {
			console.log("Failure");
			console.log(aToken);
		     }
		   });
		}
	}
	]}
});

After clicking the submit button in our application, the results are shown in the Figure 11 and Figure 12:

Figure 11: Result Token in the console after executing the submit action
in the Sencha Touch jWebSocket Demo.

The changes are also automatically notified to the Sencha Ext JS Demo, in the Figure 12 can be seen how the server notified all connected clients with the user updated:

Figure 12: Ext JS jWebSocket demo notified by a form submit in the Sencha Touch demo.

Conclusions

This work has made ​​possible a total integration of jWebSocket technology in Sencha Sencha Touch and Sencha Ext JS frameworks. This allows to both developers communities jWebSocket and Sencha, having a two powerful frameworks in both, client and server side to develop applications that require real-time communication.
With the new version of jWebSocket has been released the new jWebSocketSenchaPlugIn that includes a WebSocket communication transparently for all Sencha Ext JS and Sencha Touch components, preventing the user from having to worry about communication and focusing on creating a better and solid application. jWebSocket framework offers to the community a full open source Java/JavaScript application development framework aimed to create powerful and scalable applications, easy to understand and with a quick learning curve.


Copyright © 2013 Innotrade GmbH. All rights reserved.