Skip to main content

37 posts tagged with "migration-guide"

View All Tags

REST Expanders 2.3.0

· 4 min read
Frédéric Hannes
Frédéric Hannes
R&D Engineer

RestFacade removal

The RestFacade class which was used previously in the control layer as a bridge between the Connector and Agent classes has been removed. This was an old artifact left from the original REST JAX-RS implementation for the NS application stack. This class was intended to provide some encapsulation, but it did not really encapsulate anything and violated data version transparency.

  • $dataElement.name$RestFacade.create$dataElement.name$(): This method was integrated into the $dataElement.name$Connector.create$dataElement.name$() method.
  • $dataElement.name$RestFacade.modify$dataElement.name$(): This method was integrated into the $dataElement.name$Connector.put$dataElement.name$() method.
  • $dataElement.name$RestFacade.update$dataElement.name$(): This method was integrated into the $dataElement.name$Connector.patch$dataElement.name$() method.
  • $dataElement.name$RestFacade.remove$dataElement.name$(): This method was integrated into the $dataElement.name$Connector.delete$dataElement.name$() method.
  • $dataElement.name$RestFacade.fetch$dataElement.name$(): This method was integrated into the $dataElement.name$Connector.get$dataElement.name$Details() method, where the SearchDetails is now also constructed.
  • $dataElement.name$RestFacade.fetch$dataElement.name$List(): This method was integrated into the $dataElement.name$Connector.get$dataElement.name$DetailsList() method, where the SearchDetails is now also constructed with support for sort parameters.
  • $dataElement.name$RestFacade.applyPagination(): This method was moved to a new class $dataElement.name$Pagination.
  • $dataElement.name$RestFacade.DEFAULT_PAGE: This constant was moved to a new class $dataElement.name$Pagination.
  • $dataElement.name$RestFacade.DEFAULT_PAGE_SIZE: This constant was moved to a new class $dataElement.name$Pagination.
  • $dataElement.name$RestFacade.MAX_PAGE_SIZE: This constant was moved to a new class $dataElement.name$Pagination.
caution

The $dataElement.name$Pagination class may still be revisited in the future to improve its design.

All existing custom methods that were placed in the RestFacade class should be either integrated into their respective callers or be properly encapsulated if required in its own custom class. To provide some backwards compatibility for transitioning, the expansion of the RestFacade class can still be enabled with the transient option jaxrs.transient.generateFacade.enable. All expanded endpoints will no longer use the RestFacade even if this transient option is defined.

caution

The transient option jaxrs.transient.generateFacade.enable was removed in rest-expanders version 3.0.0.

Sorting

Default Order

For some time data returned by the GETlist endpoints was always sorted ascending by database identifier by default if no other sorting was enforced in the DataElement's QuerySearch class. This functionality was removed after the querysearch-expanders split off from the rest-expanders, as for many requests it does not make sense to deteriorate query performance by always enforcing a default order.

Not having this default ordering for the REST apis created an issue with results returned by the query not always being consistently ordered in between multiple calls. As a result, paginated results do not always make sense as resources can will sometimes shift places in the results.

The querysearch-expanders introduced the option useDefaultOrder on the QuerySearch metamodel element, which is implicitly created by the rest-expanders. This option is now always added to that QuerySearch instance as well, so the default ordering by database identifier is always enforced for the REST API. Contrary to the original implementation, the ordering by database identifier is also enforced if other ordering is applied to the query, but it is added as the last order in the chain.

If for some reason it is required to disable this default ordering, this can still be achieved per individual DataElement by setting the default order to false on the queryBuilder in the QuerySearch class:

// anchor:custom-query-before-build:start
queryBuilder.useDefaultOrder(false);
// anchor:custom-query-before-build:end

Sorting parameter

This version of the REST expanders introduces sorting of results returned by the GETlist endpoint through a query parameter sortby. This parameter is now always added to the expanded endpoints. It can however be disabled by adding the option jaxrs.endpoint.getList.sorting.disable to the DataElement or for the entire Component by adding the option jaxrs.endpoint.getList.sorting.disable to the Component.

Miscellaneous

  • All ValidationError constants in the ValidationError class are now marked final. They should always be fixed. Any deviations should be registered as new error codes.
  • The pagination anchors were removed from the applyPagination() method, as pagination parameters can now be set through expansion options.

SQL Expanders 2.0.0

· One min read
Frédéric Hannes
Frédéric Hannes
R&D Engineer

SQL script location

Starting with version 2.0.0, the database setup script is no longer expanded to [APPLICATION_ROOT]/provision_db.sql, not is now available as [APPLICATION_ROOT]/database/000-init-database.sql. This change was made as there is now also the initial data script, which is expanded to [APPLCIATION_ROOT]/database/001-app-init-data.sql.

QuerySearch Expanders 1.11.0

· One min read
Frédéric Hannes
Frédéric Hannes
R&D Engineer

QuerySearchResolver

The QuerySearchResolver class was moved from the data layer to the logic layer. Since this is used most commonly to resolve references to other components, the use of Cruds classes in the data layer will create high coupling between those components, which is not intended.

To transition to the logic layer implementation, the Agent classes should be used when resolving data for elements in other components. In this scenario there is also no need to use dependency injection with EJB, as the agents do not require this.

A transient option querysearch.transient.dataLayerResolver.enable has been supplied to revert the behavior of the expanders for backwards compatibility. But keep in mind that this option will be removed in the future and has only been supplied for short-term compatibility if needed, allowing for planning to upgrade the codebase. This option will once again expand the QuerySearchResolver in the data layer, rather than the logic layer.

REST Expanders 1.15.0

· 4 min read
Frédéric Hannes
Frédéric Hannes
R&D Engineer

CommandExtension linking

In previous versions of the main expanders, the commands were injected into the logic bean as a feature. Since we do not nest features, this made it impossible to implement commands from another expander bundle, such as the rest-expanders. This feature was integrated into the bean expander, allowing other bundles to now implement commands.

To solve this original issue, the rest-expanders injected some code into the custom anchors of the commands in the logic bean. This was never intended to be a permanent solution, but a temporary workaround to address this issue. Version 1.15.0 of the rest-expanders has a minimum dependency of version 4.12.0 of the main expanders, to be able to transition to actual feature injection for this purpose. As the previous code has now ended up in the harvest files of every project, the workaround has been inverted to remove the workaround code that was injected.

An example of the old injected code:

// anchor:custom-command-createEntity:start
// Default implementation generated by the REST expanders
commandResult = executeCreateEntityCommand(commandParameter);
// anchor:custom-command-createEntity:end

The code will be removed automatically if the endpoint still exists in the model and no code (other than whitespace) has been added in between the start anchor and the injected code.

The previous execute methods were added to avoid the code from being altered easily and make the transition more difficult. These have now been removed and the code they contained is now injected as part of the feature.

An example of the new injected feature code, which was previously in the execute method:

// @anchor:command-createEntity:start
commandResult = new CreateEntityCommandExtension().execute(commandParameter);

if (commandResult == null || commandResult.isError()) {
sessionContext.setRollbackOnly();
}
// @anchor:command-createEntity:end

Exposing diagnostics

We are no longer exposing values in Diagnostic object directly through error payloads in the REST API. The reasoning behind this is that we do not want to expose diagnostic information directly to the end-user. As an alternative, all exceptions that are handled by the REST API that contain diagnostics now have their diagnostics output into the logs along with the information that was already logged previously. Given that this pertains to 5xx errors, these are technical errors that should not occur in production and will likely be handled by a developer. Any issues with input of data should already have been handled by the validation system. These errors which return diagnostics are only thrown when something unexpected has occurred. The diagnostics have more value to a developer rather than the end-user and are more easily accessed through the application logs.

A transient option jaxrs.transient.exposeDiagnostics.enable has been supplied to revert the behavior of the expanders for backwards compatibility. But keep in mind that this option will be removed in the future and has only been supplied for short-term compatibility if needed, allowing for planning to upgrade the codebase. The option will once again expose the diagnostics through the API, but they will also appear in the application logs.

caution

The transient option jaxrs.transient.exposeDiagnostics.enable was removed in rest-expanders version 2.9.0.

The following expanders have been affected:

  • CreateFailedExceptionHandlerExpander
    • File: CreateFailedExceptionHandler.java
    • Changes:
      • Import removed: net.democritus.sys.Diagnostic
      • Objects returned by exception.getDiagnostics() no longer added to errorModel in mapException(exception) method
  • DeleteFailedExceptionHandlerExpander
    • File: DeleteFailedExceptionHandler.java
    • Changes:
      • Import removed: net.democritus.sys.Diagnostic
      • Objects returned by exception.getDiagnostics() no longer added to errorModel in mapException(exception) method
  • ModificationFailedExceptionHandlerExpander
    • File: ModificationFailedExceptionHandler.java
    • Changes:
      • Import removed: net.democritus.sys.Diagnostic
      • Objects returned by exception.getDiagnostics() no longer added to errorModel in mapException(exception) method
  • SearchResultExceptionHandlerExpander
    • File: SearchResultExceptionHandler.java
    • Changes:
      • Import removed: net.democritus.sys.Diagnostic
      • Objects returned by exception.getDiagnostics() no longer added to errorModel in mapException(exception) method
  • ServerErrorModelExpander
    • File: ServerErrorInfoModel.java
    • Changes:
      • Import removed: java.util.ArrayList
      • Import removed: java.util.List
      • Field removed: List<String> diagnostics
      • Method removed: List<String> getDiagnostics()
      • Method removed: void setDiagnostics(List<String>)
      • Method removed: void addDiagnostic(String)

Miscellaneous

  • The ValidationException class was moved from the shared layer to the control layer. It was never intended to be used outside the control layer.

REST Expanders 1.13.0

· 3 min read
Frédéric Hannes
Frédéric Hannes
R&D Engineer

Name qualifying

Some names of variables and method arguments were qualified with specific suffixes in order to avoid obvious collisions with DataElement names. This problem occurs because these variable are named with a clear collision risk, because they are named simply after the element or with an existing suffix which risks collision with other variable names. One such example is a DataElement with name Command, which could collide with a frequently used variable name command, as $dataElement.name.firstToLower$ is also used as a variable in the same scope.

A transient option jaxrs.transient.useQualifiedNames.disable has been supplied to revert the behavior of the expanders for backwards compatibility. But keep in mind that this option will be removed in the future and has only been supplied for short-term compatibility if needed, allowing for planning to upgrade the codebase.

caution

The transient option jaxrs.transient.useQualifiedNames.disable was removed in rest-expanders version 2.9.0.

The following expanders have been affected:

  • CreateElementCommandExtensionExpander
    • Local variable in execute(): DataRef $dataElement.name$DataRef $dataElement.name$DataRef
      • Example (Element City): DataRef cityDataRef cityDataRef
      • Affected anchors:
        • @after-create and custom-after-create
  • ModifyElementCommandExtensionExpander
    • Local variable in execute(): DataRef $dataElement.name$DataRef $dataElement.name$DataRef
      • Example (Element City): DataRef cityDataRef cityDataRef
      • Affected anchors:
        • @after-modify and custom-after-modify
  • UpdateElementCommandExtensionExpander
    • Local variable in execute(): SearchResult<> $dataElement.name$ResultSearchResult<> $dataElement.name$SearchResult
      • Example (Element City): SearchResult<> cityResultSearchResult<> citySearchResult
      • Affected anchors:
        • @before-update and custom-before-update
        • @after-update and custom-after-update
    • Local variable in execute(): DataRef $dataElement.name$DataRef $dataElement.name$DataRef
      • Example (Element City): DataRef cityDataRef cityDataRef
      • Affected anchors:
        • @after-update and custom-after-update
  • RemoveElementCommandExtensionExpander
    • Local variable in execute(): SearchResult<> $dataElement.name$ResultSearchResult<> $dataElement.name$SearchResult
      • Example (Element City): SearchResult<> cityResultSearchResult<> citySearchResult
      • Affected anchors:
        • @before-delete and custom-before-delete
        • @after-delete and custom-after-delete
    • Local variable in execute(): DataRef $dataElement.name$DataRef $dataElement.name$DataRef
      • Example (Element City): DataRef cityDataRef cityDataRef
      • Affected anchors:
        • @before-delete and custom-before-delete
        • @after-delete and custom-after-delete
  • ElementOutputListMapper
    • Local variable in toExternal(): $dataElement.name$OutputModel $dataElement.name$$dataElement.name$OutputModel $dataElement.name$OutputModel
      • Example (Element City): CityOutputModel cityCityOutputModel cityOutputModel
      • Affected anchors:
        • @list-mapping and custom-list-mapping
  • CreateDetailsFillerExpander
    • Method argument in fill(): $dataElement.name$Details $dataElement.name$$dataElement.name$Details $dataElement.name$Details
      • Example (Element City): CityDetails cityCityDetails cityDetails
      • Affected anchors:
        • @fill and custom-fill
    • Method argument in fill$field.name$(): $dataElement.name$Details $dataElement.name$$dataElement.name$Details $dataElement.name$Details
      • Example (Element City): CityDetails cityCityDetails cityDetails
      • Affected anchors:
        • @fill-$field.name$ and custom-fill-$field.name$
  • ModifyDetailsFillerExpander
    • Method argument in fill(): $dataElement.name$Details $dataElement.name$$dataElement.name$Details $dataElement.name$Details
      • Example (Element City): CityDetails cityCityDetails cityDetails
      • Affected anchors:
        • @fill and custom-fill
    • Method argument in fill$field.name$(): $dataElement.name$Details $dataElement.name$$dataElement.name$Details $dataElement.name$Details
      • Example (Element City): CityDetails cityCityDetails cityDetails
      • Affected anchors:
        • @fill-$field.name$ and custom-fill-$field.name$
  • UpdateDetailsFillerExpander
    • Method argument in fill(): $dataElement.name$Details $dataElement.name$$dataElement.name$Details $dataElement.name$Details
      • Example (Element City): CityDetails cityCityDetails cityDetails
      • Affected anchors:
        • @fill and custom-fill
    • Method argument in fill$field.name$(): $dataElement.name$Details $dataElement.name$$dataElement.name$Details $dataElement.name$Details
      • Example (Element City): CityDetails cityCityDetails cityDetails
      • Affected anchors:
        • @fill-$field.name$ and custom-fill-$field.name$