Camel Topology¶
The cm-* Camel microservices are the middleware between storefronts, OMS, warehouses, and retailer EDI. This page shows how they wire together.
Layer Convention¶
Every service name ends in one of three suffixes:
| Suffix | Layer | Role |
|---|---|---|
*-exp |
Experience | External-facing REST APIs |
*-prc |
Processing | Async business logic, ASB consumers |
*-sys |
System | Proxy/adapter to an external system (Cirro, NAV, Arena, etc.) |
A typical flow: external caller hits *-exp → work gets queued to *-prc → *-prc calls one or more *-sys services → *-sys talks to the external system.
Topology¶
Three columns = the Experience → Processing → System layers. Box color is the layer; red marks the retiring cm-fulfill-exp. Solid arrows are sync calls; dashed arrows are async / lower-confidence paths. Click to zoom.
This hand-drawn view runs slightly behind the prose
It still shows a cm-nav-sys box, but that service is a retired stub — its NAV order-release job moved into cm-order-prc, and NAV SOAP / page calls now run through cm-int-service-sys. The drawing also predates the shared Config Server / Key Vault / Service Bus infrastructure; for those, the layer sections below are the source of truth.
Experience Layer¶
cm-ext-service-exp¶
External-facing REST (OMS, partners). Forwards fulfillment requests onto cm-fulfill-prc via ASB.
cm-int-service-exp¶
Internal REST for other PopSockets services. Delegates to cm-int-service-sys. New internal endpoints land here.
cm-fulfill-exp¶
Legacy fulfillment REST. Retiring — use cm-int-service-exp or cm-ext-service-exp for new work.
Processing Layer¶
cm-edi-prc¶
EDI 850/940/856/945 processing. Polls SPS/PS SFTP, splits documents, dispatches 940s to Cirro (see the EDI pipeline for the full flow), publishes shipped-b2b events when B2B orders ship.
cm-order-prc¶
Orchestrates order lifecycle, routes fulfillment, publishes shipped events. Calls most of the *-sys services — everything except cm-product-sys, cm-printprod-sys, and cm-sfcc-sys. Also consumes the nav-order-release Service Bus queue directly (NAV → OMS release path) — that work used to live in cm-nav-sys, which no longer exists. Its scheduled poll into cm-jackyun-sys (China order fetch) is built but disabled in prod (cron -).
cm-fulfill-prc¶
Handles fulfillment-request-* queues from OMS (AES-encrypted payloads), decrypts, forwards to Cirro. Walkthrough: Order Export example.
cm-batching-prc¶
Consumes batching-update-topic and fans out to PrintStation (via cm-printprod-sys), OMS, and cm-order-prc.
cm-product-prc¶
Polls Arena for item/ECO events via @Scheduled, fans out to OMS/batching/Jackyun. Exposes POST /jackyun/resync for manual SKU resync.
cm-int-service-prc¶
Likely ADX log ingestion — confidence is low. Verify before touching.
System Layer¶
cm-int-service-sys¶
Owns the PostgreSQL edi_docs + fulfillment_tracking tables (live schema integration_int_service_sys_<env>). Also the only outbound NAV SOAP caller — packing instructions (PackagingInstructions codeunit) and item/BOM sync (qbd* pages). No separate NAV service.
cm-cirro-sys¶
Bearer-token proxy to Cirro. Does not modify payloads.
cm-osor-sys¶
Proxy to OMS (target host is per-env — resolved from the config server, not hardcoded). Handles order sync, NAV order-release acks back to OMS, and Gladly endpoints.
cm-snowflake-sys¶
Writes order data to Snowflake DEV.CIRRO.*.
cm-printprod-sys¶
Consumes batching-update-printstation, forwards to PrintStation.
cm-product-sys¶
Arena PLM API proxy. Shares session tokens across pods via Hazelcast.
cm-jackyun-sys¶
Jackyun/KH China integration. The only live path in prod is product/SKU/BOM sync — HTTP from cm-product-prc → Jackyun (verified running). The China order lane (cm-order-prc polls Jackyun/Qimen → batching → PrintStation → KH 3PL fulfillment) is built but disabled in prod (poll cron -; enabled in dev only). No OMS connection at all.
cm-sfcc-sys¶
Salesforce Commerce Cloud integration. Deployed in nonprod only (dev/qa/stage) — there is no prod deployment. Rarely used.
Infrastructure¶
These aren't cm-* business services, but every service depends on them. They don't appear on the topology map above.
Spring Cloud Config Server (cm-spring-cloud-config)¶
Central configuration for every cm-* service. Runs as exactly two instances:
| Instance | Deployed in | Serves profiles | Backend table | External URL |
|---|---|---|---|---|
| nonprod | int-dev (int-usw-aks-1) |
dev, qa, stage |
spring_cloud_service_nonprod.properties |
camelconfigserver-np.corp.popsockets.com |
| prod | int-prod (int-usw-aks-2) |
prod |
spring_cloud_service_prod.properties |
camelconfigserver.corp.popsockets.com |
- Backend is JDBC, not a Git repo (Spring profiles
jdbc,nonprod/jdbc,prod) — properties live in a Postgres table and are resolved live on every request. - Each service imports its config at startup via
spring.config.import. Most have no@RefreshScope, so a config change needs a consumer pod restart to take effect. The config server itself needs no restart — it re-reads the table each request. - ⚠️ The nonprod Postgres also holds
integration_*.propertiestables. Those are repo-intent mirrors that are not served — onlyspring_cloud_service_*is live. Writing a mirror table changes nothing.
Azure Key Vault¶
Holds every secret the config server hands out — DB passwords, Service Bus connection strings, Cirro/OMS/NAV credentials, AES keys.
| Vault | Env |
|---|---|
popint-cm-kv-1 |
nonprod (dev/qa/stage) |
popint-cm-kv-2 |
prod |
- Only the config server reads Key Vault. Business services never touch it directly — they receive already-resolved values in their served config.
- Properties reference secrets as
${secret-name}placeholders (e.g.${dev-ediprc-sb-connection-edi850-topic}); the config server substitutes the vault value before serving. - The config server caches vault secrets and refreshes every 15 min (
refresh-interval=900000). A rotated secret isn't picked up until that refresh and a consumer restart.
Azure Service Bus¶
The async backbone. *-prc services consume queues/topics; producers publish across service boundaries.
| Namespace | Env |
|---|---|
int-nonprod-psb-1.servicebus.windows.net |
dev/qa/stage |
int-prod-psb-1.servicebus.windows.net |
prod |
- Queue/topic names follow
int-<env>-<name>— e.g.int-dev-edi-850-topic,int-qa-edi-940-db,int-dev-edi-shipped-b2b-topic(topic) +int-dev-edi-shipped-b2b(subscription). - Connection strings are per-queue and live in Key Vault, referenced from config as
${<env>-<app>-sb-connection-...}. - Topic subscriptions filter on an
event_typemessage header. - DLQ max delivery = 1 on most queues — one processing failure dead-letters the message immediately, with no retries.
Experimental / not on the map¶
cm-sku-doandcm-thedeloreanare deployed in dev only and have no module in the camel repo — treat them as experiments, not part of the standard topology.cm-file-transferhas a repo module but is not deployed in any env (an SFTP-utility proof of concept).
Retired services¶
cm-nav-sys— gone. It used to be the NAV order-release worker; that job (consuming thenav-order-releaseService Bus queue) now lives incm-order-prc. Outbound NAV SOAP calls were always incm-int-service-sys, not here. No repo module, no deployment in any env.
Gotchas¶
cm-cirro-sysdoes not transform payloads. It's a thin proxy. Business logic happens incm-order-prc,cm-fulfill-prc, orcm-edi-prcbefore the call.- NAV lives in two places, and neither is
cm-nav-sys. Inbound order-release is consumed directly bycm-order-prc(thenav-order-releaseService Bus queue). Outbound NAV SOAP — packing instructions andqbd*item sync — goes throughcm-int-service-sys.cm-nav-sysis retired (see Retired services). cm-jackyun-sys's only live path is product sync. SKU/BOM upserts come in via HTTP fromcm-product-prc→ Jackyun (running in prod). The order path (jackyun-orders-topicfromcm-order-prc) exists in code but the poll is disabled in prod — don't assume China orders flow through it.cm-fulfill-expis retiring. It's still deployed in every env, but add new fulfillment endpoints tocm-int-service-exporcm-ext-service-expinstead.cm-sfcc-sysis nonprod-only. It runs in dev/qa/stage but has no prod deployment — don't assume it's in the prod path.cm-file-transferisn't deployed. The repo module exists but nothing runs it in any env.cm-int-service-prchas low-confidence data. Rarely touched — verify against the code before relying on anything this page says about it.