Building Stateless UI"

From Documentation
Line 29: Line 29:
 
</syntaxhighlight>
 
</syntaxhighlight>
  
= Constructing UI with IComponent =
+
= Restful URL Mapping =
Stateless components in ZK 10 are immutable and are created using Java APIs. Here is a simple example of how to compose a UI with <code>IComponent</code>. ('''I''' means '''immutable''').
+
In ZK 10, URL mapping is similar to using RESTful API. We use <code>@RichletMapping</code> to represent mapping the HTTP Request path with the GET method.
 +
* for example, the <code>shoppingCart()</code> URL will be '''<protocal>:// <host name: port> /shoppingCart'''.
 +
<source lang='java' highlight='1, 3'>
 +
    @RichletMapping("/shoppingCart")
 +
    public class DemoRichlet implements StatelessRichlet {
 +
        @RichletMapping("")
 +
        public List<IComponent> shoppingCart() {
 +
            //return ...
 +
        }
 +
    }
 +
</source>
  
<syntaxhighlight lang='java'>
+
= Composing the UI with Stateless Components =
// Example of composing UI with IComponent
+
Before ZK 10, ZK components are stateful, meaning that the server holds the state. Starting from ZK 10, we provide a set of stateless components as '''Immutable objects'''. Immutable objects are constructed once and can not be changed after they are constructed. After Immutable objects are rendered, they will be destroyed. Since the component state will not be saved on the server, they consume less memory.  
public IComponent demo() {
 
    return IButton.of("add items").withSclass("add-items");
 
}
 
</syntaxhighlight>
 
  
= Handling Events and Accessing UI State in a Stateless Manner =
+
== UI Composing ==
Events in stateless components are wired using the `@Action` annotation, and the UI state is accessed via the `@ActionVariable`.
 
  
<syntaxhighlight lang='java'>
+
With ZK 10 stateless components, you will no longer write a zul file. You will be composing your view using the stateless components and their APIs in Java.  
// Wiring an event listener
 
@Action(type = Events.ON_CLICK) // Wiring event
 
public void addItem() {
 
    ...
 
}
 
  
// Accessing UI state
+
* ZK component having a prefix letter "I" represents an immutable component.
@Action(type = Events.ON_CLICK)
+
* We offer <code>of()</code> API for commonly used properties.
public void addItem(@ActionVariable(targetId = ActionTarget.SELF, field = "id") String orderId) {
+
* <code>withSclass()</code> means the setter of sclass.
     ...
+
 
}
+
<source lang='java'>
</syntaxhighlight>
+
    // ZK 10
 +
    IButton.of("add items")
 +
          .withSclass("add-items");
 +
</source>
 +
<source lang='java'>
 +
    // ZK 9
 +
    // equivalent idea as above.
 +
    Button button = new Button("add items");
 +
    button.setSclass("add-items");
 +
</source>
 +
 
 +
= Event Wiring =
 +
To wire an event listener, you need to declare the '''ActionHandler''' method, with an annotation <code>@Action</code>.
 +
* The method should be public.
 +
* The parameter of <code>@Action</code> should be one of  [https://www.zkoss.org/javadoc/zk/org/zkoss/zk/ui/event/Events.html event types].
 +
* Wire the action handler with the target component by <code>withAction(ActionHandler action)</code>.
 +
 
 +
<source lang='java' highlight='2, 9'>
 +
    // ActionHandler method
 +
    @Action(type = Events.ON_CLICK) // Wiring event
 +
    public void addItem() {
 +
        ...
 +
    }
 +
 
 +
    public IComponent demo() {
 +
        return IButton.of("add items").withSclass("add-items")
 +
                .withAction(this::addItem);
 +
    }
 +
</source>
 +
 
 +
= Obtain Widget State =
 +
Since a server no longer holds a component's state, we provide <code>@ActionVariable</code> to access component attributes and state sent from the client.
 +
 
 +
* <code>@ActionVariable(targetId = ActionTarget.SELF, field = "id")</code> retrieves the value from the <code>field</code> of a component with the <code>targetId</code> on the client.</li>
 +
* <code>ActionTarget.SELF</code> means it targets the component associates to the event itself.
 +
 
 +
<source lang='java' highlight='2, 6'>
 +
    @Action(type = Events.ON_CLICK)
 +
    public void addItem(@ActionVariable(targetId = ActionTarget.SELF, field = "id") String orderId) {
 +
     }
 +
</source>
 +
 
 +
= Update Widget State =
 +
To update the widget state, we provide several APIs in <code>UiAgent</code>.  The state will be updated to the client immediately.
 +
* The following example will add the specified child component as the last child to the locator.
 +
<source lang='java' highlight='3'>
 +
    @Action(type = Events.ON_CLICK)
 +
    public void addItem(@ActionVariable(targetId = SELF, field = "id") String orderId) {
 +
        UiAgent.getCurrent().appendChild(Locator.ofId("shoppingBagRows"), addShoppingBagItem(parseUuid(orderId)));
 +
    }
 +
</source>
 +
 
 +
= Conclusion =
 +
In this article, I have briefly introduced how you can use ZK 10's stateless components to build a could-native application to enjoy scalability, auto-provisioning, boosted performance, and reduced memory. This architectural change also increases the modularity and allows you to easily bridge with other modern applications and microservices.
 +
 
 +
We welcome you to download ZK 10 Freshly and build your first cloud-native application today!
 +
 
 +
''Note. Stateless Component is a new feature in ZK 10 providing lighter and faster experiences and a cloud-friendly architecture. If you are not ready, you can still use ZK 10 in the same way as you usually do.''
 +
 
 +
= Example Application =
 +
You can [https://github.com/zkoss-demo/zk10-shopping-cart-demo download the shopping cart demo project].
  
  
  
 
{{ZKDevelopersReferencePageFooter}}
 
{{ZKDevelopersReferencePageFooter}}

Revision as of 07:35, 23 November 2023


Building Stateless UI


Setting up

To set up stateless components in a ZK 10 application, you need to include the stateless components module and define a Dispatcher Richlet Filter in your `WEB-INF/web.xml` file.

Including Required Jar

dependencies {
    implementation "org.zkoss.zk:stateless:${zkVersion}"
    ...
}

Dispatcher Richlet Filter

<filter>
    <filter-name>DispatcherRichletFilter</filter-name>
    <filter-class>org.zkoss.stateless.ui.http.DispatcherRichletFilter</filter-class>
    <init-param>
        <param-name>basePackages</param-name>
        <param-value><!-- your base packages --></param-value>
    </init-param>
</filter>
<filter-mapping>
    <filter-name>DispatcherRichletFilter</filter-name>
    <url-pattern>/*</url-pattern>
</filter-mapping>

Restful URL Mapping

In ZK 10, URL mapping is similar to using RESTful API. We use @RichletMapping to represent mapping the HTTP Request path with the GET method.

  • for example, the shoppingCart() URL will be <protocal>:// <host name: port> /shoppingCart.
    @RichletMapping("/shoppingCart")
    public class DemoRichlet implements StatelessRichlet {
        @RichletMapping("")
        public List<IComponent> shoppingCart() {
            //return ...
        }
    }

Composing the UI with Stateless Components

Before ZK 10, ZK components are stateful, meaning that the server holds the state. Starting from ZK 10, we provide a set of stateless components as Immutable objects. Immutable objects are constructed once and can not be changed after they are constructed. After Immutable objects are rendered, they will be destroyed. Since the component state will not be saved on the server, they consume less memory.

UI Composing

With ZK 10 stateless components, you will no longer write a zul file. You will be composing your view using the stateless components and their APIs in Java.

  • ZK component having a prefix letter "I" represents an immutable component.
  • We offer of() API for commonly used properties.
  • withSclass() means the setter of sclass.
    // ZK 10
    IButton.of("add items")
           .withSclass("add-items");
    // ZK 9
    // equivalent idea as above.
    Button button = new Button("add items");
    button.setSclass("add-items");

Event Wiring

To wire an event listener, you need to declare the ActionHandler method, with an annotation @Action.

  • The method should be public.
  • The parameter of @Action should be one of event types.
  • Wire the action handler with the target component by withAction(ActionHandler action).
    // ActionHandler method
    @Action(type = Events.ON_CLICK) // Wiring event
    public void addItem() {
        ...
    }

    public IComponent demo() {
         return IButton.of("add items").withSclass("add-items")
                .withAction(this::addItem);
    }

Obtain Widget State

Since a server no longer holds a component's state, we provide @ActionVariable to access component attributes and state sent from the client.

  • @ActionVariable(targetId = ActionTarget.SELF, field = "id") retrieves the value from the field of a component with the targetId on the client.
  • ActionTarget.SELF means it targets the component associates to the event itself.
    @Action(type = Events.ON_CLICK)
    public void addItem(@ActionVariable(targetId = ActionTarget.SELF, field = "id") String orderId) {
    }

Update Widget State

To update the widget state, we provide several APIs in UiAgent. The state will be updated to the client immediately.

  • The following example will add the specified child component as the last child to the locator.
    @Action(type = Events.ON_CLICK)
    public void addItem(@ActionVariable(targetId = SELF, field = "id") String orderId) {
        UiAgent.getCurrent().appendChild(Locator.ofId("shoppingBagRows"), addShoppingBagItem(parseUuid(orderId)));
    }

Conclusion

In this article, I have briefly introduced how you can use ZK 10's stateless components to build a could-native application to enjoy scalability, auto-provisioning, boosted performance, and reduced memory. This architectural change also increases the modularity and allows you to easily bridge with other modern applications and microservices.

We welcome you to download ZK 10 Freshly and build your first cloud-native application today!

Note. Stateless Component is a new feature in ZK 10 providing lighter and faster experiences and a cloud-friendly architecture. If you are not ready, you can still use ZK 10 in the same way as you usually do.

Example Application

You can download the shopping cart demo project.




Last Update : 2023/11/23

Copyright © Potix Corporation. This article is licensed under GNU Free Documentation License.