Architecture¶
Component overview¶
The library is organized around four core components:
- Session
- The main entry point. Owns authentication, base URL construction, request/response handling, and diagnostic state. Provides generated command methods for all MQSC commands. A single session represents a connection to one queue manager's REST API.
- Command methods
- ~144 generated MQSC command methods. Each method is a thin wrapper that
calls the internal command dispatcher with the correct command verb and
qualifier. Method names follow the pattern
verb_qualifier(orverbQualifierin camelCase languages), mapping directly to MQSC commands. For example,DISPLAY QUEUEbecomesdisplay_queue/displayQueue, andDEFINE QLOCALbecomesdefine_qlocal/defineQlocal. - Ensure methods
- 16 idempotent ensure methods for declarative object management. Each
method checks current state with DISPLAY, then DEFINE, ALTER, or no-ops
as needed. Returns an ensure result indicating what action was taken.
The queue manager variant is a special singleton (no name, no DEFINE).
Only changed attributes are sent in ALTER commands, preserving
ALTDATE/ALTTIMEaudit timestamps. - Mapping pipeline
- Bidirectional attribute translation between developer-friendly names and native MQSC parameter names. Includes key mapping (attribute names), value mapping (enumerated values), and key-value mapping (combined name+value translations). The mapping tables were bootstrapped from IBM MQ 9.4 documentation and cover all standard MQSC attributes.
- Exception hierarchy
- Structured error types for transport failures, malformed responses, authentication errors, MQSC command errors, and polling timeouts. All exceptions carry diagnostic context including the full MQ response payload when available.
In the Java implementation, the core components map to these classes:
MqRestSession: The main entry point. A single class (no mixin decomposition) that owns connection details, authentication, mapping configuration, diagnostic state, and all ~144 command methods plus 16 ensure methods. Created via a builder pattern.- Command methods: Generated methods on
MqRestSession(e.g.displayQueue(),defineQlocal(),deleteChannel()). Each method is a thin wrapper that calls the internalmqscCommand()dispatcher with the correct verb and qualifier. AttributeMapper: Handles bidirectional attribute translation usingMappingDataloaded from a JSON resource file. See the Mapping Pipeline for details.- Exception hierarchy: Sealed exception classes rooted at
MqRestException. All are unchecked (RuntimeException), so callers are not forced to catch them but can choose to handle specific subtypes.
Request lifecycle¶
Every MQSC command follows the same path through the system:
Method call (e.g. displayQueue / display_queue)
→ command dispatcher
→ Map request attributes (friendly names → MQSC)
→ Map response parameter names
→ Map WHERE keyword
→ Build runCommandJSON payload
→ Transport POST
→ Parse JSON response
→ Extract commandResponse items
→ Flatten nested objects
→ Map response attributes (MQSC → friendly names)
→ Return result
Build phase¶
- The command method calls the internal dispatcher with the MQSC verb (e.g.
DISPLAY), qualifier (e.g.QUEUE), and user-supplied parameters. - If mapping is enabled, request attributes are translated from friendly names to MQSC parameter names via the qualifier's request key map and request value map.
- Response parameter names are mapped similarly.
- A
WHEREclause keyword, if provided, is mapped through the same qualifier key maps. - The
runCommandJSONpayload is assembled and sent via the transport.
Parse phase¶
- The JSON response is parsed and validated.
- Error codes (
overallCompletionCode,overallReasonCode, per-itemcompletionCode/reasonCode) are checked. Errors raise a command exception. - The
parametersdict is extracted from eachcommandResponseitem. - Nested
objectslists (e.g. fromDISPLAY CONN TYPE(HANDLE)) are flattened into the parent parameter set. - If mapping is enabled, response attributes are translated from MQSC to friendly names.
In Java, the command dispatcher is the internal mqscCommand() method on
MqRestSession. Every public command method (e.g. displayQueue(),
defineQlocal()) delegates to it with the appropriate verb and qualifier.
The session retains diagnostic state from the most recent command for inspection:
session.displayQueue("MY.QUEUE");
session.getLastCommandPayload(); // the JSON sent to MQ
session.getLastResponsePayload(); // the parsed JSON response
session.getLastHttpStatus(); // HTTP status code
session.getLastResponseText(); // raw response body
Transport abstraction¶
The session object does not make HTTP calls directly. Instead, it delegates to a transport interface that defines a single method for posting JSON payloads:
- URL: The fully-qualified endpoint URL.
- Payload: The
runCommandJSONrequest body. - Headers: Authentication, CSRF token, and optional gateway headers.
- Timeout: Per-request timeout duration.
- TLS verification: Whether to verify server certificates.
The transport returns a response object containing the HTTP status code, response body, and response headers.
The default implementation wraps the language's standard HTTP client. Tests inject a mock transport to avoid network calls, making the entire command pipeline testable without an MQ server.
In Java, the transport is defined by the MqRestTransport interface:
public interface MqRestTransport {
TransportResponse postJson(
String url,
Map<String, Object> payload,
Map<String, String> headers,
Duration timeout,
boolean verifyTls
);
}
The default implementation, HttpClientTransport, uses java.net.http.HttpClient
(JDK built-in). It accepts an optional SSLContext at construction for mTLS
client certificate authentication.
For testing, inject a mock or lambda transport:
MqRestTransport mockTransport = (url, payload, headers, timeout, verify) ->
new TransportResponse(200, responseJson, Map.of());
var session = MqRestSession.builder()
.host("localhost")
.port(9443)
.queueManager("QM1")
.credentials(new LtpaAuth("admin", "passw0rd"))
.transport(mockTransport)
.build();
This makes the entire command pipeline testable without an MQ server.
Single-endpoint design¶
All MQSC operations go through a single REST endpoint:
The runCommandJSON payload specifies the MQSC verb, qualifier, object name,
parameters, and response parameters. This design means the library needs
exactly one HTTP method and one URL pattern to cover all MQSC commands.
In Java, this means every command method on MqRestSession ultimately calls the
same postJson() method on the transport with the same URL pattern. The only
variation is the JSON payload content.
Gateway routing¶
The MQ REST API is available on all supported IBM MQ platforms (Linux, AIX, Windows, z/OS, and IBM i). The library is developed and tested against the Linux implementation.
In enterprise environments, a gateway queue manager can route MQSC commands
to remote queue managers via MQ channels — the same mechanism used by
runmqsc -w and the MQ Console.
When a gateway queue manager is configured on the session:
- The URL path targets the remote queue manager:
POST /admin/action/qmgr/{TARGET_QM}/mqsc - The
ibm-mq-rest-gateway-qmgrHTTP header names the local queue manager that routes the command.
When no gateway is configured (the default), no gateway header is sent and the REST API talks directly to the queue manager in the URL. This makes the feature purely additive — existing sessions are unaffected.
Client Gateway QM (QM1) Target QM (QM2)
│ │ │
│ POST /qmgr/QM2/mqsc │ │
│ Header: gateway-qmgr=QM1 │ │
│─────────────────────────────>│ MQSC via MQ channel │
│ │─────────────────────────────>│
│ │<─────────────────────────────│
│<─────────────────────────────│ │
Prerequisites¶
- The gateway queue manager must have a running REST API.
- MQ channels must be configured between the gateway and target queue managers.
- A QM alias (QREMOTE with empty RNAME) must map the target QM name to the correct transmission queue on the gateway.
In Java, configure gateway routing via the session builder:
var session = MqRestSession.builder()
.host("qm1-host")
.port(9443)
.queueManager("QM2") // target (remote) queue manager
.credentials(new LtpaAuth("mqadmin", "mqadmin"))
.gatewayQmgr("QM1") // local gateway queue manager
.build();
Runtime dependencies¶
The library has a single runtime dependency: Gson (~280KB) for JSON
serialization. All other functionality uses JDK built-in APIs
(java.net.http.HttpClient, javax.net.ssl).
Package structure¶
io.github.wphillipmoore.mq.rest.admin
MqRestSession — Main entry point (builder, commands, ensure, diagnostics)
MqRestTransport — Transport interface
HttpClientTransport — Default transport (java.net.http.HttpClient)
TransportResponse — HTTP response record (statusCode, body, headers)
io.github.wphillipmoore.mq.rest.admin.auth
Credentials — Sealed interface
BasicAuth — HTTP Basic authentication
LtpaAuth — LTPA token-based authentication (auto-login)
CertificateAuth — Client certificate authentication (mTLS)
io.github.wphillipmoore.mq.rest.admin.exception
MqRestException — Sealed base class (RuntimeException)
MqRestTransportException — Network/connection failures
MqRestResponseException — Malformed JSON, unexpected structure
MqRestAuthException — Authentication/authorization failures
MqRestCommandException — MQSC command returned error codes
MqRestTimeoutException — Polling timeout exceeded
io.github.wphillipmoore.mq.rest.admin.mapping
AttributeMapper — Bidirectional attribute translation engine
MappingData — Mapping tables loaded from JSON resource
MappingIssue — Tracks individual mapping problems
MappingException — Thrown on strict-mode mapping failure
MappingOverrideMode — MERGE or REPLACE override strategy
io.github.wphillipmoore.mq.rest.admin.ensure
EnsureAction — Enum: CREATED, UPDATED, UNCHANGED
EnsureResult — Record: action + changed attribute names
Ensure pipeline¶
See ensure for details on the idempotent create-or-update pipeline.
Sync pipeline¶
See sync for details on the synchronous polling pipeline.