Skip to content

Replace ROME Propono AtomPub server with self-contained StAX implementation - #210

Merged
snoopdave merged 5 commits into
masterfrom
replace-propono-atompub
Oct 10, 2026
Merged

snoopdave merged 5 commits into
masterfrom
replace-propono-atompub

Conversation

@snoopdave

@snoopdave snoopdave commented Oct 10, 2026 •

Copy link
Copy Markdown
Contributor

Moves #161 into a branch in apache/roller; the code is the same as #161's head (35fe89870). The review history (Matt's and Michael's comments, the CodeQL alerts and their fixes) is on #161.

What

Reimplements the Atom Publishing Protocol (RFC 5023) server using only JDK StAX (javax.xml.stream) and plain DTOs — no ROME, no Propono.

Why

The AtomPub server was built on ROME's rome-propono, which is only available up to ROME 1.19.0 (the last release that ships Propono). That pin held the entire ROME stack at 1.19.0 for the whole app, even though feed rendering doesn't use Propono. Dropping rome-propono frees ROME-for-feeds to be upgraded independently in a later, deliberate step.

All Propono usage was confined to webservices/atomprotocol/; feeds and the Planet aggregator are untouched.

Changes

  • RollerAtomServlet (new) replaces Propono's AtomServlet — method dispatch, 201 Created + Location/Content-Location, and media streaming ported over. Wired in web.xml; propono.properties and RollerAtomHandlerFactory removed.
  • New wire model (AtomEntry, AtomFeed, AtomContent, AtomLink, AtomPerson, AtomCategory, plus the service-doc DTOs and AtomMediaResource) with StAX AtomWriter / AtomReader.
  • RollerAtomHandler / RollerAtomService / EntryCollection / MediaCollection keep their Roller domain-mapping logic; only the ROME types they touched changed. Fixes a latent BASIC-auth bug that compared against the null instance field instead of the looked-up user's password.
  • Auth: BASIC + OAuth. WSSE was already retired on master (Retire the WSSE AtomPub authentication mode #166).

Design decisions

  • XML: JDK StAX only — no JDOM/JAXB. javax.xml.stream is not part of the javax→jakarta migration, so it's safe.
  • Scope: server only (the AtomPub server receives requests; there is no outbound HTTP in this path).

Testing

  • Unit tests for the reader, writer, DTOs, and request wrapper.
  • Integration test (RollerAtomProtocolTest) driving the full create / retrieve / update / delete lifecycle plus service-doc and media upload against in-memory Derby.
  • Schema-validation tests (AtomSchemaValidationTest) that validate AtomWriter output against the RFC 4287 (Atom) and RFC 5023 (AtomPub) RELAX NG schemas using Jing.

mvn -pl app test: all tests pass.

Note: the HTTP transport and BASIC auth over the wire need the Spring web context and aren't exercised by the JUnit reactor. Recommend confirming wire-format interop with an over-the-wire exerciser (e.g. APE) against a deployed instance, since the previous format was ROME-generated.

…tation

Reimplements the Atom Publishing Protocol (RFC 5023) server using only
JDK StAX (javax.xml.stream) and plain DTOs -- no ROME, no Propono. This
removes the rome-propono dependency that pinned the entire ROME stack to
1.19.0, freeing ROME-for-feeds to be upgraded independently.

- New Roller-owned servlet (RollerAtomServlet) replaces Propono's
  AtomServlet; method dispatch, 201 Created/Location handling and media
  streaming are ported over.
- New wire model (AtomEntry/AtomFeed/AtomContent/AtomLink/AtomPerson/
  AtomCategory and the service-doc DTOs) with StAX AtomWriter/AtomReader.
  AtomReader disables DTDs and external entities (XXE-safe).
- RollerAtomHandler/RollerAtomService/EntryCollection/MediaCollection
  keep their domain-mapping logic; only the ROME types they touched
  changed. Fixes a latent BASIC-auth bug that compared against the null
  instance field instead of the looked-up user's password.
- Auth: keep BASIC + OAuth, drop WSSE (removes WSSEUtilities and the
  wsse choice from the admin config labels).
- Adds unit tests for the reader/writer/DTOs/request, an integration
  test driving the create/retrieve/update/delete lifecycle against
  in-memory Derby, and schema-validation tests that check AtomWriter
  output against the RFC 4287/5023 RELAX NG schemas via Jing.

The HTTP transport and BASIC auth over the wire require the Spring web
context and are not exercised by the JUnit reactor; verify those with an
over-the-wire exerciser (e.g. APE) against a deployed instance.
Port master's Propono-based AtomPub changes to the StAX implementation:

- RollerAtomServlet answers 404 while webservices.enableAtomPub is off,
  authenticates before reading the body, caps Atom entry bodies at
  webservices.atomPubMaxEntrySize (413), and refuses malformed entries
  or entries with a DOCTYPE (400).
- AtomReader reports parse errors and DOCTYPEs as HTTP 400.
- MediaCollection takes master's media type policy, directory lookup and
  file naming fixes; createMediaResource builds the immutable resource.
- RollerAtomHandler takes master's strict basic/oauth auth selection and
  the shared isEntryPath() helper.
- Port RollerAtomServletTest, MediaCollectionTest and
  MediaCollectionPathTest off Propono types; drop the factory and SAX
  parser cases that no longer apply. Drop propono.properties.
- Stream media bodies to MediaCollection instead of buffering them;
  only Atom entries are read into memory, under the entry size limit.
- AtomReader reads only direct children of atom:entry (ignores
  atom:source) and accepts type="xhtml" text constructs.
- Media DELETE through the edit URI looks up the file without the
  .media-link suffix; missing media on GET, PUT and DELETE is a 404.
- POST without Content-Type returns 415.
- Write app:edited as a child of atom:entry (RFC 5023 10.2) and declare
  charset=utf-8 on the entry media type.
- Factor AtomWriter document setup into one helper.
- Note the removed AtomHandlerFactory extension point in CHANGES.md.
- Send only the status code for 5xx AtomPub errors and unexpected
  exceptions; log the details server-side.
- Set Location/Content-Location only when the edit URI is a valid URI
  under this server's AtomPub URL (no CR/LF, no foreign host).
- Require view permission for media-link entries and return 404 for an
  unknown weblog, matching the media collection.
- Remove the unused commons-httpclient 3.1 dependency.
- Exclude xercesImpl and xml-apis from the test-scoped Jing dependency.
  Jing declares them with runtime scope, which replaced the WAR's
  Xerces 2.11.0 and xml-apis 1.4.01 with 2.9.1 and 1.0.b2.
- Add source and copyright headers to the RFC 4287 and RFC 5023 RELAX NG
  schemas used by AtomSchemaValidationTest.
@snoopdave
snoopdave merged commit c2ca40e into master Oct 10, 2026
15 checks passed
snoopdave added a commit that referenced this pull request Oct 10, 2026
#209 (templates, categories and comments over AtomPub) and #211 (AtomPub
reference guide) were merged into their stacked base branches after #210
was squash-merged into master, so their changes never reached master.
This commit applies them: the tree is that of replace-propono-atompub at
95d2419, which is master plus #209 and #211.
mraible added a commit to mraible/roller that referenced this pull request Oct 11, 2026
Master replaced ROME Propono with Roller's own StAX AtomPub server (apache#210, apache#212), which already includes apache#198's per-request webservices.enableAtomPub check, the entry size limit, hardened entry parsing, MediaTypePolicy headers on served media, and request-free temp file names. That server replaces the forked Propono servlet on this branch, so RollerAtomRequestImpl goes away and OAuth 1.0a stays removed from RollerAtomHandler, along with the OAuth sections of the AtomPub guide and security model.

Everything new from master is moved to the jakarta.servlet namespace and Struts 7 APIs (ActionContext.of().bind(), withServletRequest and friends), and the ORM and persistence files keep their Jakarta schemas under master's new license headers.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant