Skip to content

Conversation

@davidblasby
Copy link
Contributor

DO NOT MERGE - WIP

This is a PR-to-the-PR-to-the-PR for architectural issues.

Ok, I've got a really messy version of the content negotiation stuff up in a PR (to the PR, to the PR,...). The main purpose is to create and register the single-record formatters (i.e. dcat, etc...):

  1. On startup, Generic-GN5 app is run, and WebConfig will be executed. This is where spring content negotiation is setup.
  2. WebConfig registers two things - the list of acceptable MIME types and their "short name". This is used in the ?f=json and ?f=application/json.
  3. WebConfig hands off to simple MessageWriterUtil class. This gets implementations of IContentNegotiationInitializable from any of the modules.
  4. each of these are initialized and creates a set IControllerResultFormatter. In this case the FormatterApi is queried and 4 classes are created - one for each of the 4 MimeTypes that the formatter produces (xml, json, xml+rdf, geojson). These IControllerResultFormatter are profile-aware formatters that use to FormatterApi to do the actual work.
  5. These 4 are registered as spring MessageConverters in the normal spring content negotiation.

As mentioned before, when a request for a single-record comes in:

  1. spring routes it to the correct controller
  2. the controller does very little, but returns a OgcApiRecordsSingleRecordResponse, which is a very small object that contains the catalogId, recordId, and user-requested profiles.
  3. This is the handed off to the spring content negotiation system (which looks for things like `?f=application/xml+rdr)
  4. Spring will look for a messagewriter that can handle application/xml+rdr for the OgcApiRecordsSingleRecordResponse (this is one of the profile-aware ones we registered).
  5. spring will hand the OgcApiRecordsSingleRecordResponse off to our profile-aware FormatterApi setup for application/xml+rdr
  6. our formatter will do profile-negotiation (simple) and then hand off to the FormatterApi (knowing both mimetype and official profile name)

WHEW

The main thing is that the content negotation system is pluggable - any app/module can supply a set of IContentNegotiationInitializable that will register everything in the content negotation system.

Key things to look at

  1. MessageWriterUtil - doesn't do very much, it just finds IContentNegotiationInitializable and calls #initialize() on them.
  2. WebConfig - this is where the MimeTypes (for ?f=...) are setup and message writers (created by MessageWriterUtil) are registered
  3. SingleRecordFormatterApiContentNegotiationInitializable - this will create the 4 (one for each of the 4 mime types). These implement profile-aware spring MessageConverters for the OgcApiRecordsSingleRecordResponse
  4. OgcApiRecordsSingleRecordResponse - this is the tiny class generated by the controller for a single record
  5. OgcApiRecordsSingleRecordResponseFormatter actually does the formatting

PR Title

Description

Type of Change

Select one:

  • Bug fix
  • New feature
  • Documentation update
  • Refactoring

Related Issue

Closes/updates # (optional):

Approach

How to Verify

Checklist

  • Code is formatted and linted
  • All tests pass locally and in CI
  • Tests updated (if applicable)
  • Documentation updated (if applicable)

@davidblasby
Copy link
Contributor Author

the integration tests aren't running. Likely because they aren't configured correctly or running the geonetwork app instead of the generic-gn5-app

@PascalLike PascalLike self-requested a review October 31, 2025 08:20
@davidblasby davidblasby changed the title git saContent neg plugin Content negotiation plugin (archetecture) Nov 3, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants