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 Ruby implementation, the core components map to these types:
Session: The main entry point. A single class that owns connection details, authentication, mapping configuration, diagnostic state, and all 148 command methods plus 16 ensure methods and 9 sync methods. Created viaSession.newwith keyword arguments.- Command methods: Instance methods on
Session(e.g.display_queue,define_qlocal,delete_channel). Each method is a thin wrapper that calls the internalmqsc_commanddispatcher with the correct verb and qualifier. Mappingmodule: Internal module that handles bidirectional attribute translation using mapping data loaded from a bundled JSON resource. See the mapping pipeline for details.- Error classes: A hierarchy under
MQ::REST::Admin::Errorwith specific subclasses (TransportError,CommandError, etc.) forrescuematching.
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 Ruby, the command dispatcher is the private mqsc_command method on
Session. Every public command method (e.g. display_queue,
define_qlocal) delegates to it with the appropriate verb and qualifier.
The session retains diagnostic state from the most recent command for inspection:
session.display_queue(name: 'MY.QUEUE')
session.last_command_payload # the Hash sent to MQ
session.last_response_payload # the parsed Hash response
session.last_http_status # HTTP status code
session.last_response_text # 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 Ruby, the transport is defined by a duck-type contract:
# Any object responding to #post_json with this signature
def post_json(url, payload, headers:, timeout_seconds:, verify_tls:)
# Returns a TransportResponse
end
The default NetHTTPTransport uses net/http. Custom implementations can be
injected via the transport: keyword argument for testing or specialized HTTP
handling.
For testing, inject a mock transport:
class MockTransport
attr_reader :calls
def initialize(responses: [])
@responses = responses
@call_index = 0
@calls = []
end
def post_json(url, payload, headers:, timeout_seconds:, verify_tls:)
@calls << { url: url, payload: payload }
response = @responses[@call_index]
@call_index += 1
response || MQ::REST::Admin::TransportResponse.new(
status_code: 200,
body: '{"commandResponse":[]}',
headers: {}
)
end
end
session = MQ::REST::Admin::Session.new(
'https://localhost:9443/ibmmq/rest/v2', 'QM1',
credentials: MQ::REST::Admin::BasicAuth.new(username: 'admin', password: 'pass'),
transport: MockTransport.new
)
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 Ruby, this means every command method on Session ultimately calls the
same post_json 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 Ruby, configure gateway routing via a keyword argument:
session = MQ::REST::Admin::Session.new(
'https://qm1-host:9443/ibmmq/rest/v2',
'QM2', # target (remote) queue manager
credentials: MQ::REST::Admin::BasicAuth.new(username: 'mqadmin', password: 'mqadmin'),
gateway_qmgr: 'QM1' # local gateway queue manager
)
Zero dependencies¶
The gem uses only the Ruby standard library:
net/httpfor HTTPjsonfor JSONopensslfor TLS/mTLSbase64for Basic auth encoding
Ensure pipeline¶
See ensure for details on the idempotent create-or-update pipeline.
Sync pipeline¶
See sync for details on the synchronous polling pipeline.