Clients - Smile CDR Documentation

Available Clients in SmileHarness

The SmileHarness interface provides access to various clients that can be used to interact with different aspects of a Smile CDR instance. This document provides detailed information about these clients, their capabilities, and how to use them effectively.

FHIR Clients

FHIR clients are used to interact with FHIR resources on the Smile CDR server. The SmileHarness interface provides several methods to obtain FHIR clients with different configurations.

Standard FHIR Client

IGenericClient fhirClient = harness.getFhirClient();

Copy

This method returns a standard FHIR client that can be used to interact with the FHIR endpoint. By default, this client does not include any authentication, so you may need to add an interceptor for authenticated requests. Variants:

Superuser FHIR Client

IGenericClient superuserFhirClient = harness.getSuperuserFhirClient();

Copy

This method returns a FHIR client with superuser (admin) credentials already configured. This is useful for administrative tasks or tests that require elevated privileges. Variants:

FHIR Client Capabilities The FHIR clients returned by these methods are instances of HAPI FHIR's IGenericClient, which provides a comprehensive API for interacting with FHIR resources. Some common operations include:

For more information on using HAPI FHIR clients, see the HAPI FHIR documentation.

Admin JSON Client

The Admin JSON client is used to interact with the Smile CDR administrative API, which provides access to configuration, monitoring, and management functions.

AdminJsonRestClient adminClient = harness.getAdminJsonClient();

Copy

Variants:

Admin JSON Client Capabilities The AdminJsonRestClient provides methods for interacting with various aspects of the Smile CDR administrative API:

The Admin JSON client is particularly useful for:

Waiting for Module Restart Both updateModuleConfig(...) and restartModule(...) wait for the module to come back up by default. The short-form overloads block until the target module's first process reports STARTED, so tests can exercise the module immediately after the call returns without racing the restart. Callers that want the old fire-and-forget behavior use the explicit boolean shouldWaitForRestart overloads.

// Default — block until the module is STARTED again.
adminClient.restartModule(nodeId, moduleId);
adminClient.updateModuleConfig(nodeId, moduleId, options, /*restart*/ true, /*reload*/ false);

// Opt out of the wait (fire-and-forget — return as soon as the admin API accepts the request).
adminClient.restartModule(nodeId, moduleId, /*shouldWaitForRestart*/ false);
adminClient.updateModuleConfig(nodeId, moduleId, options, /*restart*/ true, /*reload*/ false, /*shouldWaitForRestart*/ false);

// updateModuleConfig only polls when either 'restart' or 'reload' is also true — otherwise wait is a no-op.

// Override the 90s default with a custom wait timeout (e.g. a longer budget for slow CI).
adminClient.restartModule(nodeId, moduleId, /*shouldWaitForRestart*/ true, Duration.ofMinutes(3));
adminClient.updateModuleConfig(nodeId, moduleId, options, /*restart*/ true, /*reload*/ false, /*shouldWaitForRestart*/ true, Duration.ofMinutes(3));

Copy

Polling behavior:

Pass false when the test does not need to interact with the module immediately after restart, or when you want the caller to be responsible for waiting (e.g. via a custom readiness check). Passing true is the recommended default for most integration tests — it removes the need for ad-hoc Awaitility blocks around module restarts.

HL7v2 REST Client

The HL7v2 REST client is used to interact with the Smile CDR HL7v2 endpoint, which allows sending and receiving HL7v2 messages.

HL7V2RestClient hl7v2Client = harness.getHL7V2RestClient();

Copy

Variants:

HL7v2 REST Client Capabilities The HL7V2RestClient provides methods for sending HL7v2 messages to the Smile CDR server:

This client is particularly useful for testing HL7v2 integration scenarios, such as:

FHIR Context

While not a client per se, the SmileHarness also provides access to the FHIR context, which is useful for working with FHIR resources programmatically.

FhirContext fhirContext = harness.getFhirContext();

Copy

Variants:

FHIR Context Capabilities The FhirContext provides various utilities for working with FHIR resources:

Outbound SMART Client

The Outbound SMART client is used to perform OAuth 2.0 SMART on FHIR authorization flows for testing outbound authentication scenarios.

OutboundSmartClient smartClient = harness.getOutboundSmartClient();

Copy

Variants:

Outbound SMART Client Capabilities The OutboundSmartClient provides methods for OAuth 2.0 authorization flows:

Implemented Methods:

API Stubs (Not Yet Implemented):

This client is particularly useful for testing:

NPM Package Client

The NPM Package client is used to interact with Smile CDR's package registry endpoint, which provides access to FHIR Implementation Guide and package management functionality.

This tool is meant for uploading Implementation Guides or other FHIR Packages to the repository. You can find out more about creating your own packages here.

NpmPackageClient npmClient = harness.getNpmPackageClient();

Copy

Variants:

NPM Package Client Capabilities The NpmPackageClient provides methods for installing FHIR packages on the Smile CDR server:

Using PackageSpecBuilder The PackageSpecBuilder provides a fluent API for creating package installation specifications:

PackageInstallationSpec spec = PackageSpecBuilder
    .name("test-profile")
    .version("1.0.0")
    .packageUrl("classpath:/test_ig.tgz")
    .storeOnly()
    .build();

PackageInstallOutcomeJson outcome = npmClient.installPackageBySpec(spec);

Copy

Alternative JSON String Usage:

String packageSpecJson = """
    {
        "name": "my-implementation-guide",
        "version": "1.0.0",
        "packageUrl": "classpath:/my_ig.tgz",
        "installMode": "STORE_AND_INSTALL",
        "reloadExisting": false,
        "fetchDependencies": true,
        "installResourceTypes": ["StructureDefinition", "ValueSet"]
    }
    """;

PackageInstallOutcomeJson outcome = npmClient.installPackageBySpec(packageSpecJson);

Copy

Builder Methods:

Advanced Configuration Example:

PackageInstallationSpec spec = PackageSpecBuilder
    .name("advanced-profile")
    .version("2.0.0")
    .packageUrl("classpath:/advanced_ig.tgz")
    .storeAndInstall()
    .reloadExisting(false)
    .fetchDependencies(true)
    .installResourceTypes("StructureDefinition", "ValueSet", "CodeSystem")
    .build();

Copy

This client is particularly useful for testing:

Client Lifecycle and Ownership

Every client a harness hands out issues on the harness's own HTTP client, so they share one connection pool and one cookie store. A login performed through one is visible to the next; see Sessions, Cookies and Harness Lifecycle.

AdminJsonRestClient, HL7V2RestClient and NpmPackageClient are AutoCloseable, and what close() does depends on where the client came from:

To build several clients directly and have them share one pool and one session, create a SmileTestHttpClient yourself and pass it to each — you own it, so close it when you are done, and the clients built over it need no closing of their own:

try (SmileTestHttpClient httpClient = SmileTestHttpClient.create()) {
    AdminJsonRestClient adminClient = AdminJsonRestClient.issuingOn(httpClient, baseUrl, "admin", "password");
    NpmPackageClient npmClient = NpmPackageClient.issuingOn(httpClient, baseUrl, "admin", "password");
    // a session established through adminClient is visible to npmClient
}

Copy

open(...), openAnonymous(...) and issuingOn(...) all exist on AdminJsonRestClient, HL7V2RestClient and NpmPackageClient, so the name tells you at the call site which of the two owns the pool. Working through a SmileHarness needs none of this — the harness already shares its client with everything it hands out.

The older build(...) and buildAnonymous(...) factories still work and are deprecated, because neither name said who owned the pool. Replace build(url, user, pass) with open(...) and buildAnonymous(url) with openAnonymous(...).

Redirects are not followed by any of these clients, so a 3xx is returned rather than resolved.

Future Clients

The SmileHarness interface includes comments about potential future clients that may be added:

These clients are not yet implemented but may be added in future versions of the library.

Best Practices

When working with these clients, consider the following best practices:

  1. Reuse Clients: Create clients once and reuse them throughout your tests to avoid unnecessary overhead.
  2. Close Resources: Make sure to close any resources (like input streams) that you open.
  3. Handle Exceptions: Properly handle exceptions that may be thrown by client methods.
  4. Use Appropriate Authentication: Use the appropriate level of authentication for your tests.
  5. Clean Up: Clean up any resources you create during tests to avoid affecting other tests.

For more recommendations on effective testing with SmileCdrContainer and SmileHarness, see Best Practices.

Usage

Clients

Testing Tools

Overview Usage Clients Best Practices

Best Practices