CodamAIDocs
Topicdone

Embedded or as a service of its own

The two operating modes of CRMS: embedded in a CDMS application, or as a service of its own that others call through crms-client. One property, two jars, and the hub derives which mode a project gets.

Variants
local (embedded)remote (service of its own through crms-client)without CRMS

What this is about

CRMS runs in two ways, just like CIAS:

  • embedded (local): CRMS runs in the same process as a CDMS application. The application calls the ports as Java methods.
  • as a service of its own (remote): CRMS runs as a program of its own. Other applications call it over HTTP, with crms-client.

In terms of the subject area, CRMS behaves the same in both cases: the same ports, the same answers, the same error keys.

The two operating modes

localremote
Propertycodamai.crms.placement=localcodamai.crms.placement=remote
On the classpathstarter, the embedded CRMS (brings template management, renderer and evidence along), the chosen format modules, the CRMS HTTP interface and, as long as final documents are stored, the CRMS S3 storagestarter and crms-client, nothing else of CRMS
Callmethod call in the same processHTTP to the CRMS service
Databasethe database of the CDMS applicationthe service's own database
Scheduled passesrun in the application: anchoring and retentionrun in the CRMS service, not in the application
Editing templatesthrough /crms/** of the applicationdirectly through the routes of the CRMS service

The CRMS HTTP interface belongs to the embedded mode. An application that embeds CRMS serves /crms/** with it, and other applications can use it as a CRMS service. An application with remote must not have this interface. Otherwise it would pass the service on through routes of its own, behind its own security.

CIAS knows the same two shapes, see CIAS embedded (a single unit).

What is checked at start

The starter checks the property against the classpath before any other part of CRMS is created. If something does not match, the application does not start, and the message says which jar is missing or which one is too many.

CRMS renderer and crms-client together?codamai.crms.placementClasspathStart
yes––fails: embed or call, never both
nomissing or empty–fails: the property is required
noneither local nor remote–fails
nolocalembedded CRMS missingfails
noremotecrms-client missingfails
noremoteCRMS HTTP interface presentfails
nolocalembedded CRMS presentCRMS embedded
noremotecrms-client presentCRMS over HTTP

The property has no default. Otherwise a project scaffold that forgot it would silently run with the wrong mode.

In a native image, the classpath is already fixed at build time, while the property is only read at start. This is on purpose: a native image has a fixed classpath but runs in different environments. The environment variable for it is CODAMAI_CRMS_PLACEMENT.

The hub decides

A project in the hub has at most one CRMS module. Where you put this module, that is, into which runtime (the program that runs later), decides the operating mode of every CDMS application of the project. There is no field where you enter local or remote.

Does the project have a CRMS module?Does the CDMS application authenticate through CIAS?Where is the CRMS module?The CDMS application
no––without CRMS
yesnonot in its own runtimewithout CRMS
yesnoin its own runtimebuild refused: CRMS needs CIAS
yesyesin no runtimebuild refused: the CRMS module must be placed in a runtime
yesyesin its own runtimelocal: CRMS embedded
yesyesin another runtimeremote: client of the CRMS there

“In another runtime” means either a CRMS service of its own or another CDMS application of the project that embeds CRMS. If the CRMS module is in a runtime without a CDMS application, it becomes a CRMS service of its own.

The build then puts the matching dependencies into the POM. With local, only the format modules of the formats the CRMS module chose go in. With remote, no format module goes in, because the rendering happens in the service.

A call over HTTP

With remote one rule applies: the call carries the person, not the service. crms-client forwards the access token of the request the application is answering right now. It never sends a service token of its own. This way every revision, every approval and every final document names the person who caused it.

  1. 1
    User→Client
    clicks "Create report"
  2. 2
    Client→CDMS
    request with token: Authorization: Bearer …
  3. 3
    CDMS
    builds the payload and calls ReportRenderPort.render(…)
  4. 4
    CDMS
    is a request with a token running right now?
  5. 5
    CDMS
    no token, for example in a background job → crms-authentication-required, nothing is sent
  6. 6
    CDMS→CRMS
    crms-client sends POST /crms/render with the same token
  7. 7
    CRMS→Keycloak
    exchanges the token for its own, with the roles CRMS knows for this person
  8. 8
    CRMS
    renders as when embedded
  9. 9
    CRMS→CDMS
    answers with the document
  10. 10
    CDMS→Client
    passes the result on
    Result: The same RenderedDocument or the same CrmsException as when embedded

crms-client translates the answer back into the same objects and errors the embedded mode returns. If the service cannot be reached, the time runs out, or an answer comes back that is not from CRMS, the result is crms-unavailable, never half a result. The address of the service is in CODAMAI_CRMS_CLIENT_URL. More in The client.

Pitfalls

Next

Search