> ## Documentation Index
> Fetch the complete documentation index at: https://docs.activeviam.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Migration guide

This guide explains the changes required to migrate to the stated version
of the Atoti Limits.

## Migrate to 4.1.1

Upgrading from version *4.1.0*, see
the [Atoti Limits 4.1.1 Release Notes](./release-notes-4.1).

Atoti Limits is using Atoti Server 6.1.3 and Atoti UI \~5.2.6.

For new features and fixes included in these releases, please see
the [Atoti UI documentation](https://docs.activeviam.com/products/atoti/ui/5.2/)
and [Atoti UI Migration Notes](https://docs.activeviam.com/products/atoti/ui/5.2/docs/changelog), and
the [release notes for Atoti Server](https://docs.activeviam.com/products/atoti/server/6.1.3/docs/release/changelog/index.).

### Summary

* **Limit warnings:** Intrepretation of the [warning threshold](#warning-threshold) limit has been updated.

#### Warning threshold

In version 4.1.0, the interpretation of the warning threshold was updated. The new behavior, along with the
Atoti Limits and Atoti UI documentation, clarifies that the threshold is a direct percentage of the limit’s utilization.
If you updated a limit’s warning threshold or defined new warning thresholds using Atoti Limits in version
4.1.0, you may need to update your warning thresholds to ensure they are still aligned with your expectations.

##### Example

The following illustrates the updated behavior. Consider a limit with these
settings:

* **Rule**: GREATER\_THAN
* **Warning**: True (80%)
* **Absolute Value**: False
* **Limit Value**: 1000

The UI wording and warning range have changed as summarized in the following table:

<table><thead><tr><th /><th>Previous behavior<br />(4.0.1-4.0.3 and 4.1.0)</th><th>New (and original) behavior<br />(pre 4.1.0 and 4.1.1+)</th></tr></thead><tbody><tr><td><strong>UI Wording</strong></td><td>“Warn when within % of limit value”</td><td>“Warn when utilization reaches % of a limit”</td></tr><tr><td><strong>Limit will warn in the range</strong></td><td>\[200, 1000]</td><td>\[800, 1000]</td></tr></tbody></table>

## Migrate to 4.1.0

Upgrading from version *4.0.3*, see
the [Atoti Limits 4.1.0 Release Notes](./release-notes-4.1).

Atoti Limits is using Atoti Server 6.1.3 and Atoti UI \~5.2.6.

For new features and fixes included in these releases, please see
the [Atoti UI documentation](https://docs.activeviam.com/products/atoti/ui/5.2/)
and [Atoti UI Migration Notes](https://docs.activeviam.com/products/atoti/ui/5.2/docs/changelog), and
the [release notes for Atoti Server](https://docs.activeviam.com/products/atoti/server/6.1.3/docs/release/changelog/index.).

### Summary

* **Authentication**: JWT is now the default authentication for machine-to-machine communication. Basic authentication has been removed.
* **Removal**: `limits-activeviam` and `/limits/rest/v2/limitDefinition/limitsDefinitionStoreQuery` have been removed.
* **Interface changes**: Several interfaces have been updated or removed (`IAuthenticatedLimitUserService`, `IEvaluationService`, `IValidationError`), custom implementations may need updates.
* **“Save” operation changes**: Atoti Limits now strictly enforces create vs. update logic based on the presence and existence of IDs.
* **Temporary limits**: `sourceLimitId` is now validated. Temporary limits are grouped under their official source limits in API responses.
* **Security filtering**: `@PostFilter` and `@PostAuthorize` are now applied in `ILimitsRetrievalService` to enforce user-based result filtering.
* **Auto-configuration**: Now uses `@ConditionalOnMissingBean` to simplify custom bean injection and avoid needing `@Primary`.

### Breaking changes

* **Endpoint removal**: Removed the `/limits/rest/v2/limitDefinition/limitsDefinitionStoreQuery` endpoint used when evaluating in favor of using the `ILimitCacheService`.
* **Module removal**: The `limits-activeviam` module has been removed from the released source files.
* **Authentication changes**: JWT is now the default machine-to-machine (MtM) authentication. This will require property changes in your Atoti Server and Atoti Limits.
* **`IAuthenticatedLimitUserService` changes**: With the removal of Basic authentication, some methods in `IAuthenticatedLimitUserService` are no longer required and have been removed.
* **Evaluation service change**: There is a new method in `IEvaluationService`, which you will need to implement if you have a custom implementation of this interface.
* **Validation error changes**: The `IValidationError` interface has been modified. If you have any custom validation errors you will need to update them accordingly.

### Module removal

The `limits-activeviam` module has been removed from the released source
files. This is to enforce best practices that will ultimately improve the developer experience. Providing a clean separation between source code and custom code makes migrations easier.

<Note>
  The source code and javadoc of `limits-activeviam` is still available for download from the
  [ActiveViam internal Maven repository](https://activeviam.jfrog.io/activeviam/mvn-internal/). We have only excluded it from the [reference starter project](../../../dev/getting-started#installing-the-starter-project)
  that we distribute with our releases.
</Note>

We don’t recommend that you modify the source code of `limits-activeviam`. Instead, use Spring
injection to add to or modify the default behavior of the core code. You can find examples of this in the [Extending the module](../../../dev/dev-extensions)
section of our documentation.

If you have modified the source code of `limits-activeviam`, you need to extract your changes
into the `limits-starter` module and use Spring to inject the changes. If you can’t use Spring injection, please raise a Jira ticket in order for us to provide the appropriate hooks.

In the meantime, you can override the `limits-activeviam` code in `limits-starter` by adding your code with the same class and package name as in
`limits-activeviam`.

#### JWT is now the default machine-to-machine (MtM) authentication

Atoti Limits now uses JWT authentication for machine-to-machine communication.
This is the default authentication method for Atoti Limits and your Atoti Server.
Therefore, you need to set the `limits.autoconfiguration.service-principal` property on both the Atoti Limits and your Atoti Server to communicate between servers. This `service-principal` user
should have sufficient rights to perform all limit related operations.

You should remove the following unused properties in your Atoti Server:

* `limits.autoconfiguration.authentication`
* `limits.autoconfiguration.content-server.authentication`
* `limits.autoconfiguration.limits-authentication`

##### `IAuthenticatedLimitUserService` changes

The following methods were required to support Basic authentication which has been removed in favor
of JWT authentication.
They have been removed from `IAuthenticatedLimitUserService`:

* `runWithAuthentication`
* `decodeBase64EncodedAuthentication`

If you have a custom implementation of `IAuthenticatedLimitUserService` that overrides the default
interface implementation of these methods, you can safely remove them from your code.

##### Functional Interface changes

The beans used for [MtM authentication](../../../dev/dev-extensions/custom-mtm-authentication) have
been updated to return only builders and have been renamed. These changes provide more consistency
and better flexibility. If you have customized the MtM authentication, you will need to update
your code accordingly.

The following interfaces have been updated:

<table><thead><tr><th>Old Interface Name</th><th>New Interface Name</th><th>Applicable Server</th><th>Old method signature</th><th>New method signature</th></tr></thead><tbody><tr><td><code>ILimitsRestTemplateProvider</code></td><td><code>ILimitsRestTemplateBuilder</code></td><td>Connected servers on Atoti Server version 6.0.x</td><td><code>RestTemplate getLimitsRestTemplate()</code></td><td><code>RestTemplateBuilder getRestTemplateBuilder()</code></td></tr><tr><td><code>ILimitsRestClientProvider</code></td><td><code>ILimitsRestClientBuilder</code></td><td>Connected servers on Atoti Server version 6.0.x-sb3 or 6.1.x</td><td><code>RestClient getLimitsRestClient()</code></td><td><code>RestClient.Builder getRestClientBuilder()</code></td></tr><tr><td><code>ILimitsRestClientBuilderProvider</code></td><td><code>ILimitsRestClientBuilder</code></td><td>Atoti Limits</td><td><code>RestClient.Builder getLimitsRestClientBuilder()</code></td><td><code>RestClient.Builder getRestClientBuilder()</code></td></tr></tbody></table>

#### Additional Method in `IEvaluationService`

An overloaded version of the `evaluateLimits` method has been added to the `IEvaluationService`
interface that allows you to control whether a notification is sent when the evaluation is complete:

```java theme={"languages":{"custom":["/engine/python-sdk/0.9/languages/pycon.tmLanguage.json"]}}
Collection<Incident> evaluateLimits(Collection<LimitEvaluationTask> limitEvaluationTasks, boolean sendNotification);
```

If you have a custom implementation of `IEvaluationService`, you will need to add this method to
your implementation.

#### Validation error changes

The structure of validation errors has been streamlined to improve readability and usability. These
changes impact the error objects themselves, as well as the error handlers. If you have custom validation
errors or error handlers in your project, you’ll need to migrate them accordingly.

##### `IValidationError` changes

* new method added: `String getFieldName()` - returns the name of the field containing the error.
* method `getLineNumber()` was renamed to `getIndex()`.
* method `getColumnIndex()` was removed (replaced by `getFieldName()`).
* method `getSource()` was removed.

##### `IValidationErrorHandler` changes

* The `handleValidationFailure` and `handleValidationError` methods no longer take a `source`
  argument, since the source isn’t stored on the validation error.

### Input file formats

No changes.

### Configuration

#### Configuration properties

##### Properties added

###### [limits-activeviam module](../../../user-ref/properties/config-properties/limits-activeviam)

<table><thead><tr><th>Property Name</th><th>Comment</th></tr></thead><tbody><tr><td>limits.autoconfiguration.use-jwt-machine-to-machine-auth</td><td>JWT authentication is now the default machine-to-machine authentication. Basic authentication was removed.</td></tr><tr><td>limits.autoconfiguration.limits-authentication</td><td>This property was used for basic machine-to-machine authentication to connect with Atoti Limits.</td></tr><tr><td>limits.autoconfiguration.authentication</td><td>This property was used for basic machine-to-machine authentication to connect with the connected Atoti Server.</td></tr><tr><td>limits.autoconfiguration.content-server.authentication</td><td>This property was used for basic machine-to-machine authentication to connect with the connected Atoti Server’s Content server.</td></tr></tbody></table>

#### Configuration files

##### Files Modified

###### [application.yml](../../../user-ref/properties/property-files/application-yml)

New properties:

<table><thead><tr><th>Property Name</th><th>Comment</th><th>Value</th></tr></thead><tbody><tr><td>activeviam.apps.inter-server-event-service.issuer.target-servers\[0].name</td><td>The name of the server to send events to (ConnectedAcc).</td><td>ConnectedAcc</td></tr><tr><td>activeviam.apps.inter-server-event-service.issuer.target-servers\[0].url</td><td>The URL of the server to send events to (ConnectedAcc).</td><td>[http://localhost:7070](http://localhost:7070)</td></tr><tr><td>activeviam.apps.inter-server-event-service.issuer.target-servers\[1].name</td><td>The name of the server to send events to (FRTB).</td><td>FRTB</td></tr><tr><td>activeviam.apps.inter-server-event-service.issuer.target-servers\[1].url</td><td>The URL of the server to send events to (FRTB).</td><td>[http://localhost:8080/frtb-starter](http://localhost:8080/frtb-starter)</td></tr><tr><td>spring.application.name</td><td>Spring property for the application name. Used by the notification service to identify the source server for each notification.</td><td>Atoti Limits</td></tr><tr><td>limits.autoconfiguration.service-principal</td><td>The name of the user authenticated to perform machine-to-machine requests from Atoti Limits to the connected Atoti Servers.</td><td>admin</td></tr></tbody></table>

### Datastores

No changes.

### Databases

No changes.

### Cube schema

No changes.

### Measures

No changes.

### Context values

No changes.

### Other changes

#### `@PostFilter` and `@PostAuthorize` in `ILimitsRetrievalService`

The methods of `ILimitsRetrievalService` have been updated to use the Spring `@PostFilter` and `@PostAuthorize`
annotations to filter the results based on the user’s roles. This change is applied at the interface level for all
methods, so all implementations of this interface will be affected. For custom internal calls that should not filter the
results, you can use the methods that accept a `LimitsQueryPayload` argument and set `checkUserPermissions` to `false`.
Please keep in mind that any user-facing invocations of these methods should always have `checkUserPermissions` set to
`true` to ensure users only see the limits they are authorized to access.

The `@PostFilter` annotation applies to methods that return java `Collection`s. The `@PostAuthorize`
annotation applies to methods that return a single object.

#### Behavior change for “save” methods/endpoints

The default behavior of the “save” methods and endpoints in Atoti Limits has changed. Previously, “save”
operations attempted to update the existing object if the incoming object had the same ID as an existing object.
Otherwise it was treated as creation. If the incoming object did not have an ID or had an ID that did not match
an existing object, a new object was created.

Now, the “save” methods and endpoints follow these rules:

* “save” a single object:
  * If the incoming object does not have an ID, it will be treated as a create operation that will fail if an
    object with that ID already exists.
  * If the incoming object has an ID, it will be treated as an update operation that will fail if no object with that
    ID exists.
* “save” a collection of objects:
  * If any of the incoming objects are missing an ID, all objects are treated as create operations that will fail if
    any contain an ID that already exists.
  * If all incoming objects have an ID, all are treated as update operations that will fail if any of the IDs do not
    exist.

The following methods and endpoints are affected by this change:

* `DefaultLimitsAppCrudService.java`:
  * `saveLimitStructure`
  * `saveLimitStructures`
  * `saveLimit`
  * `saveLimits`
  * `saveIncident`
  * `saveIncidents`
* `LimitsDefinitionCrudRestService.java`:
  * `/structure/save`
  * `/structures/save`
  * `/limit/save`
  * `/limits/save`

<Note>
  These changes do not impact the “create” or “update” specific methods or endpoints. If you previously
  used the “save” methods or endpoints to create objects with pre-defined IDs, you will need to update your code to use
  the “create” methods or endpoints instead.
</Note>

#### `ROLE_USER` no longer required in Atoti Limits

`ROLE_USER` is no longer a required role for all users in Atoti Limits. Previously, this role was required because it was hardcoded as the `owner`/`reader` of KPIs created by Atoti Limits.
Now, the role set as the `owner`/`reader` of KPIs created by Atoti Limits is auto-configured, or can be overridden using the `limits.autoconfiguration.content-server.limits-created-measures-owners` property.
Users will need to have this auto-configured (or overridden) role, or a [data access role](../../../dev/roles/data-access-permissions), to view KPIs created by Atoti Limits, including the calculated members related to the KPIS.

If users have trouble accessing KPIs and calculated measures after upgrading to this version, you may need to manually
delete them from the content server so Atoti Limits can recreate them with the correct owner/reader role(s).

#### Temporary limits changes

The following changes have been made involving temporary limits:

##### 1. `sourceLimitId` field is now validated for temporary limits

The `sourceLimitId` field links a temporary limit to its source limit. This field is now validated to ensure that the
source limit exists and is an official limit. Please ensure that the `sourceLimitId` field is correctly set when
creating temporary limits.

<Warning>
  Prior to this change, creating temporary limits with another temporary limit as the source limit was blocked via the UI,
  but wasn’t validated by the server so it was possible to create such limits via the REST API. This was an unintended
  behavior which we don’t expect clients to do, and is now blocked.
</Warning>

##### 2. Temporary limits are now grouped under official limits

Limits retrieved via REST now have temporary limits grouped under the official limit indicated in the temporary
limit’s `sourceLimitId` field. If you are using the Atoti Limits REST API to retrieve limits, please note that you may need
to update your code to account for this change. Temporary limits are stored in the `temporaryLimits` field of the
corresponding official limit.

#### Auto-configuration changes

We have updated some of our `@Autoconfiguration` classes to not explicitly `@Import` Spring beans
and to instead use the `@ConditionalOnMissingBean` annotation to check for the presence of the beans.
This makes it easier for users to inject beans into Atoti Limits and prevents the need to
mark a bean as `@Primary` when multiple beans are present.

The following `@AutoConfiguration` classes have had explicit imports removed:

* `LimitsCoreAutoconfiguration`
* `LimitsEvaluationServicesAutoConfiguration`

The following beans are now `@ConditionalOnMissingBean`:

* `DefaultUtilizationMeasureCalculator` which implements `IUtilizationCalculator`
* `LimitsCopperMeasureBuilder` which implements `ILimitsCopperMeasureBuilder`
* `DefaultEvaluationService` which implements `IEvaluationService`

If you have any custom implementations of these interfaces then you can remove the `@Primary`
annotation.
