{"id":50701527,"url":"https://github.com/intersystems-ib/iris-azure-servicebus-interop","last_synced_at":"2026-06-09T09:30:32.423Z","repository":{"id":354674358,"uuid":"1224680263","full_name":"intersystems-ib/iris-azure-servicebus-interop","owner":"intersystems-ib","description":"InterSystems IRIS interoperability demo showing how to send to and receive from Azure Service Bus queues using embedded Python, custom inbound adapters, business services, and business operations.","archived":false,"fork":false,"pushed_at":"2026-04-29T14:18:11.000Z","size":14,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":0,"default_branch":"main","last_synced_at":"2026-04-29T16:22:40.622Z","etag":null,"topics":["azure","azure-service-bus","integration","interoperability","intersystems-iris","python"],"latest_commit_sha":null,"homepage":"","language":"ObjectScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/intersystems-ib.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2026-04-29T14:16:28.000Z","updated_at":"2026-04-29T14:22:34.000Z","dependencies_parsed_at":null,"dependency_job_id":null,"html_url":"https://github.com/intersystems-ib/iris-azure-servicebus-interop","commit_stats":null,"previous_names":["intersystems-ib/iris-azure-servicebus-interop"],"tags_count":null,"template":false,"template_full_name":null,"purl":"pkg:github/intersystems-ib/iris-azure-servicebus-interop","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/intersystems-ib%2Firis-azure-servicebus-interop","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/intersystems-ib%2Firis-azure-servicebus-interop/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/intersystems-ib%2Firis-azure-servicebus-interop/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/intersystems-ib%2Firis-azure-servicebus-interop/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/intersystems-ib","download_url":"https://codeload.github.com/intersystems-ib/iris-azure-servicebus-interop/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/intersystems-ib%2Firis-azure-servicebus-interop/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":34101064,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-05-26T15:22:16.424Z","status":"online","status_checked_at":"2026-06-09T02:00:06.510Z","response_time":63,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["azure","azure-service-bus","integration","interoperability","intersystems-iris","python"],"created_at":"2026-06-09T09:30:29.812Z","updated_at":"2026-06-09T09:30:32.415Z","avatar_url":"https://github.com/intersystems-ib.png","language":"ObjectScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"# InterSystems IRIS + Azure Service Bus Interoperability Demo\n\nThis repository is a small, focused example that shows how to connect **InterSystems IRIS interoperability productions** to **Azure Service Bus queues** by using **embedded Python**.\n\nIt is intended for customers who want to understand:\n\n- how to send messages from an IRIS Business Operation to Azure Service Bus\n- how to receive messages from Azure Service Bus through an IRIS inbound adapter and Business Service\n- how to structure inbound and outbound interoperability components in a simple IRIS production\n\nThe current implementation is deliberately compact. It favors clarity over completeness so the integration pattern is easy to inspect and reuse.\n\n* * *\n\n## What this repo demonstrates\n\nThe demo production contains two main integration paths:\n\n### Outbound path\n\nIRIS message -\u003e `Demo.Azure.ServiceBus.Outbound.BusinessOperation` -\u003e Azure Service Bus queue\n\nThe outbound Business Operation:\n\n- initializes the Azure SDK client and sender in `OnInit()`\n- reuses them while the BO job is running\n- sends one message body plus optional broker/application properties\n\n### Inbound path\n\nAzure Service Bus queue -\u003e `Demo.Azure.ServiceBus.Inbound.Adapter` -\u003e `Demo.Azure.ServiceBus.Inbound.BusinessService`\n\nThe inbound adapter:\n\n- receives messages using `PEEK_LOCK`\n- keeps locked messages in memory until IRIS processing finishes\n- completes messages on success\n- abandons messages on failure\n- can receive messages in batches\n\nThe inbound Business Service currently keeps the logic simple:\n\n- logs the received message\n- forwards it to a dummy target so the end-to-end IRIS flow can be inspected\n\n* * *\n\n## Repository structure\n\n```text\niris/src/Demo/Production.cls\niris/src/Demo/Azure/ServiceBus/Outbound/BusinessOperation.cls\niris/src/Demo/Azure/ServiceBus/Outbound/Request.cls\niris/src/Demo/Azure/ServiceBus/Outbound/Response.cls\niris/src/Demo/Azure/ServiceBus/Inbound/Adapter.cls\niris/src/Demo/Azure/ServiceBus/Inbound/BusinessService.cls\niris/src/Demo/Azure/ServiceBus/Inbound/Request.cls\ndocs/service-principal-passwordless.md\n```\n\nMain points:\n\n- `Demo.Production` is the top-level IRIS production\n- `Outbound/*` contains the send-to-Service-Bus flow\n- `Inbound/*` contains the receive-from-Service-Bus flow\n- `docs/service-principal-passwordless.md` captures a future passwordless setup using a service principal\n\n* * *\n\n## Requirements\n\nBefore starting, make sure you have:\n\n- [Git](https://git-scm.com/)\n- [Docker and Docker Compose](https://docs.docker.com/)\n- optionally [Visual Studio Code](https://code.visualstudio.com/) with the InterSystems ObjectScript extension\n- an Azure subscription\n- an Azure Service Bus namespace and queue\n\nThe container installs the required Python package for embedded Python:\n\n- `azure-servicebus`\n\n* * *\n\n## Getting started\n\nClone the repository and start the IRIS container:\n\n```bash\ngit clone \u003cyour-fork-or-repo-url\u003e\ncd iris-azure-interop\ndocker compose build\ndocker compose up -d\n```\n\nOnce the container is running:\n\n- Management Portal: `http://localhost:52776/csp/sys/UtilHome.csp`\n- Username: `superuser`\n- Password: `SYS`\n\nThe source code is loaded during image build from:\n\n- `iris/src`\n\n* * *\n\n## Azure Service Bus setup\n\nIf you do not already have a queue, start with Microsoft’s quickstart:\n\n- Azure Service Bus queue quickstart: https://learn.microsoft.com/en-us/azure/service-bus-messaging/service-bus-python-how-to-use-queues\n\nFor the current version of this repo, the simplest way to test is:\n\n- create a Service Bus queue\n- obtain a namespace connection string with send/receive permissions\n- configure the queue name in the IRIS production components\n\nImportant:\n\n- `QueueName` is only the queue name, for example `myqueue`\n- it is not a URL and not the full namespace\n\n* * *\n\n## Open the production\n\nIn the Management Portal:\n\n1. Go to **Interoperability** \u003e **Configure** \u003e **Production**\n2. Open `Demo.Production`\n\nYou should see at least these components:\n\n- `Azure ServiceBus Sender`\n- `Azure ServiceBus Receiver`\n\nThe production is intentionally small so it is easy to explore.\n\n* * *\n\n## Scenario 1: Send a message to Azure Service Bus\n\nOpen the component:\n\n- `Azure ServiceBus Sender`\n\nThis component is backed by:\n\n- `Demo.Azure.ServiceBus.Outbound.BusinessOperation`\n\nConfigure:\n\n- `ConnectionString`\n- `QueueName`\n\nWhat this component does:\n\n- accepts an IRIS outbound request\n- uses embedded Python with the Azure SDK\n- sends the request `Body` to the Azure queue\n- optionally maps:\n  - `MessageId`\n  - `CorrelationId`\n  - `Subject`\n  - `ApplicationPropertiesJSON`\n\n### What to inspect in the code\n\n- [BusinessOperation.cls](/Users/afuentes/Documents/ISC/workspace/iris-azure-interop/iris/src/Demo/Azure/ServiceBus/Outbound/BusinessOperation.cls:1)\n- [Request.cls](/Users/afuentes/Documents/ISC/workspace/iris-azure-interop/iris/src/Demo/Azure/ServiceBus/Outbound/Request.cls:1)\n- [Response.cls](/Users/afuentes/Documents/ISC/workspace/iris-azure-interop/iris/src/Demo/Azure/ServiceBus/Outbound/Response.cls:1)\n\nFocus on:\n\n- `OnInit()`\n- `OnMessage()`\n- `PySendMessage()`\n\n### What to test\n\nUse the component test tool in the production to send an instance of:\n\n- `Demo.Azure.ServiceBus.Outbound.Request`\n\nSuggested values:\n\n- `Body`: a JSON string such as `{\"hello\":\"from iris\"}`\n- `MessageId`: a unique string\n- `Subject`: something like `demo`\n\nThen check the queue in Azure Portal using Service Bus Explorer.\n\n* * *\n\n## Scenario 2: Read a message from Azure Service Bus\n\nOpen the component:\n\n- `Azure ServiceBus Receiver`\n\nThis receiver is backed by:\n\n- Business Service: `Demo.Azure.ServiceBus.Inbound.BusinessService`\n- Adapter: `Demo.Azure.ServiceBus.Inbound.Adapter`\n\nConfigure on the receiver:\n\n- `ConnectionString`\n- `QueueName`\n- `MaxMessageCount`\n- `MaxWaitTime`\n\n### How the inbound flow works\n\n1. The adapter polls Azure Service Bus using `PEEK_LOCK`\n2. It receives up to `MaxMessageCount` messages in one cycle\n3. It converts the Azure message data into `Demo.Azure.ServiceBus.Inbound.Request`\n4. It calls the Business Service\n5. If processing succeeds, the adapter completes the Azure message\n6. If processing fails, the adapter abandons the Azure message\n\nThis keeps the example reliable while still showing a more realistic batched adapter design.\n\n### What to inspect in the code\n\n- [Adapter.cls](/Users/afuentes/Documents/ISC/workspace/iris-azure-interop/iris/src/Demo/Azure/ServiceBus/Inbound/Adapter.cls:1)\n- [BusinessService.cls](/Users/afuentes/Documents/ISC/workspace/iris-azure-interop/iris/src/Demo/Azure/ServiceBus/Inbound/BusinessService.cls:1)\n- [Request.cls](/Users/afuentes/Documents/ISC/workspace/iris-azure-interop/iris/src/Demo/Azure/ServiceBus/Inbound/Request.cls:1)\n\nFocus on:\n\n- `OnTask()`\n- `PyReceiveBatch()`\n- `PyCompleteMessageByToken()`\n- `PyAbandonMessageByToken()`\n\n### What to test\n\n1. Send one or more messages into the Azure queue\n2. Start the production\n3. Open the Message Viewer in IRIS\n4. Verify that the inbound service logs the body and message ID\n\n* * *\n\n## Why embedded Python is used this way\n\nInterSystems IRIS requires interoperability callback methods such as:\n\n- `OnInit()`\n- `OnTearDown()`\n- `OnMessage()`\n- `OnTask()`\n\nto remain in ObjectScript.\n\nThe Azure SDK logic is therefore placed in helper methods marked:\n\n- `[ Language = python ]`\n\nThis repo shows that pattern directly in both inbound and outbound components.\n\n* * *\n\n## Authentication options\n\n### Current example\n\nThe current example uses a Service Bus connection string in the production settings because it is the fastest way to get a first working demo.\n\n### Better next step\n\nA better production-ready direction is to avoid exposing the full connection string directly in the production.\n\nTwo common options are:\n\n1. IRIS credentials + reconstructed SAS connection string\n2. passwordless auth with `DefaultAzureCredential`\n\nFor the passwordless service principal option, see:\n\n- [docs/service-principal-passwordless.md](/Users/afuentes/Documents/ISC/workspace/iris-azure-interop/docs/service-principal-passwordless.md:1)\n\n* * *\n\n## Useful links\n\n- Azure Service Bus Python quickstart:\n  https://learn.microsoft.com/en-us/azure/service-bus-messaging/service-bus-python-how-to-use-queues\n- Embedded Python in IRIS interoperability productions:\n  https://docs.intersystems.com/irislatest/csp/docbook/DocBook.UI.Page.cls?KEY=GEPYTHON_productions\n- Run Python from IRIS:\n  https://docs.intersystems.com/irislatest/csp/docbook/DocBook.UI.Page.cls?KEY=GEPYTHON_runpython\n\n* * *\n\n## Notes\n\n- This repo is meant to be read and explored, not only executed\n- the classes intentionally stay small so the integration pattern is easy to follow\n- once the simple version is understood, the same approach can be extended to:\n  - credentials objects\n  - passwordless auth\n  - dead-letter handling\n  - richer payload validation\n  - routing to real IRIS targets instead of a dummy passthrough operation\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fintersystems-ib%2Firis-azure-servicebus-interop","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fintersystems-ib%2Firis-azure-servicebus-interop","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fintersystems-ib%2Firis-azure-servicebus-interop/lists"}