Full Changelog

Release: v1.0.1

Sprint: v6.5.2

Breaking Changes

Jira References

  • DEV-1165 - Java API > Active connection determination > Change logic

  • DEV-2283 - Java Northbound API > Create condition > Angular project > Management portal > Group Update > Add/Edit > Condition is missing

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)

Chores

  • bump api-common to 0.0.6

refs(DEV-2143, DEV-2148)

Refactoring

  • move deviceTemplatesPath from FTApiConfig to FtAcsApiClient constructor

- 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.

Tests

Build

CI

  • set cache-to to ignore errors in build-callable workflow