ZK10 Preview: Diving into Stateless Components
Matthieu Duchemin, Engineer, Potix Corporation
August 23, 2022
ZK 10 CE, PE, and EE
Introduction
ZK 10 introduces a new set of Stateless components called I-Components. In this smalltalk, we will discuss the use case for these components as well as how to implement a document using them.
This is a follow-up on the previous ZK10 Preview smalltalk.
Overview
First, we need to understand the differences between classic ZK components, and the new Stateless components.
Classic ZK overview
Classic ZK components are stored in the HttpSession on the server side. Based on the Java EE Web application specification, a session is an object which exists in memory on the server side. When a web browser sends a request to the server, it also sends a session identifier. This is commonly done with a JSESSIONID cookie or through a URL parameter.
Based on this identifier, the Web Server will retrieve the session object from memory and make it available while processing the response to the user's request. This allows the server-side application to store various objects semi-permanently in the server's memory until the session is destroyed.
In the classic use case, the page generated by ZK exists in the session. When the user triggers an action or changes the state of a component on the client-side, a request is sent to the server and updates the "main state" of the components which exist in the session. In this workflow, the server-side state is authoritative, and the client-state is synchronized based on the server-side state.
Stateless components overview
The stateless components are not stored in the server's memory. They are transient objects which only exist during the user's request and response cycle.
In this case, the authoritative state is located on the client-side. Updates performed with Stateless components are done on a "per action" basis.
Each action has a set of "Action parameters", which indicates what data needs to be retrieved from the client in order to process a given action. This way, no server-side record of the page's state is required. When the user triggers an action, the client-side engine will fetch the properties and values requested by the action and sends all relevant data in the request.
The server-side action will then process any relevant update based on that data and the event triggered by the user. At the end of that processing, the action may modify the state of the client and send a response that will write the new state on the client-side.
During this process, the action only used the information retrieved by the action parameters. As such, it did not need to access any data located on the server-side.
Use cases
Stateless use cases
The main point of a page generated by the ZK 10 Stateless components is that it doesn't have an associated user session.
This is beneficial in a number of scenarios in which session access, session control, and session replication are difficult.
Arbitrary containers
Let's consider an application using a platform such as a docker or manually instantiated and terminated copies of the same services such as spring boot.
Establishing session replication, sticky session (request priority given to the same node having processed the previous request by the same actor, if it is still available), and session failover can be challenging.
Since a page created with Stateless components doesn't rely on the user session to store the state of the components, the infrastructure can be simplified by not implementing these aspects.
Limited server-side memory per user
Some platforms have a limited user session size or provide a serialized shared session object between all server nodes with a limited size. The Stateless components workflow is a good candidate for such infrastructures since it doesn't rely on sessions, and doesn't keep objects in memory between transactions.
Even outside of a cloud platform, the same low-memory footprint can be useful and performant for a classically deployed application.
Composed page from multiple services
While a page can be composed of documents generated by both classic ZK and stateless components, the stateless components are a good fit for smaller scales "input and output only" services with a limited scope.
Depending on the need for integration vs compartmentalization, the main page can integrate services generated by either classic ZK or by a Stateless Richlet as "page elements".
This is commonly done with Iframe, or with the ZK embedded feature.
Using Iframe, the main page can use the window postMessage API to send and receive messages between itself and the included frames. This guaranty that each service is fully independent of the other, and that each service is compartmentalized.
Using ZK Embedded, the embedded services are added to the same context as the main document. This is very powerful since the main page can interact directly with the embedded elements client-side features, send direct messages to their respective back-end, etc. However, since the libraries are loaded in the same window context, it is necessary to be careful not to mix/override versions between each service.
The balance between direct access and compartmentalization makes both options useful in different scenarios.
Common questions on Stateless Components
Are Stateless components an upgrade to classic ZK components
No. Stateless components are a branching technology from the classic ZK components. They use the same client-side code (the JavaScript Widgets and associated HTML and CSS code), in addition to a completely different communication and update layer.
How to handle use cases that require server-side permanence
While the Stateless components only exist during requests and responses, you may need to store data which the user should not be able to modify or data that should not be publicly accessible.
In this situation, some sort of shared permanence layer is necessary for the application's function. For this purpose, a good option is to use a database layer. In the stateless components demo application, the content of the user's shopping basket is stored in a SQL database. Since the data layer is decoupled from the web container, it can be accessed by any number of instances. Databases already provide replication and high availability features, which makes them a great candidate to act as the shared permanence layer.
I have an existing ZK application...
... using classic ZK, do I need to update my code to use Stateless components instead?
Maybe, maybe not. We do not see the Stateless component as "the next step" in ZK innovation. Instead, we see them as a convenient tool that can be used if they are relevant to a specific application's architecture requirements.
As a rule of thumb, consider the following.
I should use stateless components if:
- I'm developing an application for a heavily distributed infrastructure in which session replication between nodes is difficult to achieve (cloud hosting, high availability with multiple regional clusters, etc.)
- I'm developing smaller-scale services which do not need to know about each other to perform their functions.
- I do not have access to sticky sessions, which causes the active node for a given user to change with each request
- I am concerned about the memory footprint, I would like to minimize the memory used on the server side.
I should use classic ZK if:
- I already have a fully functional application, which matches my infrastructure needs
- My infrastructure is a classic "Database, webserver (or webserver cluster), gateway/reverse proxy"
- I need to store multiple data, states and other semi-permanent objects between requests
- My application has a lot of interdependent systems which rely on server-side communication
Can stateless components and classic components be used on the same page?
Stateless and classic components cannot be used in the same document. The basic architecture for these components is different.
This said, a page can be created by composing content from multiple services. Nothing prevents some of these services from using stateless components and other classic components.
In the previous section Composed page from multiple services, we discussed the benefits of Iframe and ZK embedded for different use cases.
Both can be used in this context.
For example, the main page could declare a panel as an Iframe targetting a ZK stateless service, while another panel with more direct interaction with the containing page could be added using a ZK Embedded call for a classic ZK page.
Comparing and contrasting the Stateless workflow, and the new ZK 10 Client-MVVM features
Both of these new features have the goal of improving the resource footprint of a given page on the server-side. There is a similar concept between both features: removing server-side component instances.
In the case of Client-side MVVM, the ClientBindComposer will keep track of the bindings and commands but not create corresponding ZK components (the textboxes, grids, buttons, etc) in the server memory.
The view model being already decoupled from the view doesn't need to know that the command comes from a server-side Java instance of Textbox, or if it was sent by the client, and forwarded directly by the ClientBindComposer. In the opposite direction, the client-side Textbox JavaScript object doesn't know if the update returned by the response is generated by a server-side Java Textbox object or forwarded directly from the view model by the ClientBindComposer.
In the case of stateless components, the Java-side objects are also removed. Instead of maintaining a state in the view model, and using the ClientBindComposer to forward that state to the client-side objects, the stateless workflow use a list of inputs and outputs for each user action in a pattern which is closer to MVC.
When a user triggers an action on the client-side, all the state data required to process that action is sent together with the request. As a result, there is no state at all located in server memory.
Sample starter projects
A page using stateless components is created by declaring a Stateless Richlet.
The demo richlet provide in the ZK10 Preview smalltalk already shows how to set up a full page using the stateless components, register actions and perform updates.
For a very simple example of how a page and action declaration work with a stateless richlet, you can also refer to the simple richlet demo sample.
Comments
Copyright © Potix Corporation. This article is licensed under GNU Free Documentation License. |