Skip to content

PDF Render Module

The PDF Render module (system.shopAccess.pdfRender) provides a service for generating PDF documents via the external Documint API. It acts as the system’s single integration point with Documint — all printing operations (kanban cards, labels, breadcrumbs, purchase orders) pass through this module.

The module has no domain logic of its own. It accepts a pre-constructed rendering job (template ID + payload grid) from a calling module, forwards it to Documint, and returns the resulting PDF URL. Template selection, payload construction, and post-print side effects (e.g., updating print status) are the responsibility of the calling module.

  • Item Module (reference.item): Calls PdfRenderService.render() to print labels and breadcrumbs via ItemPrintingService
  • Kanban Cards Module (resources.kanban): Calls PdfRenderService.render() to print kanban cards via PrintLifecycleImpl
  • Documint API (external): The third-party PDF rendering service at api.documint.me

PlantUML diagram

The module exposes an interface with two methods:

PlantUML diagram

ParameterTypeDescription
jobRenderJobThe template configuration and payload grid to render
authorStringThe user who initiated the print (passed through but not included in the Documint payload)
liveBoolean?true for production rendering (counts against quota), false for test/preview (watermarked). null uses the module default.

Returns: Result<RenderResult> — on success, contains the PDF URL, a generated job ID, the current timestamp, and the template ID used.

A RenderJob bundles a template configuration with a grid payload:

FieldTypeDescription
templateConfigPrintingTemplateConfigurationTemplate ID, column count, description, and active flag
payloadGridThe grid of JSON elements arranged into rows and columns

The Grid is constructed from a flat list of JSON elements (one per item) chunked by the template’s column count. For a 2-column template with 5 items, the grid has 3 rows: two full rows of 2 and one row of 1 (padded with an empty JSON object).

FieldTypeDescription
urlURLPre-signed S3 URL to the generated PDF
jobUUIDUnique identifier for this render job (generated server-side)
asOFTimeCoordinatesBitemporal timestamp when the render occurred
templateIdStringThe Documint template ID that was used
ParameterTypeDescription
groupsList<Pair<PrintingTemplateConfiguration, List<JsonElement>>>List of (template config, item JSON elements) pairs — one pair per template group
authorStringThe user who initiated the print
liveBoolean?Rendering mode. null uses the module default.
debugBooleanWhen true, includes the constructed Documint payload (debugPayload) in each GroupRenderResult. Default: false.
dryRunBooleanWhen true, constructs the payload but skips the Documint API call. Returns payload without generating PDFs. No side effects. Implies debug. Default: false.

Returns: Result<CompositeRenderResult> — contains one GroupRenderResult per template group (or sub-batch if a group was split).

Responsibilities:

  1. For each group, split into sub-batches if the element count exceeds maxItemsPerDocumintRequest
  2. Pack each batch into a Grid using the template’s column count
  3. Render all batches via DocumintProxy.render() in parallel, limited by Semaphore(maxParallelRenders)
  4. Map each Documint response to a GroupRenderResult (URL on success, error message on failure)
  5. Compose results into a CompositeRenderResult with a generated job UUID and current timestamp
FieldTypeDescription
jobUUIDUnique identifier for the composite print job
asOFTimeCoordinatesBitemporal timestamp when the render occurred
resultsList<GroupRenderResult>One entry per template group/sub-batch
FieldTypeDescription
templateIdStringDocumint template ID
descriptionStringHuman-readable template description (e.g., “3 x 5”)
itemCountIntNumber of items in this group/sub-batch
urlURL?PDF URL on success, null on failure or dry-run
errorString?Error message on failure, null on success
debugPayloadJsonElement?Constructed Documint payload. Present when debug=true or dryRun=true. Omitted from JSON when null.

PlantUML diagram

PlantUML diagram

The module is configured via shop-access/pdf-render/application.conf with two sections:

KeyTypeDefaultDescription
documint.useLiveBooleanfalseDefault rendering mode. false = preview (watermarked, no quota impact). true = production (counts against Documint quota).
documint.apiKeyString(from build system)API key for authenticating with the Documint service. Injected at build/deploy time.
KeyTypeDefaultDescription
servers.documint.protocolStringhttpsHTTP protocol
servers.documint.hostStringapi.documint.meDocumint API hostname
servers.documint.portInt443HTTPS port
servers.documint.basePathString1/templatesAPI root path
servers.documint.retriesInt0HTTP retry count

The module initializes via Application.pdfRenderService():

  1. Loads module configuration from path system.shopAccess.pdfRender
  2. Reads documint.useLive from extras (defaults to false)
  3. Constructs a DocumintProxy with:
    • Server config (protocol, host, port, basePath) from servers.documint
    • API key from extras.documint.apiKey
    • A shared HTTP client
  4. Registers the module with the ModuleRegistry
  5. Returns PdfRenderService.Impl configured with the proxy and the default live flag

The DocumintProxy can be injected for testing via the optional injectedDocumintProxy parameter on pdfRenderModule().

The module communicates with Documint via a single HTTP endpoint:

Request:

  • Method: POST
  • URL: https://api.documint.me/1/templates/{templateId}/content?preview={!live}&active={live}
  • Header: api_key: {apiKey}
  • Content-Type: application/json
  • Body: The Grid JSON — an object with a row array of PrintColumn objects, each containing a column array of item JSON objects

Response (success):

{
"name": "Document Name",
"template": "template-id",
"account": "account-id",
"url": "https://documint.s3.amazonaws.com/...pdf"
}

The url field is a pre-signed S3 URL to the generated PDF document.

Response (error): Non-200 HTTP status with an error body. The module wraps these as AppError.ExternalService with the HTTP status code and response body.