Releases

Aspectran 9.8 Release Notes

This release is a major architectural milestone featuring native HTTP/2 protocol support for Netty and Undertow, a high-performance Redis Sorted Set-based session expiration index and lock-free striped connection pool for large-scale distributed clustering, enhanced WebSocket multi-message broadcasting and serialized asynchronous messaging, streamlined action execution exception handling and parameter binding, and comprehensive modernization and JSpecify null-safety standardization across the core utilities.

Servlet-less Netty and Undertow web services now natively support multiplexed HTTP/2 communication over Cleartext (h2c) and TLS ALPN (h2). In addition, the Lettuce-based distributed session store has transitioned from an $O(N)$ full SCAN polling model to an $O(\log N + M)$ Redis Sorted Set (ZSET) expiration index structure, dramatically reducing session scavenging overhead. This release also eliminates redundant exception wrapping across the Action execution pipeline, optimizes ETag and conditional HTTP processing, reinforces REST request/response APIs, and substantially expands unit test coverage and runtime resilience across all framework layers.

🚀 New Features

  • Native HTTP/2 Protocol Support for Netty and Undertow Services (Cleartext h2c and TLS ALPN h2)
    • Added comprehensive HTTP/2 protocol support across aspectran-with-netty and aspectran-with-undertow modules.
    • Cleartext HTTP/2 (h2c): Supports both direct connection and HTTP/1.1 Upgrade handshakes for h2c communication, delivering low-latency, multiplexed networking for internal microservices.
    • Secure TLS ALPN (h2): Implemented Application-Layer Protocol Negotiation (ALPN) to seamlessly negotiate HTTP/1.1 or HTTP/2 over a single TLS port and process multiplexed streams.
    • Added Http2Config for granular tuning of header table size, maximum concurrent streams, initial window size, maximum frame size, and maximum header list size.
    • Enhanced startup logging in Netty and Undertow web servers to clearly report HTTP/2 activation status and protocol negotiation details.
  • Redis Sorted Set Expiration Index (aspectran:session:expiry) and Lightweight SessionDataCodec
    • Replaced the legacy $O(N)$ Redis SCAN-based session expiration polling with an $O(\log N + M)$ Redis Sorted Set (ZSET) index (aspectran:session:expiry).
    • Stored expiration timestamps as ZSET scores to achieve lightning-fast lookups (doGetExpired, getAllSessions) even with millions of distributed sessions.
    • Lightweight SessionDataCodec Optimization: Introduced magic byte tags (MAGIC_ID_ONLY, MAGIC_FULL) to encode session IDs for index storage with minimal byte overhead while maintaining full backward compatibility.
    • Added the expiryIndexKey configuration option to AbstractLettuceSessionStore and session store factories for customizable index naming.
  • Redis Distributed Lock (SET NX EX) for Session Scavenging and Orphan Cleanup
    • Integrated Redis distributed locking (SET NX EX) into expired session scavenging (doGetExpired) and orphan session cleanup (doCleanOrphans) in multi-node clusters.
    • Prevented redundant deletions and Redis I/O contention by guaranteeing that only a single cluster node performs background cleanup routines at any given time.
    • Enhanced doCleanOrphans to physically delete orphaned session data keys from Redis before clearing index entries.
  • Lock-Free Striped Connection Pool for Lettuce Session Stores
    • Completely removed Apache Commons Pool2 dependencies and introduced a high-throughput, lock-free StripedConnectionPool tailored for Lettuce’s asynchronous multiplexing architecture.
    • Applied dynamic proxies to make connection close() calls safe no-ops within try-with-resources blocks.
    • Standardized connection pooling across Standalone, Cluster, and Primary-Replica topologies via a single poolSize configuration, eliminating lock contention.
  • Enhanced WebSocket Broadcasting and Serialized Asynchronous Messaging in SimplifiedEndpoint
    • Added broadcast(String) and broadcast(ByteBuffer) to SimplifiedEndpoint for efficient multi-session message broadcasting.
    • Expanded synchronous (sendText, sendBinary) and queue-based serialized asynchronous (sendTextAsync, sendBinaryAsync) messaging APIs to eliminate concurrent write collisions and ensure reliable WebSocket delivery.
  • Legacy HTTP HEAD Request Handling and NoBodyResponse Support
    • Established standardized HTTP HEAD request processing across Servlet, Netty, and Undertow services to return accurate response headers and Content-Length without generating response bodies.
    • Introduced NoBodyResponse to bypass redundant body serialization and optimize header metadata generation.

🚀 Improvements

  • Streamlined Action Exception Pipeline and Transparent Root Cause Propagation
    • Removed redundant ActionExecutionException try-catch wrapping from individual action implementations (AnnotatedAction, InvokeAction, EchoAction, HeaderAction, IncludeAction, ChooseAction, AdviceAction, AnnotatedAdviceAction).
    • Centralized exception wrapping within the execution engines (CoreActivity and AdviceActivity) to simplify execution stack traces and improve performance.
    • Enhanced AnnotatedMethodInvoker to reliably support InstantTranslet environments, parameter mapping, and bean resolution.
  • Defensive Response Transformation (TransformResponse) and View Dispatching in Non-Translet Environments
    • Added defensive activity.hasTranslet() guards across AponTransformResponse, JsonTransformResponse, TextTransformResponse, XmlTransformResponse, XslTransformResponse, and view dispatchers before invoking activity.getTranslet().
    • Ensured safe character encoding resolution and template rendering in standalone or daemon execution contexts where translet instances may not be present.
    • Modernized TransformResponseFactory using Java switch expressions.
  • Optimized HTTP ETag and Conditional Processing (ETagInterceptor)
    • Supported wildcard (*) matching in If-None-Match headers in full compliance with RFC 7232.
    • Added isEligibleMethod and isEligibleResponse guards to restrict ETag processing to eligible HTTP methods (GET/HEAD) and successful responses (2xx).
    • Optimized hex token formatting via DigestUtils.appendMd5DigestAsHex directly on StringBuilder instances to minimize temporary string allocations.
  • Reinforced REST Request/Response APIs and Advanced Content Negotiation
    • Enhanced RestRequest with a fluent API for chaining headers, query parameters, and request body payloads.
    • Added HTTP status code validation helpers and response conversion utilities to RestResponse.
    • Extended WebRequestBodyParser to recognize structured syntax suffixes (e.g., application/vnd.api+json, application/problem+xml).
    • Optimized MediaType and MediaTypeUtils with standard media type constants, parsing caching, and fast-path lookups.
    • Added support for Retry-After headers in error responses to guide client retry intervals.
  • Refined Clustered Session Lifecycle and Atomic Destruction Control
    • Implemented silent eviction (checkActiveInStore) to gracefully evict local session entries when a local timer expires while the session remains active in the shared cluster store.
    • Introduced the deletedInStore flag in ManagedSession to guarantee that onSessionDestroyed is fired only once by the specific node that atomically deletes the session from the store.
    • Acquired session locks in AbstractSessionCache.delete to maximize concurrency safety.
  • Modernized Core Utilities and Comprehensive JSpecify Null-Safety Annotations
    • DurationUtils: Added ISO-8601 duration string (PT1H30M) parsing, day unit (d/day/days) support, and locale-safe formatting via Locale.ROOT.
    • DataSizeUtils: Supported IEC binary suffixes (KiB, MiB, GiB, TiB), added byte unit constants, 64-bit integer overflow guards, and locale-independent formatting.
    • Assert: Extended CharSequence support and provided default failure message overloads for state, isTrue, notNull, hasText, noNullElements, etc.
    • ArrayStack: Added polymorphic generic lookups (peek(Class<T>), pop(Class<T>)), safe lookup helpers (peekOrNull, popOrNull), java.util.Stack compatibility (empty), and consistent negative index bounds checking.
    • DigestUtils: Added SHA-1/256/512 digest methods and in-place append*DigestAsHex formatters.
    • CopyOnWriteMap: Fixed NPE on missing keys, wrapped collection views (keySet, values, entrySet) for immutability, and overrode atomic compute* methods.
    • FileLocker: Implemented AutoCloseable (try-with-resources), modernized PID extraction using ProcessHandle.current().pid(), and ensured automatic parent directory creation.
    • ClassUtils / TypeUtils: Prevented unintended static class initialization (initialize: false), supported primitive and array type parsing, and improved unwrapping of nested CGLIB/Javassist proxies.
    • Standardized nullability annotations (@NonNull, @Nullable) and improved functionality across AutoLock, ShutdownHook, CyclicTimeout, Scheduler, LocaleUtils, FilenameUtils, PathUtils, SystemUtils, ObjectUtils, ExceptionUtils, ConcurrentReferenceHashMap, BeanUtils, and LinkedCaseInsensitiveMap.
  • Refactored i18n Locale Resolution and Message Sources
    • Reorganized LocaleResolver hierarchy and strategies, accompanied by comprehensive Javadoc documentation.
    • Improved consistency and unit testing across AcceptHeaderLocaleResolver, CookieLocaleResolver, and SessionLocaleResolver.

🐛 Bug Fixes

  • Fixed Map Mutation Risk on Path Parameter Extraction in WebSocketEndpointTemplate
    • Refactored WebSocketEndpointTemplate.match() to lazily instantiate the parameter map only when variable segments are decoded, preventing potential mutation errors on immutable Collections.emptyMap() and eliminating unnecessary allocations on literal or non-matching paths.
  • Fixed NullPointerException on Missing Keys in CopyOnWriteMap
    • Resolved NPEs occurring when invoking remove(key, value) or replace(key, oldValue, newValue) on keys not present in the map.
  • Fixed NPE on Null Elements and Inconsistent Negative Index Bounds in ArrayStack
    • Fixed an NPE when invoking peek(Class) on stacks containing null elements and ensured EmptyStackException is consistently thrown for negative indices.
  • Fixed Fixed-Size Buffer Overflow in DigestUtils.encodeHex
    • Corrected fixed character buffer allocation to accommodate arbitrary byte array lengths during hex encoding.
  • Fixed Filter Evaluation Logic in TransletScanner
    • Fixed an issue where certain wildcard filter patterns failed to match candidate translet rules during component scanning.
  • Fixed Target Matching and Flash Attribute Scoping in FlashMap
    • Corrected destination target path evaluation and reinforced null safety during flash attribute lifecycle handling.
  • Corrected Header Overwriting Logic in HeaderAction
    • Updated response header configuration to explicitly set headers (setHeader) instead of appending them (addHeader).

🛠️ Dependency Upgrades

  • Networking & Distributed Sessions
    • Netty: 4.2.18.Final (Introduced BOM dependency management and added netty-codec-http2)
    • Lettuce Core: 7.7.0.RELEASE → 7.8.0.RELEASE (Removed Apache Commons Pool2)
  • Core Utilities & Expressions
    • OGNL: 3.4.12 → 3.4.13
    • JLine: 4.4.3 → 4.4.6
  • Logging & Database
    • SLF4J: 2.0.19 → 2.0.20
    • Logback Classic: 1.6.3 → 1.6.4
    • H2 Database: 2.5.250 → 2.5.252
    • Hibernate ORM: 7.4.7.Final → 7.4.11.Final
    • Hibernate Validator: 9.1.3.Final → 9.1.4.Final
    • QueryDSL: 7.6 → 7.7
  • Build & Plugins
    • Maven Install Plugin: 3.1.4 → 3.2.0
    • Maven Deploy Plugin: 3.1.4 → 3.2.0
    • Maven Bundle Plugin: 6.1.2 → 6.2.0
    • Build Helper Maven Plugin: 3.6.1 → 3.6.2

NEWS
Release

Archive