Customization Patterns
tSM is designed to be extended and customized at multiple levels. Depending on the complexity of the requirement, you can choose from five progressively deeper customization strategies — from pure configuration to building entirely new domain services on top of the tSM base microservice.
| Level | Name | Typical Actor | Deployment Impact |
|---|---|---|---|
| ① | Configuration | Configurator / Business Analyst | None — runtime configuration only |
| ② | Integration | Configurator / Developer | None to minimal — external services or workers |
| ③ | UI Customization | Frontend Developer | Frontend build / deploy |
| ④ | Extend | Backend Developer | Replaces a core microservice with a custom build |
| ⑤ | Specialization | Backend Developer / Architect | Adds a new independently deployed microservice |
1 — Configuration
The most common and recommended starting point. tSM core entities (Customer, Ticket, Order, …) are designed to be configured, not modified. No custom code is required.
What you can configure
| Mechanism | Description | Documentation |
|---|---|---|
| EntityTypes | Create domain-specific subtypes of a core entity. For example, define CustomerType: Retail, B2B, Wholesale — each with its own Configuration Profile (characteristics, forms, comments, attachments). | Entities & Characteristics |
| Characteristics | Add dynamic attributes to any entity type using JSON Schema-based forms. E.g., add a Billing Address or SLA Level attribute to a specific Customer type without changing the core data model. | Form Designer |
| Forms | Design entity-specific UI forms (detail screens, create dialogs, etc.) visually in the Form Designer. | Form Designer |
| Scripts (SpEL) | Write tSM Expression Language scripts that react to platform events (CustomerCreated, TicketStateChanged, …), perform validations, compute derived values, or invoke other services. | tSM Expression Language |
| Processes | Model business workflows visually in the Process Engine — define tasks, deadlines, SLA tracking, approvals, and automated steps. | Process Engine |
| Lookup Tables | Define status dictionaries, lifecycle states, transitions, and other enumeration values for each entity type. | Entity Type |
| Listings | Configure data listings with custom filters, columns, sorting, and export. | Listings |
| Output Management | Configure document templates (HTML, PDF, Word) with placeholder-driven generation. | Output Management |
| Notifications | Define notification rules — when to send, which template, which channel (email, SMS, push). | Notifications |
Example: Configuring a new Customer type
To support a new B2B customer segment, a configurator can:
- Create an EntityType
CustomerType: B2B - Define a Configuration Profile with B2B-specific characteristics (e.g., Company Registration Number, Tax ID, Contract SLA)
- Design a Form for the B2B customer detail screen
- Define a Process for B2B customer onboarding with approval steps
- Write a SpEL script that listens to
CustomerCreatedand automatically creates a default Account
All of this happens at runtime through the tSM administration UI — no build, no deployment.
2 — Integration
When you need to connect tSM with external systems or orchestrate more complex logic that goes beyond configuration scripts.
Integration mechanisms
| Mechanism | Description | Direction |
|---|---|---|
| Integration Connectors | Pre-built connectors for common external systems (Jira, Google Chat, MS Teams, network management, public registers, …). See Integration Connectors for the full catalog. | tSM ↔ External |
| Connection Worker | A process activity that calls an external HTTP endpoint (REST/SOAP). Configured within the Process Engine — supports request/response mapping, error handling, and retries. | tSM → External |
| REST / SOAP Script Bindings | Call external HTTP endpoints directly from SpEL scripts using the built-in REST and SOAP client bindings — no process step required. Useful for lightweight, synchronous integrations within event handlers or validation scripts. | tSM → External |
| External Task | A process activity whose execution is handled by an external worker (a standalone service that polls for pending tasks, executes custom logic, and reports completion). Ideal for long-running or complex integrations. | tSM ↔ External |
| Custom Microservice | Build a standalone microservice (in any technology — Java, Python, Node.js, …) that uses the tSM Public API and/or Kafka events to implement custom business logic. This is the most flexible integration option — it can combine multiple mechanisms (REST calls, Kafka consumption, own database) and is deployed and scaled independently from tSM. | Both |
| Kafka Consumer | Deploy a custom service that consumes tSM events from Kafka topics (e.g., customer, order, ticket) and performs external processing. | tSM → External |
| tSM Public API | External systems call tSM's RESTful API to create, read, update, or query tSM entities. Authentication via API keys or OAuth. | External → tSM |
| MCP Bindings | tSM provides Model Context Protocol (MCP) bindings, allowing AI agents and LLM-based tools to interact with tSM services, query data, and execute operations programmatically. | External → tSM |
When to choose which
- Connection Worker — simple request/response calls to external APIs within a process flow
- External Task — the external logic is complex, long-running, or maintained by another team
- Kafka Consumer — event-driven, asynchronous reaction to tSM domain events
- Public API — the external system needs to push data into tSM or query tSM data
- Custom Microservice — the recommended choice when the integration logic is non-trivial, combines multiple data sources, or needs its own persistence. A custom microservice can consume Kafka events, call the tSM Public API, expose its own API, and be built in any technology stack
3 — UI Customization
When the standard tSM UI components do not cover a specific requirement, custom frontend widgets can be integrated into the tSM Portal.
Supported approaches
| Approach | Technology | Description |
|---|---|---|
| Custom Widget | Angular / React / Web Component | A custom component registered in the tSM Form Designer, usable like any native tSM widget. Communicates with the host via tSM Form Runtime. |
| Iframe | Any web technology | Embed any external web application into a tSM screen via iframe. Supports optional two-way communication via postMessage. |
| Menu / Frame | Any web technology | Register an external application as a dedicated menu entry in the tSM Portal (full-page frame). |
Custom widgets can access the tSM context (current entity, user session, JWT token) and interact with tSM APIs. For details, see UI Integration.
4 — Extend a tSM Microservice
When configuration and integration are not sufficient — typically because you need custom business logic that must run inside the same transaction as the core entity operations, you need maximum performance (no extra network hops), or when the equivalent configuration would be too complex and a proper codebase with unit tests, compilation checks, and code review brings more maintainability.
Extending a tSM microservice requires deep knowledge of the tSM internal architecture and Spring framework. Consult your tSM Implementation Team before choosing this approach.
How it works
Instead of deploying the standard core microservice (e.g., tsm-customer), you build a custom variant (e.g., my-customer) that:
- Includes the core tSM module as a library dependency
- Adds custom Spring services, event handlers, and additional logic
- Can override core service implementations where necessary (e.g., replace the default validation logic)
The resulting microservice is deployed in place of the original — same database, same API, same Kafka topics.
What you can do
- Add custom Spring
@Service/@Componentclasses with additional business logic - Register event handlers that react to entity lifecycle events (e.g.,
@EventListener(CustomerCreated.class)) - Override a core service bean to change default behavior (e.g., custom enrichment before save)
- Add new REST endpoints alongside the core API
- Add new database entities and tables with relationships (links) to the core entities
Benefits
- Performance — custom logic runs in-process, no network overhead
- Transactional consistency — custom logic participates in the same database transaction as the core operation
- Full access to core internals (services, repositories, domain events)
Trade-offs
- Requires a custom build and deployment pipeline for the affected microservice
- Upgrading to a new tSM version requires recompilation and regression testing of custom code
- The custom code is tightly coupled to the core module's internal API
When to use
Use Extend when:
- You need custom logic that must execute within the same transaction as core entity operations
- You need the lowest possible latency (no extra HTTP/Kafka round-trips)
- You want to add new entities with links to the base entities (e.g., a custom
Contractentity linked toCustomer) - The equivalent SpEL / process configuration would be too complex to maintain — a proper codebase with unit tests and compilation checks is more appropriate
5 — Specialize a tSM Base Microservice
When you want to reuse an existing tSM business module for a second, parallel domain that must be independently deployed, scaled, and evolved — sharing the same core implementation but running with its own entity types, lookup tables, Kafka topics, and database.
Most projects never require Specialization. The typical scenario where it applies is when you already have a highly tuned and heavily customized module (e.g., Retail Customer handling with complex workflows, performance optimizations, and a large configuration base) and a separate business unit or implementation team now needs support for a fundamentally different domain variant (e.g., Wholesale Customers) with its own specialized requirements, release cadence, and performance profile — and they must not interfere with the core business. If a simple EntityType distinction (e.g., CustomerType: Retail vs. CustomerType: Wholesale) within the same service is sufficient, prefer Configuration instead.
This pattern is intended for business domain microservices (Customer, Order, Ticket, Inventory, …). Infrastructure and platform microservices do not support it. Not all business modules support overriding EntityType names and topic prefixes — consult the tSM Core Team to verify your use case.
How it works
Specialization combines the Extend pattern with dedicated deployment. You create a new microservice (e.g., tsm-wholesale-customer) that includes tsm-customer as a core library — exactly like in the Extend pattern — but instead of replacing the original, you deploy it alongside as a separate service with its own database and Kafka topics.
The separation between the core and specialized instance is largely driven by configuration — entity types, lookup tables, and Kafka topics are prefixed (e.g., wholesale-) to keep the two domains apart. In the simplest case you can deploy the same service image twice under different URLs with different configuration. However, because there is typically a strong business reason for the separation and the specialized domain is expected to diverge over time, we recommend combining this with the Extend pattern and building a dedicated microservice project (e.g., tsm-wholesale-customer) from the start — this gives you a place for custom logic, event handlers, and domain-specific code as the requirements grow.
What the specialized service gets from the core library
- Base entity model (DTOs, JPA entities, mappings)
- CRUD controller / service scaffolding
- Validation, filtering, paging, sorting conventions
- Security helpers, tracing, correlation
- Shared infrastructure abstractions
What the specialized service defines on its own
- New entity types (e.g.,
WholesaleCustomer,WholesaleAccount— separate fromCustomer,Account) - Own lookup tables — status dictionaries, lifecycle states, and other enumerations can evolve independently
- Own Kafka topics — dedicated event streams (e.g.,
wholesale-customer) - Extended DTOs — e.g.,
WholesaleCustomerPublic extends CustomerPublicwith domain-specific fields - Own database — complete data isolation
- Own client library — e.g.,
tsm-wholesale-customer-clienttargeting the new service - Custom logic — additional Spring services, event handlers, and overrides (same as Extend)
Compatible API contract
The base API shape remains compatible — the specialized service exposes the same endpoints and base DTO structure. A WholesaleCustomerPublic is readable as a CustomerPublic (polymorphism). Domain-specific fields are additive.
Benefits
- Complete runtime isolation — separate deployment, scaling, database, Kafka topics
- Independent release cadence — the specialized service evolves without affecting the core module
- Maximum reuse — the core library provides 80–90 % of the implementation, only domain-specific behavior is custom
- Consistent APIs — clients interacting with either service see a compatible contract
Trade-offs
- Operational overhead of managing an additional microservice
- Core library version upgrades require recompilation (same as Extend)
- Requires careful discipline to keep domain-specific logic out of the core library
- Not all tSM modules support this pattern
When to use
Use Specialization when:
- The customer requires strict runtime isolation between variants of the same domain (e.g., Retail Customers vs. Wholesale Customers, Product Orders vs. Service Orders)
- The new domain is expected to diverge significantly in entity types, workflows, and statuses
- You still want maximum code reuse and a consistent API across the variants
tSM UI compatibility
Because the specialized service exposes the same API contract as the core microservice, existing tSM UI widgets (listings, detail screens, form components) are compatible with the specialized variant out of the box.
The only adjustment needed is telling the widget which microservice to target. By default, a widget points to the global service (e.g., tsm-customer). For a specialized variant (e.g., tsm-wholesale-customer), the target can be configured in two ways:
- Widget attribute — set the service base URL or service name directly on the widget instance in the Form Designer (e.g.,
serviceUrl: tsm-wholesale-customer) - Parent context derivation — the widget inherits the target service from the parent form context automatically (e.g., when a Wholesale Customer detail screen is opened, all child widgets resolve to
tsm-wholesale-customer)
This means you do not need to rebuild or fork UI components — the same widget code works for both the core and specialized services.
Choosing the right level
General guidance:
| If you need… | Use |
|---|---|
| Custom entity types, attributes, forms, workflows, status dictionaries | ① Configuration |
| Connections to external systems (HTTP, Kafka, API) | ② Integration |
| Specialized frontend components or embedded external UIs | ③ UI Customization |
| Custom backend logic in the same transaction, or configuration is too complex | ④ Extend |
| A fully separate domain variant with own entities and database | ⑤ Specialization |
Each level builds on the previous ones — an Extended microservice still uses Configuration (entity types, forms, processes) and can still leverage Integration mechanisms (Connection Workers, External Tasks). A Specialized service reuses the same UI widgets as the core module. The levels are not mutually exclusive.
Always start with Configuration — most business requirements can be covered without code. Escalate to higher levels only when the simpler approach is genuinely insufficient.