Skip to content

SAIF.Services.Appworx architecture

SAIF.Services.Appworx is a small, single-purpose integration/service library. Despite the SAIF.Services.* naming it is not a hosted service — it is a thin client-side adapter, compiled directly into the LegalMaintenance web application, that translates a "run this batch job" intent into the Appworx enterprise scheduler's Oracle submission contract (the submit_appworx_job stored procedure).

Responsibilities

  • Translate a "run this batch job with these arguments" intent into the Appworx scheduler's Oracle submission contract (submit_appworx_job), normalizing argument handling (fixed 20 positional slots, empty-slot suppression, defaults for requestor and printer).
  • Provide a stateful instance API (clsRequestAppworxJob) and a stateless shared convenience overload (SubmitBatchJob) that constructs a fresh instance per call.
  • Reset argument state between submissions (InitArgs) so a reused instance cannot leak arguments from a previous job.
  • Optionally redirect submissions to a fixed, hard-coded Appworx-hosting Oracle database/schema (PRADT on WCISPROD/WCISDEV1) instead of the caller's own data portal, via the inUseWCISDEV1AppworxForAllDevEnv flag.

Component boundaries

  • clsRequestAppworxJob (class, SAIF.Services.Appworx/clsRequestAppworxJob.vb) is the sole hand-written type in the library. It has no base class, implements no interfaces, and takes no part in the BOF OnRetrieve/OnSave business-object lifecycle — it uses the BOF data portal purely as a command channel*.
  • Instance API: constructor, DPI, ModuleName, Requestor, Printer, Arg1–Arg20 properties, SubmitBatchJob (instance), InitArgs.
  • Shared convenience overload: SubmitBatchJob (Shared) — the form actually used by all in-repo callers — which optionally redirects the data portal, constructs the instance, maps only non-Nothing arguments, and submits.
  • No IBusinessCriteria implementations or nested Criteria types exist; the library performs no application-layer SQL beyond the single stored-procedure call.
  • The library is a leaf/foundation project with no outbound <ProjectReference> elements — all collaborators (IDataPortalInfo, clsSmartString, clsMSOracleDataLayer, AppGlobal) come from external SAIF framework packages, not from repo projects.

Interaction model

  • Application/business → scheduler: application managers in SAIF.Application.Claim.Legal (clsCreateFileManager, clsMailDateManager, clsRequestManager) call the shared SubmitBatchJob overload; from that point the work is asynchronous and out-of-process — the library returns as soon as the job row is accepted and has no visibility into scheduler execution, success, or output.
  • Library → database: all traffic goes through the BOF data portal (IDataPortalInfo.ProcessPortalRequest) rather than raw ADO.NET, so connection management, credentials, and provider selection are the framework's concern.
  • Deliberate escape hatch: the shared overload can bypass the caller's data portal entirely and construct its own clsMSOracleDataLayer("PRADT", "WCISPROD" | "WCISDEV1"), hard-coding a schema/owner and two database aliases directly into the library rather than relying on configuration.
  • Statefulness: the instance API is mutable and reusable (InitArgs allows resetting between submissions), but the shared overload creates a fresh instance per call, so the class is used statelessly by this repository's code.
  • Error posture: the only failure handling is a Try/Catch around ProcessPortalRequest that rethrows a wrapped ApplicationException; there is no logging, retry, or compensating action inside this library.

Architecture diagram

The following diagram shows the high-level flow from an application-layer caller through this library to the Appworx scheduler's Oracle stored procedure.

flowchart TD
    A[SAIF.Application.Claim.Legal<br>clsCreateFileManager / clsMailDateManager / clsRequestManager] --> B[clsRequestAppworxJob.SubmitBatchJob<br>Shared overload]
    B --> C[clsRequestAppworxJob<br>instance: ModuleName, Requestor, Printer, Arg1..Arg20]
    C --> D[clsRequestAppworxJob.SubmitBatchJob<br>instance method]
    D --> E[IDataPortalInfo.ProcessPortalRequest<br>BOF data portal]
    E --> F[submit_appworx_job<br>Oracle stored procedure]
    B -.optional redirect.-> G[clsMSOracleDataLayer<br>PRADT / WCISPROD or WCISDEV1]
    G --> E

Sequence diagram

The following diagram shows the primary submission sequence used by all observed in-repo call sites.

sequenceDiagram
    participant Caller as Application manager
    participant Shared as SubmitBatchJob (Shared)
    participant Instance as clsRequestAppworxJob
    participant Portal as IDataPortalInfo
    participant Proc as submit_appworx_job
    Caller->>Shared: SubmitBatchJob(inDPI, inModule, inRequestor, args...)
    Shared->>Instance: New clsRequestAppworxJob(lDPI)
    Instance->>Instance: InitArgs()
    Shared->>Instance: set ModuleName, Requestor, Printer, ArgN (non-Nothing only)
    Shared->>Instance: SubmitBatchJob()
    Instance->>Portal: ProcessPortalRequest(PortalRequest)
    Portal->>Proc: execute submit_appworx_job(inModule, inrequestor, inprinter, inargN...)
    Proc-->>Portal: NonQuery completion (no output)
    Portal-->>Instance: result
    Instance-->>Caller: returns (or rethrows wrapped ApplicationException)

Design constraints

  • No validation exists on ModuleName, Requestor, Printer, or argument content within this library; the receiving procedure also performs no validation**.
  • Parameter sizes are fixed to the scheduler's contract: module 30, requestor 32, printer 30, each argument 4000 characters.
  • The submission is fire-and-forget — RequestType = DataRequestType.NonQuery, no output parameters are registered, and the unused vResult local is never assigned or read, so callers cannot correlate a submission with a scheduler job instance from this library*.
  • Only argument slots explicitly set (non-Nothing on the shared overload, non-empty clsSmartString on the instance) are transmitted, so positional argument gaps are possible and expected (observed callers skip arg3).
  • The differing requestor defaults between the two entry points ("APPWORX" on the instance field vs. "Appworx" on the shared overload's optional parameter) mean the instance-field default is only observable when the class is constructed directly*.
  • No authorization checks are performed by this library; any caller holding a valid IDataPortalInfo can submit any Appworx module with any arguments — enforcement is the responsibility of the calling application layer and the database account behind the data portal*.

Note: Statements marked with * were inferred from code structure, naming conventions, or contextual evidence where direct confirmation was not available in source artifacts. Statements marked with ** could not be confirmed; treat as unknown until verified.

Sources

  • SAIF.Services.Appworx/SAIF.Services.Appworx.vbproj
  • SAIF.Services.Appworx/clsRequestAppworxJob.vb
  • SAIF.Services.Appworx/packages.config
  • SAIF.Services.Appworx/App.config
  • SAIF.Services.Appworx/Web.config
  • SAIF.Business.Claim.Legal/SAIF.Business.Claim.Legal.vbproj
  • SAIF.Application.Claim.Legal/SAIF.Application.Claim.Legal.vbproj
  • SAIF.Application.Claim.Legal/LegalNet/clsRequestManager.vb
  • SAIF.Application.Claim.Legal/LegalNet/clsMailDateManager.vb
  • SAIF.Application.Claim.Legal/LegalNet/clsCreateFileManager.vb