🚀

ng-objects

The core libraries

Version
v0.1.6
Updated
Oct 18

0.1.6

v0.1.6 Oct 18 on GitHub ↗

A stabilizing release, mostly deployment fixes.

  • WOHost is optional, as in WO: lifebeats fall back to this machine's host name (#93)
  • Instance requests (/womp/instanceRequest, e.g. TERMINATE) are accepted only from this host, not through the web server adaptor or a proxy (part of #55)
  • TERMINATE no longer fails when lifebeats are disabled
  • The development endpoints (/ng/dev/…) answer loopback clients only (#83)
  • WOOutputPath problems are logged and the app carries on; a failed archive no longer truncates the previous log (#95)
  • KVC tries fields in the same pattern as methods: key, isKey, _key, _isKey. WO's order is _key, _isKey, key, isKey (#80)
  • An unregistered direct action class answers 404, not 500; direct action 404s are plain text (#84)
  • Elements that render a tag pass unknown attributes through (#88)
  • NGConditional: empty strings and collections are true (#94)
  • An element nobody registers is found on the classpath by name, as in WO
  • .apiext files live in their namespace's components folder and name their element's class in full; readers for .apiext and parsley.taglib files are in ng-template-parser
  • Plugins are initialized after the plugins they require
  • A class that exists but can't be loaded is reported, not taken for a missing one
  • Inline error messages have a new look
  • Jetty 12.1.14

Full Changelog: https://github.com/ngobjects/ng-objects/compare/v0.1.5...v0.1.6

0.1.5

v0.1.5 Oct 14 on GitHub ↗
  • Attribute values are escaped by default (#56)
  • Session access moved to NGContext. NGRequest.session(), existingSession() and hasSession() are removed: use the NGContext methods (#68)
  • NGRequest.parsedURI() is removed (#77)
  • NGDynamicElementDescription is removed
  • NGPopUpButton fails with a clear message on malformed submissions (#70)
  • A development-instance stopper shared with wonder-slim (ng.dev.NGDevInstanceStopper), which stops whatever ng or WO app holds the development port and kills it if it won't stop

Full Changelog: https://github.com/ngobjects/ng-objects/compare/v0.1.4...v0.1.5

0.1.4

v0.1.4 Oct 4 on GitHub ↗

Interim development release. Expect incompatible changes between 0.1.x releases.

Templating

  • Binding keys may now start with : as well as ?, e.g. <wo:Hyperlink :id="$user.id" />. This is groundwork for passing route parameters to link elements.

Developer tooling

  • /ng/dev/eval describes exceptions with their whole cause chain, e.g. ExceptionInInitializerError ← NullPointerException: …, and reports the root cause's top stack frames in diagnostics (#75).
  • Unknown-key "Did you mean" suggestions no longer offer void methods (clear), operator keys (@count) or keys every object has (class, hashCode, toString) (#74).

Dependencies

  • vermilingua 1.1.10 → 1.1.11

Full Changelog: https://github.com/ngobjects/ng-objects/compare/v0.1.3...v0.1.4

0.1.3

v0.1.3 Sep 25 on GitHub ↗

Interim development release. Expect incompatible changes between 0.1.x releases; the request/response model (ng.appserver.http) in particular is still being reshaped.

Templating

  • Breaking: the tag registry is now ng-tag-aliases.properties, renamed from parsley-tag-aliases.properties. ng-objects and WebObjects/Parsley can now share a classpath without each reading the other's tag declarations. Frameworks and applications that ship their own tag aliases must rename their file (#71).

Responses

  • Breaking: streamed content has its own response type, NGStreamingResponse, created with NGResponses.streaming( inputStream, length ). setContentInputStream/contentInputStream()/contentInputStreamLength() are no longer on NGResponse. A streaming response can't be constructed without a non-negative length.
  • NGStandardResponse's ( int, String ) and ( int, byte[] ) constructors were deleted; use NGResponses.of( status, content ).

Deployment

  • NGLifebeatThread no longer blocks application startup on a slow or unreachable wotaskd, and no longer waits for the reply body. The classic WO adaptor answers without a Content-Length, so waiting for the body stalled each message for three minutes.
  • New /ng/describe endpoint identifying the framework to management tools (early; currently returns the framework name only).

Dependencies

  • slf4j 2.0.19 → 2.0.20

Full Changelog: https://github.com/ngobjects/ng-objects/compare/v0.1.2...v0.1.3

0.1.2

v0.1.2 Sep 19 on GitHub ↗

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.

Developer tooling

  • 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

0.1.1

v0.1.1 Apr 22 on GitHub ↗

Maintenance release.

  • Removed the no-op WOElement interface, originally introduced only to fool WOLips into thinking it was working with a WO project
  • Fail parsing of elements with duplicate attributes.

Full Changelog: https://github.com/ngobjects/ng-objects/compare/v0.1.0...v0.1.1

0.1.0

v0.1.0 Mar 7 on GitHub ↗

First release to maven central 🎉