Skip to main content

Configuration properties

The tSM system is built on top of Spring Boot, which allows it to leverage Spring’s powerful externalized configuration capabilities. In tSM, configuration is primarily managed through the application.yml file, which defines common properties that apply to all microservices. These configurations can be easily customized for different environments such as development, testing, and production.

tSM also supports optional usage of Spring Cloud Config to centralize configuration across multiple microservices. This setup ensures consistency and easier management of shared properties like data sources, messaging services (Kafka), and environment-specific settings.

Please consult Spring Externalized Configuration for more info.

Common Configuration for tSM Microservices

In tSM, every microservice shares some common configuration properties, which can be centrally managed. This is especially useful when using Spring Cloud Config, where you can maintain one application.yml for all services. Here’s an example of a minimal common configuration:

# ----------------------------------------------------------------------------
# Common configuration
# ----------------------------------------------------------------------------
tsm:
  prefix: projectX
  datasource:
    host: my.postgres.database:5401
    database: tsm
    username: tsm_admin
    password: myPass
  elastic:
    address: tsm-elastic
    username: elastic
    password: elasticdata
  kafka:
    address: my.kafka.cluster:9092
    autocreate:
      partitions: 2
  elk:
    enabled: true
    logstash:
      url: tsm-log-server:5044
  locale:
    locale: cs-CZ
    timezone: "Europe/Prague"

Explanation of Common Properties:

  • tsm.prefix: A unique identifier for the project, which is used to distinguish between different projects in the same environment. It is used as a prefix for all Kafka topics, elasticsearch indexes, and other project-specific settings.
  • tsm.datasource: Defines the database connection details for tSM microservices.
  • tsm.elastic: Specifies the ElasticSearch configuration for logging and searching within tSM.
  • tsm.kafka: Configures Kafka settings, including the address of the Kafka broker and partition settings.
  • tsm.elk: Controls ELK stack logging, including connection to Logstash.
  • tsm.locale: Sets locale and timezone settings for tSM microservices.

These properties are common across all tSM microservices and ensure consistency in the way services connect to databases, messaging queues, and logging systems.

Deployment Options

When deploying tSM microservices, you have multiple options to manage configurations. The most common approach is using Spring Cloud Config for cloud environments, such as Kubernetes (K8s), where configurations are managed centrally and shared across all microservices. For on-premise deployments, configurations are typically managed locally via application.yml files.

Cloud Config Deployment

In cloud-based deployments, such as Kubernetes, Spring Cloud Config can be used to manage configuration files centrally. This enables easy scaling and maintenance of configurations across all microservices.

To use Spring Cloud Config, you need to specify the configuration source using the spring.config.import environment variable. This can be done directly in the Kubernetes deployment spec.

Example: Kubernetes Deployment with Spring Cloud Config

spec:
  containers:
    - env:
        - name: spring.config.import
          value: 'configserver:http://tsm-config-server'
      image: 'registry.datalite.cz/tsm/tsm-calendar:2.2'

In this example:

  • spring.config.import points to the Spring Cloud Config server URL, which provides the configurations for the microservice.
  • The tsm-calendar microservice image is pulled from the registry and uses the configurations provided by the config server.

To deploy the Spring Cloud Config server, you need to ensure that it is configured to pull configurations from a Git repository or other storage. Here's an example Kubernetes configuration for deploying the config server:

spec:
  containers:
    - env:
        - name: JAVA_TOOL_OPTIONS
          value: '-Xms150m -Xmx150m'
        - name: spring.cloud.config.server.git.uri
          value: https://gitlab.datalite.cz/tsm/config.git
        - name: spring.cloud.config.server.git.username
          value: user
        - name: spring.cloud.config.server.git.password
          value: pass
        - name: encrypt.key
          value: myPass
      image: 'registry.datalite.cz/tsm/tsm-config-server:2.2'

Make sure you have the Spring Cloud Config Server up and running and pointing to the correct repository where your application.yml files are stored.

On-Premise Deployment

For on-premise deployments, configurations are typically managed locally by placing the application.yml file directly in the classpath of the microservice. No external configuration server is required, and each microservice will load its configuration from the local file system.

Built in Configuration Properties

The following properties are common to all profiles, environments, and customizations.

They are included to all microservices and can be overridden by the environment or profile.

# ------------------------------------------------------------
# Base shared settings (apply to every profile and environment)
# ------------------------------------------------------------

tsm:
  kafka:
    # Global topic prefix injected from an env variable or parent YAML
    prefix: ${tsm.prefix}              # e.g. “prod”, “test”, “local”
    # Dead-letter queue: messages that failed processing are routed here
    dlqTopic: ${tsm.kafka.prefix}-tsm-dlq
    # Default consumer-group name for all listeners in this service
    consumerGroupId: ${tsm.name}
    # List of common topics
    topics:
      # Cache-invalidation events across micro-services
      tsmCacheMaintanance: ${tsm.kafka.prefix}-tsm-cache-maintanance

  elastic:
    index:
      # Index name prefix in Elasticsearch
      prefix: ${tsm.prefix}
    storedScript:
      autoUpdate:
        # Auto-upload stored scripts to Elasticsearch on startup
        enabled: true

# ------------------------------------------------------------
# Embedded server (Spring Boot)
# ------------------------------------------------------------
server:
  port: ${tsm.port}                    # Listening port
  max-http-request-header-size: 64KB   # Max size of HTTP request headers

# ------------------------------------------------------------
# Spring Boot – global configuration
# ------------------------------------------------------------
spring:
  application:
    name: ${tsm.name}                  # Service name (logs, Actuator /info, etc.)

  # ---------- Kafka ----------
  kafka:
    bootstrap-servers: ${tsm.kafka.address}  # Comma-separated broker list
    consumer:
      group-id: ${tsm.kafka.consumerGroupId} # Default group-id
      auto-offset-reset: earliest            # No offset? Start from beginning
      # ErrorHandlingDeserializer catches (de)serialization errors
      key-deserializer:   org.springframework.kafka.support.serializer.ErrorHandlingDeserializer
      value-deserializer: org.springframework.kafka.support.serializer.ErrorHandlingDeserializer
      properties:
        spring.deserializer.key.delegate.class:   org.apache.kafka.common.serialization.StringDeserializer
        spring.deserializer.value.delegate.class: org.apache.kafka.common.serialization.StringDeserializer
        max.poll.interval.ms: 3600000            # Long-running message processing
        max.poll.records: 20                     # Messages fetched per poll
    producer:
      key-serializer:   org.apache.kafka.common.serialization.StringSerializer
      value-serializer: org.apache.kafka.common.serialization.StringSerializer

  # ---------- Data source ----------
  datasource:
    # JDBC URL built from env variables (host, database, schema, extra params)
    url: jdbc:postgresql://${tsm.datasource.host}/${tsm.datasource.database:tsm}?currentSchema=${tsm.datasource.schema}${tsm.datasource.params:}
    username: ${tsm.datasource.username}
    password: ${tsm.datasource.password}
    hikari:
      maximum-pool-size: 30            # Max connections in the pool
      minimum-idle: 2                  # Minimum idle connections

  # ---------- JPA / Hibernate ----------
  jpa:
    properties:
      hibernate:
        # JSON (B) mapper for Kotlin + Jackson → PostgreSQL jsonb type
        type.json_format_mapper: cz.datalite.tsm.db.KotlinJacksonFormatMapper
        jdbc:
          lob.non_contextual_creation: true   # Fix for large-object creation
          batch_size: 100                     # Batch size for bulk ops
    hibernate:
      ddl-auto: none                          # Flyway manages the schema
    open-in-view: true                        # Keep session open for lazy-load

  # ---------- Jackson ----------
  jackson:
    mapper:
      DEFAULT_VIEW_INCLUSION: true            # Fields without @JsonView are always included

  # ---------- FreeMarker ----------
  freemarker:
    template-loader-path: classpath:/templates
    suffix: .ftl

  # ---------- Flyway ----------
  flyway:
    default-schema: ${tsm.datasource.schema}
    schemas: ${tsm.datasource.schema}
    locations: classpath:db/release-*/**/{vendor}   # Multiple version folders
    group: true                          # Group migrations with the same version
    placeholder-prefix: $$FLYWAY$${      # Placeholder syntax in SQL scripts
    validate-migration-naming: true
    baseline-on-migrate: true
    baseline-version: 10.01.0.001        # Initial baseline if DB is empty
    baseline-description: TSM Init
    out-of-order: true                   # Allow hot-fix versions out of sequence

  # ---------- Redis / Redisson ----------
  redis:
    redisson:
      file: classpath:redisson.yaml        # Deployment-provided Redisson config

  # ---------- Auto-configuration exclusions ----------
  autoconfigure:
    exclude:
      - org.springframework.boot.autoconfigure.data.elasticsearch.ReactiveElasticsearchRepositoriesAutoConfiguration
      - org.springframework.boot.autoconfigure.elasticsearch.ReactiveElasticsearchClientAutoConfiguration
      - org.springframework.boot.autoconfigure.security.servlet.UserDetailsServiceAutoConfiguration

  # ---------- Spring Cloud ----------
  cloud:
    openfeign:
      httpclient.enabled: true          # Use Apache HttpClient (supports PATCH)
      lazy-attributes-resolution: true  # Delay Feign bean initialization
      cache.enabled: false              # Work-around for occasional startup loop
      client:
        config:                         # Global timeouts for all Feign clients
          default:
            exception-propagation-policy: UNWRAP
            logger-level: FULL
            connectTimeout: 30000       # 30 s
            readTimeout: 30000          # 30 s
    discovery:
      reactive.enabled: false           # Force blocking discovery client

# ------------------------------------------------------------
# Feign (outside Spring Cloud) – enable Apache HttpClient
# ------------------------------------------------------------
feign:
  httpclient.enabled: true

# ------------------------------------------------------------
# JaVers – auditing library
# ------------------------------------------------------------
javers:
  auditable-aspect-enabled: false
  packages-to-scan: cz.datalite.tsm
  sqlSchemaManagementEnabled: false

# ------------------------------------------------------------
# Camunda (workflow engine) – defaults
# ------------------------------------------------------------
camunda:
  bpm:
    database:
      schema-update: false             # Enable only if admin grants are in place
    auto-deployment-enabled: false     # Process definitions are deployed via CI/CD
    application:
      scan-for-process-definitions: false
    defaultNumberOfRetries: 1          # Avoid automatic retries for REST calls
    defaultSerializationFormat: application/json
    tenant-id-provider: cz.datalite.tsm.process.camunda.TsmCamundaTenantIdProvider
    generic-properties:
      properties:
        historyTimeToLive: P365D       # Keep process history for one year
        loggingContextActivityId:      tsm.camunda.activityId
        loggingContextBusinessKey:     tsm.camunda.businessKey
        loggingContextProcessDefinitionId: tsm.camunda.processDefinitionId
        loggingContextProcessInstanceId:   tsm.camunda.processInstanceId
        loggingContextApplicationName:
        loggingContextTenantId:

# ------------------------------------------------------------
# Spring Boot Actuator – endpoints and health checks
# ------------------------------------------------------------
management:
  endpoint:
    health:
      show-details: always             # Show full health details to everyone
      probes.enabled: true             # Enable liveness / readiness view
  endpoints:
    web:
      exposure.include: flyway,loggers,logfile,env,info,health,configprops,metrics,scheduledtasks,threaddump,heapdump,prometheus
  health:
    camunda.enabled: false             # Enable after upgrading to Camunda 7.20.1
    redis.enabled: false               # Turn on only if Redis is actually used

# ------------------------------------------------------------
# Custom bean toggles
# ------------------------------------------------------------
bean:
  RequestLoggerConfiguration.enabled: true   # Log every inbound/outbound HTTP request

tsm-user-management

tsm:
  # HTTP port on which the TSM User-Management service listens
  port: 8088

  # Application name (used in logs, tracing, etc.)
  name: tsm-user-management

  datasource:
    # Database schema that holds TSM tables
    schema: um                         # “um” = user-management schema

  kafka:
    # Kafka consumer group for all listeners in this service
    consumerGroupId: tsm-user-management
    topics:
      # Topic with user-related events (create / update / delete)
      tsmUser: ${tsm.kafka.prefix}-tsm-user
      # Topic with WorkForce Management work-resource updates
      tsmWfmWorkresource: ${tsm.kafka.prefix}-wfm-workresource
      # Topic with calendar events (holidays, shifts, etc.)
      tsmCalendar: ${tsm.kafka.prefix}-tsm-calendar

  planner:
    # When true, send updates about work-resources to the external planner
    update-workresource: true

security:
  ad-config:
    # Toggle LDAP authentication against Active Directory
    ldap-auth-enabled: false           # true → users are authenticated via AD
    # Toggle scheduled sync of users / groups from AD to local DB
    ldap-sync-enabled: false           # true → periodic sync runs
    # LDAP endpoint (protocol + host + port)
    url: ldap://todo.todo:389          # e.g. ldap://ad.company.com:389
    # Kerberos / AD DNS domain; leave blank to infer from base-dn
    domain:                            # e.g. company.com
    # Root DN under which all user / group objects reside
    base-dn: OU=TODO,DC=in,DC=customer,DC=domain
    # Optional narrower subtree to search (overrides base-dn if set)
    search-base:
    # Service account (bind DN or UPN) used to query the directory
    mng-user: Service-account@customer.com
    # Password for the service account — keep this secure!
    mng-password:

  radius:                              # Auth via RADIUS server; roles sync on login
    radius-auth-enabled: false         # true → enable RADIUS authentication
    # One or more RADIUS servers separated by “|”
    server: 127.0.0.1                  # Ensure ports 1812 (auth) & 1813 (acct) are open
    # Shared secret that must match the RADIUS server configuration
    sharedSecret: testing123

  database:
    # Allow classic username/password auth against internal DB
    password-auth-enabled: true        # Set false to disable local fallback

management:
  health:
    ldap:
      # Include LDAP in Actuator /health only if LDAP is used and should affect status
      enabled: false                   # true → app hits LDAP to report health


# common config
spring:
  flyway:
    out-of-order: true
  jmx:
    enabled: false
  banner:
    location: classpath:tsm-banner.txt
  application:
    name: ${tsm.name}

javers:
  sqlSchema: um

# Remove too verbose logging
logging:
  level:
    org.apache.kafka: WARN
    org.springframework.cloud.openfeign.FeignClientFactoryBean: WARN
    org.flywaydb.core.internal.license.VersionPrinter: WARN
    com.zaxxer.hikari.HikariDataSource: WARN