#2328: SipgateService.kt

projectforge-rest/src/main/kotlin/org/projectforge/rest/sipgate/SipgateService.kt Service, projectforge-rest/src/main/kotlin/org/projectforge/rest/sipgate/SipgateService.kt 226 lines · 153 code · 56 comments · 17 blank
REST client for Sipgate telephony API: lists users, devices, numbers, addresses, call logs; initiates calls and sends SMS via WebClient.

Architecture

SipgateService is a @Service in the REST layer that wraps the Sipgate REST API. It depends on SipgateClient (which provides OAuth2-authenticated WebClient). The webClient property is lazily initialized on @PostConstruct.

API Coverage

MethodSipgate API EndpointReturns
getLogs()GET /log/webhooksList of SipgateIoLogsResponse (call logs)
getUsers()GET /usersList of SipgateUser
getDevices(user)GET /{userId}/devicesList of SipgateDevice per user
getNumbers()GET /numbersList of SipgateNumber (phone numbers)
getAddresses()GET /addressesList of SipgateAddress
initCall(...)POST /sessions/callsBoolean success (initiates phone call)
sendSms(...)POST /sessions/smsBoolean success (sends SMS)

Pagination Handling

The companion object's getList() generic method handles Sipgate's offset/limit pagination. It loops up to maxNumberOfPages (default 100), making GET requests with offset and limit query parameters until currentOffset > totalCount. Responses are deserialized from JSON using JsonUtils.fromJson into typed list data classes (e.g. UserListData, DeviceListData) that extend ListData<T>.

Call Initiation

initCall(deviceId, caller, callee, callerId) POSTs a NewCallRequest JSON to /sessions/calls expecting HTTP 200. The deviceId is optional (needed only when caller is a phone number, not a device). The callerId parameter sets the displayed phone number for the callee.

SMS Sending

sendSms(smsId, recipient, message) POSTs a SendWebSmsRequest to /sessions/sms expecting HTTP 204 (No Content). The smsId identifies the sending phone number/extension.

Privacy

Both NewCallRequest.toString() and SendWebSmsRequest.toString() redact the callee/recipient phone number using StringHelper.hideStringEnding(), showing only the last 5 characters masked, for log privacy.

Design Rationale

The service lives in the REST module (not business module) because it's purely an external API client — no business logic, no persistence. The generic getList method with typed list data classes avoids code duplication across five endpoints with identical pagination. Error handling is silent (catches exceptions, logs, returns empty lists / false) because Sipgate API failures are non-critical for ProjectForge's core operation. The separation of SipgateClient (authentication/HTTP) from SipgateService (endpoint knowledge) follows single-responsibility principle.

Git History

868d6abb7 2025 -> 2026
600951ee0 2025 -> 2026
63081666f Source file headers: 2024-> 2025.
199c26801 Source file headers: 2024-> 2025.
77bade6df javax.* -> jakarta.*
3afa03fb1 javax.* -> jakarta.*
b6092df09 Copyright 2023 -> 2024
9a0609dd1 Copyright 2023 -> 2024
9cee83a03 WIP: phone calls for Sipgate
5d7cb9d07 WIP: phone calls for Sipgate
97645bd38 WIP Sipgate; Excel export of SipgateConfiguration
86d7f8391 WIP Sipgate; Excel export of SipgateConfiguration
539f41cf3 WIP Sipgate.
6fb0c1828 WIP Sipgate.
876e0b188 WIP Sipgate.
0ece18fb2 WIP Sipgate.
eafdb76c0 WIP Sipgate.
4d1412659 WIP Sipgate.
b4a0462a1 Nothing real.
73ee6a1a4 Nothing real.