Full Changelog
Release: v1.0.1
Sprint: v6.5.2
Features
-
STUN-aware active connection determination
DEV-1165: FTGetCPEActiveConnection now picks UDPConnectionRequestAddress only when it is global or when STUNEnable!=0 and STUNServerAddress is set; otherwise falls back to ConnectionRequestURL. Both local => UDP. Implementation lives in api-common 0.0.5.
Bug Fixes
-
resolve ORA-01882 on Oracle datasource startup
The Oracle thin driver sent the JVM time zone region name on logon (e.g. Europe/Kyiv), which older Oracle tz libraries do not recognise, failing the schema initializer with ORA-01882. Set oracle.jdbc.timezoneAsRegion=false so the driver sends a numeric offset derived from the container TZ instead, keeping the session time zone aligned with the configured TZ. Apply it globally via JAVA_OPTS and on both datasources for non-Docker runs. Drop the forced UTC session and hibernate.jdbc.time_zone overrides so the effective time zone follows TZ. refs(DEV-2290)
-
route iotw datasource to dedicated iotw schema
The iotw datasource shared the same connection target as the acs
datasource (MYSQL_JDBC_URL / MYSQL_SCHEMA, defaulting to the ftacs
schema). Group Update condition views are persisted via the
@DataSourceSchema("iotw") repository with no hibernate.default_schema,
so iotw_view was written into ftacs while the Management Portal reads
iotw_view from the dedicated iotw schema. As a result, conditions
created through the Northbound API never appeared in the portal.
Point the iotw datasource at the iotw schema, mirroring ui-backend:
- MySQL: MYSQL_SCHEMA_IOTW (default iotw), optional MYSQL_URL_IOTW override
- Oracle: connect as ORACLE_USER_IOTW (default iotw)
- local: jdbc url targets the iotw schema
The acs datasource keeps targeting the ftacs schema.
-
default per-task ErrorCode to SUCCESS for failed/pending/rejected tasks
The task items returned by the Failed/Pending/Rejected task queries were serialized with a null ErrorCode (and Message), whereas the original FTACSWS returns the success default (100) because TaskApi inherits an errorCode pre-initialized to Result.Success. The source query exposes no per-parameter error code, so success is the only faithful value. Centralize TaskResponse construction in a single helper that defaults ErrorCode to 100 and Message to "", covering the REST endpoints, the FTGetCPE*Tasks SOAP methods (TaskWSDL) and USP, which all delegate here.
-
coerce null domain id to 0 for super-admin in getUserResponse
DEV-2218: POST /api/Device/Info returned 500 with an unboxing NPE when the admin (super-admin) user had no domain — UserResponse.getDomainId() was null and unboxed in DeviceQuerySupport.isIspAccessible. Reproduce the C# Session reference, where a NULL domain/location column is read as LocationId=0, by coercing null to 0 in the getUserResponse row mapper. This guards every getUserResponse caller at the source instead of patching each call site individually.
-
CreateGroupUpdateCondition NPE и Hibernate 7.x совместимость
GroupUpdateApiService.createCondition: добавлена нормализация columnKey "lastConnection" → "updated" перед сохранением view и построением Specification. UI-alias "lastConnection" не имел маппинга в FieldPath, PARAMETER_NAMES_SEARCH или CUSTOM_DEVICE_PARAMS, что приводило к NPE в DeviceViewUtil.getPredicateFromCondition. Логика повторяет changeLastConnectionToUpdatedIfNeeded из oneiot_web_backend. QueryUtil.translateToSqlAndCollectParams: совместимость с Hibernate 7.x. - session.createQuery(criteria) → session.createSelectionQuery(criteria): первый возвращает SqmQueryImpl и приводит к ClassCastException. - Query.unwrap(SqmSelectionQueryImpl.class) → direct cast: unwrap к internal-классам в 7.x бросает "Unrecognized unwrap type". - (SqlAstCreationContext) sfi → sfi.getSqlTranslationEngine(): SessionFactoryImpl больше не реализует SqlAstCreationContext, его наследник SqlTranslationEngine получают через getSqlTranslationEngine().
-
restore dynamic TaskName for failed/rejected tasks
Revert hardcoded "SetParameterValues-Device" introduced in 0240219; read CPE_FAILED_TASK.TASK_NAME / CPE_REJECTED_TASK.TASK_NAME from DB and clean it via clearParamName(), matching the pending tasks flow. Also covers SOAP FTGetCPEFailedTasks / FTGetCPERejectedTasks since they delegate to the same TaskService.
-
drop local CLOB workaround, use api-orm 0.0.67
-
return empty list when no pending tasks match filters
Updated `retrievePendingTasks` behavior to return an empty list instead of throwing exceptions when no pending tasks match filters. This change aligns the pending tasks endpoint behavior with failed and rejected task endpoints. Refs DEV-1931
Documentation
-
update antora version to 1.0.1
-
DEV-2252 add request/response examples for Group Update methods
Added request and response examples for all 11 Group Update REST methods
in Swagger, aligned with CustomRpcController style: @ApiResponses with
200/500 codes, schema implementation, success and failure examples with
descriptions.
Fixed inaccuracies in pre-existing examples:
- success Message set to its actual empty value (""), not
"string"/"Operation was performed successfully";
- response field "Status" replaced with the actual "ErrorCode";
- failure examples use the real code 204 and texts from the error
registry (UPDATE_GROUP_NOT_FOUND, PARAMETER_NOT_UNIQUE,
DEVICE_PROFILE_NOT_FOUND).
-
expand changelog index with release format guide
-
document Group Update endpoints in Swagger and Antora
Group Update endpoints in GroupUpdateApiController carried only @Operation summaries, so Swagger UI rendered no per-method description below the operation header. They were also absent from the Antora docs portal, while other controllers (e.g. TaskController) already follow a Behavior / Request fields / Response fields layout. Add description blocks to all 11 @Operation annotations (CreateGroupUpdate, DeleteGroupUpdate, CreateGroupUpdateCondition, DeleteGroupUpdateCondition, ViewGroupUpdateList, ViewGroupConditionList, ViewGroupUpdateDetails, ViewGroupUpdateConditionDetails, GroupUpdateActivate, GroupUpdatePause, GroupUpdateStop) so springdoc-openapi exposes the same behavior/field layout used elsewhere. Add a dedicated Antora page docs/src/modules/ROOT/pages/group-update.adoc covering the campaign lifecycle, per-endpoint request/response fields, behavior, errors and JSON examples; wire it into nav.adoc and convert the Group Update Endpoints table in api.adoc into cross-references with real HTTP paths. refs(DEV-2145)
-
update antora version to 1.0.1 (dev)
Refactoring
-
move
deviceTemplatesPathfromFTApiConfigtoFtAcsApiClientconstructor
- Removed `deviceTemplatesPath` from `FTApiConfig` and injected it directly into `FtAcsApiClient` via constructor. - Updated tests and usage references accordingly.
Performance
-
build jar in job and pack via Dockerfile.simple
Gradle was building inside docker build, so dependencies were re-fetched on every run: type=gha caches only Docker layers, not the BuildKit cache mount holding the Gradle cache, which did not survive builder recreation on the self-hosted runner. Combined with a double Gradle run and a 210MB build context (build/ and .gradle/ not ignored), this hit the 20-minute timeout. Build the boot jar in a job step with actions/setup-java and gradle/actions/setup-gradle for a reliable native ~/.gradle cache, then let Dockerfile.simple only COPY the jar. Drop the now-unused build secrets and pass GitHub Packages credentials via env. Trim the build context by ignoring build/ (keeping the boot jar) and .gradle/. Also pass workflow inputs through env in the tag-prep step to avoid shell injection.