Interim development release. APIs are still being reshaped — the request/response model (ng.appserver.http) in particular — so expect incompatible changes between 0.1.x releases.
Page cache overhauled
restorePageFromCache/retainPageWithContextIDInCache/releaseLock replaced by an atomic checkout() returning an AutoCloseable NGPageLease (try-with-resources).
- Thread-safety: synchronized cache maps, atomic contextID counter, and locking per page instance — requests for the same page serialize, different pages of one session run concurrently. A page returned as a response is rendered under its own lock.
- Timed lock acquisition (10s default): contention surfaces as
NGPageContendedException → 503 with Retry-After.
- Partial-update entries reworked: flat parent chains, a per-page cap that only evicts superseded fragments (the newest entry per update container always survives), orphaned saves promoted rather than failing a completed action. Two session-lifetime memory leaks fixed.
- Cache sizes and lock timeout constructor-injectable (defaults 100/50/10s). 30 new tests, including an application-free request-handler harness.
HTTP message model (redesign in progress)
- Breaking:
NGRequest/NGResponse/NGMessage are now interfaces (NGStandardRequest/NGStandardResponse implementing), live in the new ng.appserver.http package.
- Breaking: responses are created through the new
NGResponses factories instead of new NGResponse( content, status ). Note the argument order is now status-first — NGResponses.of( 404, "Not found" ) — with NGResponses.ok( content ) for the common case. The factories return the NGResponse interface; NGStandardResponse's constructors are protected.
NGRequest walking toward immutability: _setFormValues/_setCookieValues/setMethod deleted, settled fields final, remoteAddress a constructor argument (null = no transport peer), request content accepted as InputStream, httpVersion removed.
- Session access belongs to the context:
NGContext.session()/existingSession()/hasSession() are the supported API; the NGRequest equivalents are deprecated. Also deprecated, scheduled for deletion: NGRequest._setContext() (renamed from setContext) and uploadedFiles().
- Breaking:
NGCookie is now an immutable record. name/value are required, SameSite is an enum, maxAge given as a Duration (null = session cookie, Duration.ZERO = delete, negative rejected), secure/httpOnly accessors lose their is-prefix. Only Max-Age is emitted, never Expires.
NGAdaptorRaw and NGAdaptorPlain deleted, we'll only be targeting Jetty while developing.
Templating & elements
- Attribute values in generated element tags are now escaped
- Tag names are declared in
parsley-tag-aliases.properties — a single source of truth read by both the runtime and the Parsley template editor. Every such file on the classpath is loaded (first declaration wins, conflicts warned); explicit code registrations still override.
.apiext definitions ship for all 26 framework elements — bindings with direction and types, required flags, defaults, deprecations, cross-binding constraints.
NGSwitchComponent: fixed an elementID-minting race that could permanently merge two cases' component caches.
NGRepetition: fixed infinite recursion in takeValuesFromRequest for count-bound repetitions.
NGPopUpButton: the selection binding is the sole authority for rendered selection when bound; out-of-range selection indexes fail deliberately.
NGTextField: (temporarily) doesn't attempt to format a null value.
Security
- Session cookie hardened by default:
HttpOnly, SameSite=Lax, Path=/, host-only. Secure remains a deployment decision; createSessionCookie is protected and overridable.
/ng/dev/eval stays loopback-restricted and rejects form-encoded bodies with a clear error.
- New endpoints
/ng/dev/eval and /ng/dev/problems; Parslips dev-server support (apps self-register, reporting runtime=ng); pid logged at startup.
- Dev tools moved out of
ng.appserver.privates: NGConsoleCapture → ng-core's ng.dev; the rest → new ng.appserver.dev.
Infrastructure & dependencies
NGLifebeatThread uses Java's HttpClient instead of raw sockets.
- Jetty 12.1.8 → 12.1.13, JUnit 6.0.3 → 6.1.3, slf4j 2.0.17 → 2.0.19, vermilingua 1.1.3 → 1.1.10; Maven plugins refreshed.
Full Changelog: https://github.com/ngobjects/ng-objects/compare/v0.1.1...v0.1.2