Analyzer Bridge -> OpenELIS FHIR forwarding: HAPI-0287 on webapp /fhir, mTLS required on external-fhir-api - which is the intended path?

Hi all,

I’m integrating two veterinary lab analyzers (via ASTM) through the
openelis-analyzer-bridge (legacy image: itechuw/astm-http-bridge:3.0.4)
into a self-hosted OpenELIS Global 2 instance deployed via the official
openelis-docker Compose setup (image tag 3.2.1.11). I’ve got the
following working already:

  • Bridge successfully authenticates to the webapp’s REST API
    (https://oe.openelis.org:8443/OpenELIS-Global/rest/analyzer/analyzers)
    and pulls the analyzer registry correctly (confirmed via bridge logs:
    “Bootstrap complete: pulled 2 analyzers from OE”).
  • A simulated ASTM message (ENQ/ACK handshake, framed STX/ETX records)
    sent to the bridge’s ASTM listener is correctly received, parsed, and
    converted into a FHIR Bundle by the bridge.

Where I’m stuck is the actual result forwarding step. The bridge takes
that Bundle and POSTs it to:

https://oe.openelis.org:8443/OpenELIS-Global/fhir

(i.e. the main webapp container’s own /fhir path, derived automatically
by the bridge from the same base URI used for the REST registry pull).

This returns HTTP 400 with:

{"resourceType":"OperationOutcome","issue":[{"severity":"error",
"code":"processing","diagnostics":"HAPI-0287: This is the base URL
of FHIR server. Unable to handle this request, as it does not
contain a resource type or operation name."}]}

I noticed the deployment also runs a separate, dedicated FHIR container
(external-fhir-api / itechuw/openelis-global-2-fhir), so I tried POSTing
the same Bundle directly to that instead:

https://fhir.openelis.org:8443/fhir

But this container appears to require mutual TLS - the TLS handshake
includes a “Request CERT” step, and since curl didn’t present a client
certificate, the server responded with a “bad certificate” TLS alert.

My questions:

  1. For analyzer-bridge result forwarding, is the intended target the
    main webapp’s own /fhir path, or the standalone external-fhir-api
    container?

  2. If it’s the webapp’s own /fhir path - is HAPI-0287 here a sign that
    the transaction Bundle provider isn’t registered/enabled by default
    in this deployment, and if so, what’s the config to enable it?

  3. If it’s meant to be the standalone external-fhir-api container - how
    are client certificates for internal/mTLS calls normally provisioned
    in this stack? Is there a documented CA or cert-generation step for
    internal service-to-service calls (I see a “certgen” container in
    the Compose file - is that related)?

Happy to share full bridge/webapp logs, my configuration.yml, and
docker-compose.yml if useful. Thanks in advance for any pointers!

I have a similar issue with getting data back from fhir-api to OpenELIS UI.

To send data to FHIR server you need to get client certs like:

#!/usr/bin/env bash
set -e

# This script extracts the CA root certificate, client certificate, and client private key from the Java keystore and truststore used by the OpenELIS FHIR API service running in a Docker container. The extracted certificates and keys are saved in a specified output directory for use in Rust applications or other clients that require these credentials.



# Configuration (Ensure your container name matches your docker ps)
FHIR_CONTAINER="external-fhir-api"
OUTPUT_DIR="./fhir-client-certs"

# Default OpenELIS Keystore and Truststore passwords
KEYSTORE_PASS="kspass"
TRUSTSTORE_PASS="tspass"

OPENSSL_PKCS12_FLAGS=()
if openssl pkcs12 -help 2>&1 | grep -q -- "-legacy"; then
  OPENSSL_PKCS12_FLAGS+=("-legacy")
fi

echo "🚀 Starting extraction directly from Java keystores..."
mkdir -p "$OUTPUT_DIR"

# ==========================================
# 1. EXTRACT CA ROOT CERTIFICATE
# ==========================================
echo "📦 Pulling Truststore to generate ca_root.crt..."
docker cp "${FHIR_CONTAINER}:/etc/openelis-global/truststore" "${OUTPUT_DIR}/truststore.jks"

# Convert JKS truststore to a PKCS12 file first, then parse out the CA Cert
keytool -importkeystore -srckeystore "${OUTPUT_DIR}/truststore.jks" \
        -destkeystore "${OUTPUT_DIR}/truststore.p12" \
        -srcstorepass "$TRUSTSTORE_PASS" -deststorepass "$TRUSTSTORE_PASS" \
        -deststoretype PKCS12 -noprompt 2>/dev/null

openssl pkcs12 "${OPENSSL_PKCS12_FLAGS[@]}" -in "${OUTPUT_DIR}/truststore.p12" -cacerts -nokeys \
               -out "${OUTPUT_DIR}/ca_root.crt" -passin pass:"$TRUSTSTORE_PASS"

# Clean up temp truststore artifacts
rm "${OUTPUT_DIR}/truststore.jks" "${OUTPUT_DIR}/truststore.p12"
echo "✅ Saved: ${OUTPUT_DIR}/ca_root.crt"

# ==========================================
# 2. EXTRACT CLIENT CERTIFICATE & CLIENT KEY
# ==========================================
echo "🎟️  Pulling Keystore to generate client.crt and client.key..."
docker cp "${FHIR_CONTAINER}:/etc/openelis-global/keystore" "${OUTPUT_DIR}/keystore.p12"

# Extract the client certificate (public key) from the client identity keystore
openssl pkcs12 "${OPENSSL_PKCS12_FLAGS[@]}" -in "${OUTPUT_DIR}/keystore.p12" -clcerts -nokeys \
               -out "${OUTPUT_DIR}/client.crt" -passin pass:"$KEYSTORE_PASS"
echo "✅ Saved: ${OUTPUT_DIR}/client.crt"

# Extract the client private key, stripping any password protection from the resulting PEM file
openssl pkcs12 "${OPENSSL_PKCS12_FLAGS[@]}" -in "${OUTPUT_DIR}/keystore.p12" -nocerts -nodes \
               -out "${OUTPUT_DIR}/client.key" -passin pass:"$KEYSTORE_PASS"
echo "✅ Saved: ${OUTPUT_DIR}/client.key"

# Clean up temp keystore artifact
rm "${OUTPUT_DIR}/keystore.p12"

echo "🎉 Success! Verified directory contents:"
ls -l "$OUTPUT_DIR"

And after you can send data back like:

curl -ks --cert "data/certs/client.crt" --key "data/certs/client.key" \
  -H "Content-Type: application/fhir+json" \
  -X POST \
  "https://localhost:8444/fhir" \
  -d @bundle.json

The real issue it that OpenELIS doesn’t get data back from FHIR server to the GUI. I was not able to figure that out.