JMS Destination

Send messages to a JMS queue for integration with enterprise messaging systems.

Overview

The JMS destination publishes messages to a Java Message Service (JMS) queue, enabling integration with enterprise messaging systems such as Apache ActiveMQ and IBM MQ. JMS queues are common in large healthcare organizations that rely on Java-based middleware for reliable message delivery between clinical, administrative, and financial systems. This destination provides guaranteed delivery through the JMS provider's persistence and acknowledgment mechanisms.

Configuration

Define a JMS destination in your root intu.yaml under the destinations key:

yaml
# intu.yaml
destinations:
  legacy-mq:
    type: jms
    jms:
      provider: activemq
      url: tcp://activemq.hospital.internal:61616
      queue: HEALTHCARE.ADT.INBOUND
      auth:
        username: ${JMS_USER}
        password: ${JMS_PASS}
      timeout_ms: 30000

Properties

provider string required
JMS provider type. One of: activemq, ibmmq.
url string required
Connection URL for the JMS provider. Format depends on the provider: tcp://host:61616 for ActiveMQ, or the appropriate connection string for IBM MQ. Supports environment variable interpolation.
queue string required
The name of the JMS queue to send messages to.
timeout_ms int optional
Send timeout in milliseconds. Defaults to 30000 (30 seconds).
persistent bool optional
Use persistent delivery mode, ensuring messages survive broker restarts. Defaults to true.
priority int optional
JMS message priority (0-9). Higher values indicate higher priority. Defaults to 4 (normal).
ttl_ms int optional
Time-to-live in milliseconds for each message. Messages that exceed their TTL are discarded by the broker. Defaults to 0 (no expiration).

Authentication

auth.username string optional
Username for JMS broker authentication.
auth.password string optional
Password for JMS broker authentication. Use ${VAR} to reference environment variables.

IBM MQ Specific Properties

When using provider: ibmmq, additional properties are available:

queue_manager string optional
IBM MQ Queue Manager name.
channel_name string optional
IBM MQ server-connection channel name.

Full Example

Receive FHIR Encounter resources via HTTP, transform them to a legacy message format, and publish to an ActiveMQ queue consumed by a hospital billing system.

Root Configuration

yaml
# intu.yaml
destinations:
  billing-queue:
    type: jms
    jms:
      provider: activemq
      url: tcp://activemq.hospital.internal:61616
      queue: BILLING.ENCOUNTERS.INBOUND
      persistent: true
      priority: 6
      auth:
        username: ${JMS_USER}
        password: ${JMS_PASS}
      timeout_ms: 15000

Channel Configuration

yaml
# channels/encounter-to-billing/channel.yaml
name: encounter-to-billing
description: Transform FHIR Encounters to billing messages for legacy system

source:
  type: http
  http:
    port: 8082
    path: /fhir/Encounter

destinations:
  - billing-queue

Destination Transformer

typescript
// channels/encounter-to-billing/transformer.ts
import { Message, Context } from "@intu/sdk";

interface BillingMessage {
  messageType: string;
  encounterNumber: string;
  patientMrn: string;
  admitDate: string;
  dischargeDate: string;
  encounterClass: string;
  department: string;
  attendingProvider: string;
  diagnoses: Array<{
    code: string;
    system: string;
    display: string;
    rank: number;
  }>;
  procedures: Array<{
    code: string;
    system: string;
    display: string;
    date: string;
  }>;
}

export default function transform(msg: Message, ctx: Context): Message {
  const encounter = msg.body;

  const patientRef = encounter.subject?.reference ?? "";
  const patientMrn = patientRef.split("/").pop() ?? "";

  const billing: BillingMessage = {
    messageType: "ENCOUNTER_NOTIFICATION",
    encounterNumber: encounter.id ?? "",
    patientMrn,
    admitDate: encounter.period?.start ?? "",
    dischargeDate: encounter.period?.end ?? "",
    encounterClass: encounter.class?.code ?? "",
    department: encounter.serviceProvider?.display ?? "",
    attendingProvider:
      encounter.participant?.find(
        (p: any) => p.type?.[0]?.coding?.[0]?.code === "ATND"
      )?.individual?.display ?? "",
    diagnoses: (encounter.diagnosis ?? []).map((d: any, i: number) => ({
      code: d.condition?.coding?.[0]?.code ?? "",
      system: d.condition?.coding?.[0]?.system ?? "",
      display: d.condition?.coding?.[0]?.display ?? "",
      rank: d.rank ?? i + 1,
    })),
    procedures: (encounter.procedure ?? []).map((p: any) => ({
      code: p.code?.coding?.[0]?.code ?? "",
      system: p.code?.coding?.[0]?.system ?? "",
      display: p.code?.coding?.[0]?.display ?? "",
      date: p.performedDateTime ?? "",
    })),
  };

  ctx.logger.info(
    `Publishing billing message for encounter ${billing.encounterNumber}`
  );

  return {
    ...msg,
    body: billing,
  };
}
Note Set persistent: true for healthcare messages to ensure they survive broker restarts. Non-persistent messages offer lower latency but risk data loss if the broker fails.
Tip Use the priority field to ensure time-sensitive messages (such as emergency department encounters) are processed ahead of routine messages in the queue.