# Multi-service deployment
xly is not a single Spring Boot WAR. The repository contains several
deployable modules plus a few library-like WAR modules that are also used
as dependencies by `xlyEntry`.
## Topology at a glance
```mermaid
flowchart LR
classDef library fill:#f5f5f5,stroke:#999,stroke-dasharray:3 3
classDef boot fill:#e8f0fe,stroke:#4285f4
subgraph clients [Operator-facing]
BACK["BACK SPA
http://<host>:8597"]
FROUNT["FROUNT SPA
http://<host>:8598"]
end
EXT([External integrators])
HOOKS([Third-party webhooks])
subgraph boots [Deployable Spring Boot apps]
direction TB
XENTRY["xlyEntry
:8080 /xlyEntry
EntryApplicationBoot"]:::boot
XAPI["xlyApi
:8090 (local) / :8080
/xlyApi · ApiApplicationBoot"]:::boot
XIF["xlyInterface
:8080 /xlyInterface
InterfaceApplicationBoot"]:::boot
XPLC["xlyPlc
:8000 (dev) / :8080
/xlyEntry · PlcApplicationBoot"]:::boot
XFACE["xlyFace
:8091 (local) / :8080
/xlyFace (out of doc scope)"]:::boot
XEJMSC["xlyErpJmsConsumer
(no port; inherits)
JmsConsumerApplicationBoot"]:::boot
end
subgraph libs [Library modules — not standalone runnable]
direction TB
XMANAGE[xlyManage]:::library
XBSERVICE[xlyBusinessService]:::library
XPERSIST[xlyPersist]:::library
XENTITY[xlyEntity]:::library
XFLOW[xlyFlow]:::library
XMSG[xlyMsg]:::library
XEJMSP[xlyErpJmsProductor]:::library
XPLATC[xlyPlatConstant]:::library
end
subgraph infra [Shared infrastructure]
DB[("MySQL
xlyweberp_*")]
REDIS[(Redis :16379
shared cache + session)]
AMQ([ActiveMQ :61616])
MONGO[("MongoDB
(wired but unused)")]
end
BACK -->|nginx| XENTRY
FROUNT -->|nginx| XENTRY
FROUNT -->|nginx| XAPI
EXT --> XAPI
HOOKS --> XIF
XENTRY --- XMANAGE
XENTRY --- XBSERVICE
XENTRY --- XFLOW
XBSERVICE --- XPERSIST
XAPI --- XPERSIST
XIF --- XPERSIST
XPERSIST --- XPLATC
XPERSIST --- XENTITY
XBSERVICE --- XMSG
XIF --- XMSG
XBSERVICE --- XEJMSP
XENTRY --> DB
XAPI --> DB
XIF --> DB
XPLC --> DB
XFLOW --> DB
XENTRY --> REDIS
XAPI --> REDIS
XEJMSC --> AMQ
XEJMSP -. publishes .-> AMQ
XENTRY -. publishes .-> AMQ
```
The reverse-proxy maps the operator-facing ports (8597 / 8598) onto the
internal Spring Boot apps (mostly :8080 with distinct context paths).
The library modules don't run on their own — they're packaged into the
deployable WARs as dependencies. `xlyFlow` and `xlyPlc` share xlyEntry's
context-path `/xlyEntry`, so a real deployment routes by host or
upstream rather than by path.
## The main modules
### Deployable Spring Boot applications
| Service / module | Role | Default profile / port | Boot class |
|---|---|---|---|
| **xlyEntry** | Main runtime and builder/admin surface. Hosts `/business/*`, `/gdsmodule/*`, `/gdsconfigform/*`, `/gdsconfigtb/*`, reporting, login, and other framework controllers. | `dev` → 8080, context `/xlyEntry` | `EntryApplicationBoot` |
| **xlyApi** | API-oriented module for `/api/*`, `/online/*`, `/pro/*`, `/thirdparty/*`, and related endpoints. | `local` (default in repo) → 8090, dev/win/linux → 8080, context `/xlyApi` | `ApiApplicationBoot` |
| **xlyInterface** | External-integration module with Swagger dependencies and third-party integration code. | `dev` → 8080, context `/xlyInterface` | `InterfaceApplicationBoot` |
| **xlyPlc** | Shop-floor PLC bridge ([Slice 6](../../slices/06-hardware.md)). | `dev` → 8000, named profiles (15S, S10, T0, T1, CT, yt, pro) → 8080, context `/xlyEntry` *(shares xlyEntry's context-path)* | `PlcApplicationBoot` |
| **xlyFace** | Face-recognition module. In build (`settings.gradle` keeps it active per user) but **out of documentation scope** for this wiki. | `win` (default in repo) → 8080, local → 8091, context `/xlyFace` | `XlyFaceApplicationBoot` |
| **xlyErpJmsConsumer** | JMS consumer worker. Has a Boot main but no `application*.yml` of its own — runtime config inherits from peer services. | n/a (inherits) | `JmsConsumerApplicationBoot` |
### Library modules (in `settings.gradle`, not standalone runnable)
| Module | Role |
|---|---|
| **xlyManage** | Backend metadata-management services (`Gds*ServiceImpl` family); pulled into xlyEntry. |
| **xlyBusinessService** | Business-logic service tier (`BusinessBaseServiceImpl` and ~100 sibling `*ServiceImpl` classes); pulled into xlyEntry. |
| **xlyFlow** | Workflow / Activiti code. `XlyFlowApplicationBoot.java` is fully commented out on this branch; consumed as a library through xlyEntry. Also shares context-path `/xlyEntry`. |
| **xlyEntity** | Shared entity / DTO classes (~83 Java files, including 22 Mongo `@Document` classes). |
| **xlyPersist** | Persistence helpers (DAOs, MyBatis mapper XMLs, `RequestAddParamUtil`, etc.). |
| **xlyMsg** | Notification helpers (DingTalk, WeChat, email); no Boot main. |
| **xlyErpJmsProductor** | JMS producer code (queue declarations in `P2pQueue.java`); no Boot main. |
| **xlyPlatConstant** | Shared utility constants (`MultiThreadServer`, `TimeContant`) consumed by `xlyPersist`. The single active Plat* module. |
Each has its own `application.yml` + several `application-.yml`
files. The active profile is selected at startup via
`-Dspring.profiles.active=…`.
## Disabled in `settings.gradle`
The cleanup branch comments out 12 `include` lines. Three are non-Plat
modules present on disk:
- `xlyErpTask` — long-running background tasks.
- `xlyRxtx` — native serial-port library. May be re-enabled when xlyPlc
needs direct serial access (some press models use TCP/Ethernet
instead).
- `xlyFile` — older file-management module, superseded by
`xlyPlatFileUpload` (also commented out).
The remaining nine commented-out includes are `xlyTestService`,
`xlyTestController`, and the full `xlyPlat*` family except
`xlyPlatConstant` — i.e. `xlyPlatTask`, `xlyPlatJmsProductor`,
`xlyPlatJmsConsumer`, `xlyPlatReportForm`, `xlyPlatFileUpload`,
`xlyPlatMarketingService`, `xlyPlatUserService`, `xlyPlatSmsService`,
`xlyPlatMerchantController`, `xlyPlatWebsocket`, `xlyPlatPayService`,
`xlyPlatCainiaoWaybillSevice`. (`xlyTestService` / `xlyTestController`
directories are not on disk; only `TestController.java` exists inside
`xlyEntry/.../businessweb/` as a stub.)
A maintainer cleaning up the codebase should consider whether to delete
the on-disk-but-excluded `xlyErpTask` / `xlyRxtx` / `xlyFile`
directories or keep them as historical reference. They take up disk
space but do not affect the build.
## Plat* family
The `xlyPlat*` modules (`xlyPlatMerchantController`, `xlyPlatUserService`,
`xlyPlatPayService`, `xlyPlatMarketingService`, `xlyPlatCainiaoWaybillSevice`,
`xlyPlatSmsService`, `xlyPlatReportForm`, `xlyPlatFileUpload`,
`xlyPlatJmsConsumer`/`Productor`, `xlyPlatTask`, `xlyPlatWebsocket`)
are the **B2B printing-platform layer** and remain out-of-scope for
this wiki. The single exception is `xlyPlatConstant`, which is still
`include`d in `settings.gradle` and consumed as a shared constants
utility by `xlyPersist` (`MultiThreadServer`, `TimeContant`).
## How services find each other
Three communication channels:
1. **Shared database** — every service reads/writes the same MySQL
schema. Most cross-service "communication" is implicit through
shared tables.
2. **Messaging** — both ActiveMQ/JMS and RocketMQ exist in the codebase.
Cache invalidation ([cache invalidation on metadata change](cache-invalidation.md))
uses the ActiveMQ/JMS path.
3. **HTTP REST** — for synchronous calls (e.g., xlyApi calling xlyEntry's
`/business/*` endpoints).
There is no service registry / discovery mechanism beyond the
`application-.yml` files, which hardcode peer URLs per
environment.
## URL routing in deployed environments
The workspace `.env.local` points `BACK` at port `8597` and `FROUNT` at
port `8598` in the live environment. That is enough to identify the two
operator-facing surfaces, but the reverse-proxy and context-path mapping
are deployment details rather than code-backed facts in this repository.
## Profile permutations
Profiles split by service:
- **xlyEntry**: `dev`, `local`, `win`, `linux`, `15s`, `s10`, `saas`,
`bgj` (lowercase). `dev` is the in-repo default.
- **xlyApi**: `local` (default in repo), `dev`, `linux`, `win`.
- **xlyInterface**: `dev` only.
- **xlyFlow**: `dev` (empty file).
- **xlyFace**: `win` (default), `dev`, `linux`, `local`.
- **xlyPlc**: `dev` (default) plus 7 press-model profiles
(`15S`, `S10`, `T0`, `T1`, `CT`, `yt`, `pro` — uppercase / mixed-case,
distinct from xlyEntry's lowercase `15s` / `s10`).
The press-model profiles (`T0`, `T1`, `CT`, `yt`, `pro`, `15S`, `S10`)
are **xlyPlc-specific** — they don't exist for the other services. The
cross-service profiles cover combinations of:
- Operating system (`linux` / `win`)
- Environment (`dev`, `local`, `saas`, `bgj`)
- Customer/edition (`15s`, `s10` for xlyEntry)
A given deployment selects exactly one profile per service. The
mapping from "this customer" → "these profiles" lives in deployment
ops documentation, not the codebase.
## Open: production URL routing
> **Deferred (outside the repository's reach).** The nginx /
> reverse-proxy config that maps the public `:8597` / `:8598` to the
> internal Spring Boot context-paths lives in deployment-ops
> infrastructure, not in this codebase. The wiki has no way to verify
> it against src/db/web; this section is a placeholder waiting for
> the deployment-side config to be linked or vendored.
The exact nginx / reverse-proxy config for `8597` / `8598` is not in this
repository. Add it here only when the deployment-side config is available.