Session Replication
Session Replication
This document provides comprehensive guidance for implementing and troubleshooting ZK session replication in clustered environments. Based on analysis of production support tickets, this guide addresses the most common issues with their root causes and solutions.
Performance Challenge
The major challenge is: session replication serializes the entire session including ZK’s Desktop and component tree on every AU request.
Large Destkop and Component Tree
ZK stores a Desktop and a whole component tree in a Session attribute. Since app developers build a page with zk components mostly, each page usually contains lots of components which enlarge a session size. A large session takes longer time to replicate.
Component States Changes Frequently
Each AU request might invoke an event listener that changes a component’s state. That means a Session state also changes, so you need to replicate the session every time. This can lead to high replication overhead, especially in applications with frequent UI updates.
Solutions:
- Minimize session size - only store essential information and optimize the number of component in each page. Reducing the number of components reduces session size. See Performance Tips
- Use lazy loading for heavy objects, see Defer the Creation of Child Components.
- Use Client binding to reduce server-side state management, see Client Binding.
- Consider application-level caching instead of session storage
- Monitor replication overhead in network traffic
- Use transient fields for non-essential data that can be recomputed
Common Issues and Solutions
Serialization Failures
Most frequent issue: NotSerializableException
during session replication
Root Causes
Framework Level:
- ZK internal classes with non-serializable logger fields
- Default components storing non-serializable references
- Session hierarchy requiring full serialization chain
Application Level:
- ViewModels not implementing
Serializable
- Composers containing non-serializable fields (especially logger instances)
- Non-serializable third-party libraries in session scope
Solutions
- Regarding ZK related classes, report to ZK support team for further assistance.
- Regarding application classes, application developers should ensure all classes stored in the session implement
Serializable
and follow best practices for serialization.
Logger Serialization Issues
java.io.NotSerializableException: org.apache.log4j.Logger
java.io.NotSerializableException: java.util.logging.Logger
Solution
Make logger fields static (as detailed in Programming Tips)
// Instead of:
private final Logger logger = LoggerFactory.getLogger(getClass());
// Use:
private static final Logger logger = LoggerFactory.getLogger(MyClass.class);
Custom Class Serialization
Solution
ViewModel should implement Serializable
:
public class EventsMessageViewModel implements Serializable {
private static final long serialVersionUID = 1L;
private static final Logger logger = LoggerFactory.getLogger(EventsMessageViewModel.class);
// Serializable fields
private String message;
private List<String> events;
// Non-serializable fields marked as transient
private transient DatabaseConnection dbConnection;
// Implement readObject for transient field initialization
private void readObject(ObjectInputStream in) throws IOException, ClassNotFoundException {
in.defaultReadObject();
// Reinitialize transient fields after deserialization
initializeTransientFields();
}
private void initializeTransientFields() {
dbConnection = DatabaseFactory.getConnection();
}
}
Configuration Issues
Root Causes
- Missing ZK clustering configuration
- Incomplete application server setup
- ZScript compatibility problems in clustered environments
Solutions
- Ensure
SerializableUiFactory
is configured (see ZK Configuration) - Add
<distributable/>
to web.xml - Disable ZScript in clustered environments
- Configure proper load balancer with sticky sessions (see Server Configuration)
Session Timing Problems
Root Causes
- UI changes not triggering session replication automatically
- Framework not detecting session modifications
Solutions
Manual Session Replication Trigger: For cases where UI changes don’t automatically trigger replication:
public void myEventListener() {
// Perform your business logic
updateUserData();
// Manually trigger session replication
Sessions.getCurrent().setAttribute("_manual_replication_trigger",
System.currentTimeMillis());
}
ExecutionCleanup Listener: Force session replication after each request:
public class SessionReplicationCleanup implements ExecutionCleanup {
@Override
public void cleanup(Execution exec) throws Exception {
// Force session replication after each request
Session session = Sessions.getCurrent();
if (session != null) {
session.setAttribute("_replication_timestamp", System.currentTimeMillis());
}
}
}
Register in zk.xml:
<system-config>
<listener>
<listener-class>com.yourpackage.SessionReplicationCleanup</listener-class>
</listener>
</system-config>
#Testing and Validation
Serialization Testing
Test Method:
private <T> T testSerialization(T object) throws IOException, ClassNotFoundException {
// Serialize
ByteArrayOutputStream baos = new ByteArrayOutputStream();
ObjectOutputStream oos = new ObjectOutputStream(baos);
oos.writeObject(object);
oos.close();
// Deserialize
ByteArrayInputStream bais = new ByteArrayInputStream(baos.toByteArray());
ObjectInputStream ois = new ObjectInputStream(bais);
T result = (T) ois.readObject();
ois.close();
return result;
}
// Usage
@Test
public void testViewModelSerialization() {
MyViewModel viewModel = new MyViewModel();
viewModel.setData("test data");
try {
MyViewModel deserialized = testSerialization(viewModel);
assertEquals("test data", deserialized.getData());
} catch (Exception e) {
fail("ViewModel serialization failed: " + e.getMessage());
}
}