Eclipse Scout Migration Guide

This document is referring to an upcoming Scout release. Please click here for the current version.

About This Document

This document describes all relevant changes from Eclipse Scout 25.2 to Eclipse Scout 26.2. If existing code has to be migrated, instructions are provided here.

Obtaining the Latest Version

Scout Runtime for Java

Scout Runtime artifacts for Java are distributed using Maven Central:

Usage example in the parent POM of your Scout application:

<dependency>
    <groupId>org.eclipse.scout.rt</groupId>
    <artifactId>org.eclipse.scout.rt</artifactId>
    <version>26.2.0-beta.1</version>
    <type>pom</type>
    <scope>import</scope>
</dependency>

Scout Runtime for JavaScript

Scout Runtime artifacts for JavaScript are distributed using npm:

Usage example in your package.json:

{
  "name": "my-module",
  "version": "1.0.0",
  "devDependencies": {
    "@eclipse-scout/cli": "26.2.0-beta.1",
    "@eclipse-scout/releng": "~26.2.0"
  },
  "dependencies": {
    "@eclipse-scout/core": "26.2.0-beta.1",
    "jquery": "3.7.1"
  }
}

The pre-built Scout JavaScript assets are also available using a CDN (e.g. to be directly included in a html document): https://www.jsdelivr.com/package/npm/@eclipse-scout/core?path=dist

IDE Tooling (Scout SDK)

Scout officially supports IntelliJ IDEA and Eclipse for Scout Developers.

IntelliJ IDEA

You can download the Scout plugin for IntelliJ IDEA from the JetBrains Plugin Repository or you can use the plugins client built into IntelliJ IDEA. Please refer to the IntelliJ Help on how to install and manage plugins.

Eclipse

You can download the complete Eclipse IDE with Scout SDK included here:
Eclipse for Scout Developers

To install the Scout SDK into your existing Eclipse IDE, use this P2 update site:
https://download.eclipse.org/scout/releases

REST operations: Add Consumes annotation

It is recommended that all REST operations which consume a request entity body message have a Consumes annotation set to restrict invalid input. Therefore, a test has been added which fails if there are such operations which do not have a Consumes annotation. The AbstractRestResourceAnnotationTest has to be extended in your modules to run this test.

REST resources: Explicit @Path annotation required

It is recommended that all REST resource classes explicitly declare a @Path annotation.

According to the Jakarta RESTful Web Services specification, JAX-RS annotations — including @Path — are not inherited from superclasses or interfaces. While Jersey, the implementation we use, does attempt to locate a @Path annotation on parent classes, this behavior is not defined by the specification and should not be relied upon.

To ensure compliance, a test has been introduced that fails if any REST resource is missing a @Path annotation. To activate this validation for your module, extend the AbstractRestResourceAnnotationTest class accordingly.

Removal of autoPrefixWildcardForTextSearch on Desktop

The methods isAutoPrefixWildcardForTextSearch and setAutoPrefixWildcardForTextSearch on IDesktop have been removed. They have not been used since years and were never supported in Scout JS.

If you need a prefix wildcard, add it to your search texts manually where required.

Removal of old Maven-Master properties

The Maven Build no longer uses npm to run scripts. Npm is now only used to install pnpm and @eclipse-scout/releng. Then, pnpm is used to run build and test scripts. Accordingly, the following Maven-Master properties have been removed and can be deleted without replacement:

  • master_npm_version

  • master_webpack_options

Removal of Deprecated Code

The following Java code was deprecated since at least one release and has been removed:

  • ITileGrid.PROP_ASYNC_LOAD_JOBNAME_PREFIX: Use ITileGrid.ASYNC_LOAD_JOBNAME_PREFIX instead.

  • ITileGrid.PROP_ASYNC_LOAD_IDENTIFIER_PREFIX: Use ITileGrid.ASYNC_LOAD_IDENTIFIER_PREFIX instead.

  • ITileGrid.PROP_WINDOW_IDENTIFIER_PREFIX: Use ITileGrid.WINDOW_IDENTIFIER_PREFIX instead.

  • BasicCache: The constructors without labelSupplier have been removed. Use the ones including labelSupplier. A label supplier can be retrieved using CacheBuilder.getLabelSupplier().

  • EncryptionKey: The constructor without compatibilityHeader has been removed.

  • FileUtility.extractArchive has been removed. It used a dangerous special handling for zip directories with the same name as the target directory. Use FileUtility.extractZip instead. If top-level directories exist, they should be removed manually as required.

  • Config property scout.rest.api.exposed.enforce has been removed without replacement. If the feature is not required, remove the ApiExposedFilter from your filter chain.

  • TrivialAccessController.TrivialAuthConfig.getPathInfoFilter has been removed. Use TrivialAccessController.TrivialAuthConfig.getExclusionFilter instead.

  • The package org.eclipse.scout.rt.server.commons.servlet.filter.gzip and all containing classes have been removed. The HTTP request compression is now automatically handled by Jetty instead of this custom implementation.

  • Accordingly, the compression flags on UrlHints and UrlHintsHelper have been removed. So compression can no longer be enabled or disabled on the fly. Old cookie values are still valid but the compression flag (Z) will be ignored now.

The following TypeScript code was deprecated since at least one release and has been removed:

  • CodeType.codes(rootOnly?: boolean) was deleted. Use the more flexible CodeType.codes(options?: CodeTypeCodesOptions). It provides an option rootOnly amongst others.

  • Page.getOutline() function was replaced with Page.outline property.

  • Page._pageParam() function was removed as it was never used.

  • PageWithTable.createChildPage() function was replaced with PageWithTable._createChildPage().

  • Form._withBusyHandling() was renamed to Form.withBusyHandling().

  • Column.isVisible() function was replaced with Column.visible property.

  • Table.removeAllRows() was deleted. Use Table._removeAllRows() to only remove DOM elements, otherwise use Table.deleteAllRows() (recommended).

  • Table.groupColumn() was deleted. Use Table.group() instead.

  • Table.removeColumnGrouping() was deleted. Use Table.removeGroupColumn() instead.

  • Table.removeAllColumnGroupings() was deleted. Use Table.removeGroupColumn() instead.

  • Table.isHierarchical() was deleted. Use Table.hierarchical property instead.

  • Table.getVisibleRows() was deleted. Use Table.visibleRows property instead.

  • TableRow.getTable() was deleted. Use TableRow.table property instead.

  • TileGrid.tilesWithoutPlaceholders() has been deleted. Use TileGrid.tiles instead.

  • TreerNode.getTree() has been deleted. Use TreeNode.tree property instead.

  • objects.isPlainObject() has been deleted. Use objects.isObject() or objects.isPojo() instead.

  • Widget.isVisible() has been deleted. Use Widget.visible property instead.

  • Widget.getFocusableElement() has been deleted. Use Widget.get$Focusable() instead.

  • widgets.createUniqueId() has been deleted. Use ObjectIdProvider.get().createUiSeqId() instead.

  • ObjectFactory.createUniqueId has been removed. Use ObjectIdProvider.get().createUiSeqId() decorator instead.

  • ObjectFactoryOptions.ensureUniqueId has been removed. Use @objectFactoryHints({ensureId: true}) decorator on the affected class instead.

In case you still use JavaScript code (instead of TypeScript), these API changes will not be verified using the TypeScript compiler! Then you have to go through your JavaScript code manually to find all usages.

The following Less mixins have been removed as they are no longer necessary:

  • #scout.animation: Use animation property directly. So instead of e.g. #scout.animation(show-axis-select 0.5s ease-in-out 1); use animation: show-axis-select 0.5s ease-in-out 1;.

  • #scout.animation-duration: Use animation-duration property directly. So instead of e.g. #scout.animation-duration(0.5s); use animation-duration: 0.5s;.

  • #scout.animation-name: Use animation-name property directly. So instead of e.g. #scout.animation-name(slideout-right); use animation-name: slideout-right;.

  • #scout.animation-delay: Use animation-delay property directly. So instead of e.g. #scout.animation-delay(400ms); use animation-delay: 400ms;.

  • #scout.animation-fill-mode: Use animation-fill-mode property directly. So instead of e.g. #scout.animation-fill-mode(forwards); use animation-fill-mode: forwards;.

  • #scout.animation-timing-function: Use animation-timing-function property directly. So instead of e.g. #scout.animation-timing-function(linear); use animation-timing-function: linear;.

  • #scout.animation-iteration-count: Use animation-iteration-count property directly. So instead of e.g. #scout.animation-iteration-count(1); use animation-iteration-count: 1;.

  • #scout.transform: Use transform property directly. So instead of e.g. #scout.transform(rotatex(180deg)); use transform: rotatex(180deg);.

  • #scout.transform-origin: Use transform-origin property directly. So instead of e.g. #scout.transform-origin(top); use transform-origin: top;.

  • #scout.cursor-grab: Use cursor property directly. So instead of e.g. #scout.cursor-grab(); use cursor: grab;.

  • #scout.cursor-grabbing: Use cursor property directly. So instead of e.g. #scout.cursor-grabbing(); use cursor: grabbing;.

  • KeyFrames for the following animations have been deleted as they were no longer used. If the KeyFrames are still necessary, copy them to your own code from a previous release:

    • fadeout-grow

    • fadein-grow-blur

    • rotation-reverse

    • pulse-opacity

    • rotate-x

AbstractRestLookupCall moved to shared module

AbstractRestLookupCall was moved from the client to the shared module: org.eclipse.scout.rt.client.services.lookup.AbstractRestLookupCallorg.eclipse.scout.rt.shared.services.lookup.AbstractRestLookupCall.

SmtpConnectionPool: Connection error/idle handling

For the org.eclipse.scout.rt.mail.smtp.SmtpConnectionPool in the past idle timeouts could be defined in seconds. However, connections were only checked once per minute, hence idle timeouts less than one minute were not respected. This check interval has been decreased from one minute to 20 seconds (default value), it is now configurable by config property scout.smtp.pool.closeIdleConnectionsJobSchedule. Also the default idle timeout has been decreased from one minute to 20 seconds (existing config property scout.smtp.pool.maxIdleTime).

Also the connection error handling has been changed, connection error codes 421 and 451 are now also treated as failed connection (according to RFC 5312 3.8 connection failures and at least error codes 451 should be treated the same way).

Tree (Scout JS): API of VisitNodes Changed

Returning true in a visitor used for Tree.visitNodes now stops visiting completely instead of just skipping the subtree, see also Release Notes.

Please check your JavaScript / TypeScript code for occurrences of visitNodes and if the visitor explicitly returns true, replace it with TreeVisitResult.SKIP_SUBTREE.

Listing 1. Old
tree.visitNodes(node => {
  return true;
});
Listing 2. New
tree.visitNodes(node => {
  return TreeVisitResult.SKIP_SUBTREE;
});

Trust manager and remote files

org.eclipse.scout.rt.server.commons.GlobalTrustManager.getTrustedCertificatesInRemoteFiles() has been removed. As a result, all trusted certificates now have to be provided locally.

The following service operations have also been removed:

  • org.eclipse.scout.rt.client.services.common.file.IFileService.syncRemoteFiles(String, FilenameFilter)

  • org.eclipse.scout.rt.client.services.common.file.IFileService.syncRemoteFilesToPath(String, String, FilenameFilter)

  • org.eclipse.scout.rt.shared.services.common.file.IRemoteFileService.getRemoteFiles(String, FilenameFilter, RemoteFile[])

ICacheBuilder.withMaxConcurrentResolve: Allow multiple resolve operations for one thread

The BoundedResolveCacheWrapper (used implicitly by ICacheBuilder.withMaxConcurrentResolve) has been changed to allow multiple resolve operations for one thread (default is now reentrant) to avoid a potential deadlock cause. That is, one thread will only be counted once towards the limit.

However, this is just one potential deadlock cause, deadlocks may still occur if the resolve operation also relies on external semaphores.

To restore the previous behavior the BoundedResolveCacheWrapper may be added directly as custom wrapper with the second constructor allowing to disable this reentrant behavior.

Stateless Backend Server

As part of the move toward a stateless backend server, the server session support was extracted into separate modules for legacy support.

  • Shared session code was moved into new module org.eclipse.scout.rt.shared.session and org.eclipse.scout.rt.shared.session.test

  • Server session code was moved into new module org.eclipse.scout.rt.server.session and org.eclipse.scout.rt.server.session.test

The new default setup is to use the Scout backend without session-support.

Several shared classes were moved into a .session package, adapt the imports in your UI-server modules.

Old New

org.eclipse.scout.rt.shared.ISession

org.eclipse.scout.rt.shared.session.ISession

org.eclipse.scout.rt.shared.job.filter.event.SessionJobEventFilter

org.eclipse.scout.rt.shared.session.job.filter.event.SessionJobEventFilter

org.eclipse.scout.rt.shared.job.filter.future.SessionFutureFilter

org.eclipse.scout.rt.shared.session.job.filter.future.SessionFutureFilter

org.eclipse.scout.rt.shared.session.Sessions.randomSessionId()

org.eclipse.scout.rt.shared.session.SessionId.randomSessionId()

The unit test annotation @RunWithServerSession has become obsolete if you do not use backend sessions any longer. Remove the annotation and make sure your test is annotated with @RunWithSubject.

API for current user

A new thread local org.eclipse.scout.rt.platform.security.User.CURRENT provides access to the user which is associated with the current thread. This object replaces the org.eclipse.scout.rt.shared.user.UserId.CURRENT thread local that has been introduced in Scout 26.1.

Old New

org.eclipse.scout.rt.shared.user.UserId.CURRENT.get()

org.eclipse.scout.rt.shared.user.User.currentUserId()

The user associated to the current thread can be accessed via org.eclipse.scout.rt.platform.security.User.current().

Creation and initialization of the User is centralized in IAccessControlService.

Old New

org.eclipse.scout.rt.security.IAccessControlService.getUserIdOfCurrentSubject()

org.eclipse.scout.rt.shared.user.User.currentUserId()

org.eclipse.scout.rt.security.IAccessControlService.getUserId(Subject)

org.eclipse.scout.rt.security.IAccessControlService.getUser(Subject).getUserId()

or org.eclipse.scout.rt.security.IAccessControlService.extractUserId(Subject) in case only the id should be extracted from the Subject.

A User can be assigned to a RunContext. It can be assigned via RunContext.withUser(User) and accessed via RunContext.getUser().

Make sure when assigning a different Subject to a run context to also update the User if necessary.
RunContexts.empty()
    .withSubject(subject)
    .withUser(BEANS.get(IAccessControlService.class).getUser(subject))

API replacing backend server session

The following APIs were introduced as replacement for the former backend server session:

  • New thread local org.eclipse.scout.rt.shared.session.SessionId.CURRENT provides access to the id of the client session which is associated with the current thread.

  • Implementations of org.eclipse.scout.rt.server.session.IInitialSharedVariableContributor allow to load user/session-specific data in backend and return to UI server when a client session is initialized.

public class UserDataSharedVariableContributor implements IInitialSharedVariableContributor {

  @Override
  public void contribute(Map<String, Object> variables) {
    // load data
    variables.put("mykey", "myvalue");
  }
}
Make sure to invoke method loadInitialSharedVariables when loading your client session in order to load shared variables from backend server.
  @Override
  protected void execLoadSession() {
    loadInitialSharedVariables();
    // ...

Legacy server session support

If your application requires session support in Scout backend, add a dependency to org.eclipse.scout.rt.server.session in your server module and a dependency to org.eclipse.scout.rt.shared.session in your shared module.

The Scout backend server session support is considered deprecated and will be removed in a future release.

As part of extracting the session code into separate modules several classes were moved into a .session package. Adapt your imports in your server modules.

Old New

org.eclipse.scout.rt.server.IServerSession

org.eclipse.scout.rt.server.session.IServerSession

org.eclipse.scout.rt.server.AbstractServerSession

org.eclipse.scout.rt.server.session.AbstractServerSession

org.eclipse.scout.rt.server.context.HttpServerRunContextProducer

org.eclipse.scout.rt.server.session.context.HttpServerSessionRunContextProducer

org.eclipse.scout.rt.server.context.ServerRunContextProducer

org.eclipse.scout.rt.server.session.context.ServerSessionRunContextProducer

org.eclipse.scout.rt.server.context.ServerRunContext

org.eclipse.scout.rt.server.session.context.ServerSessionRunContext

org.eclipse.scout.rt.server.context.ServerRunContextFilter

org.eclipse.scout.rt.server.session.context.ServerSessionRunContextFilter

org.eclipse.scout.rt.server.context.ServerRunContexts

org.eclipse.scout.rt.server.session.context.ServerSessionRunContexts

org.eclipse.scout.rt.testing.server.runner.RunWithServerSession

org.eclipse.scout.rt.testing.server.session.runner.RunWithServerSession

API changes for JAX-WS modules

As part of extracting the session code into separate modules several classes for providing a RunContext were moved to org.eclipse.scout.rt.server.jaxws because they were used solely in a JAX-WS context.

Old New

org.eclipse.scout.rt.platform.context.RunWithRunContext

org.eclipse.scout.rt.server.jaxws.context.RunWithRunContext

org.eclipse.scout.rt.platform.context.RunContextProducer

org.eclipse.scout.rt.server.jaxws.context.RunContextProducer

org.eclipse.scout.rt.server.context.ServerRunContextProducer

org.eclipse.scout.rt.server.jaxws.context.ServerRunContextProducer

If you use JAX-WS together with legacy backend server session support you need to override and replace the org.eclipse.scout.rt.server.jaxws.context.ServerRunContextProducer and delegate to org.eclipse.scout.rt.server.session.context.ServerSessionRunContextProducer.
@Replace
public class JaxWsServerSessionRunContextProducer extends ServerRunContextProducer {
  @Override
  public ServerRunContext produce(final Subject subject) {
    return BEANS.get(ServerSessionRunContextProducer.class).produce(subject);
  }
}

ClientNotificationRegistry API changes

The client notification dispatching was refactored as preparation step for a stateless Scout backend. The API of org.eclipse.scout.rt.server.clientnotification.ClientNotificationRegistry changed.

The central change is the removal of the boolean distributeOverCluster overloads: notifications are now always distributed within the cluster and published to all UI server nodes. The only exception is the new (but deprecated, legacy) putTransactionalForAllNodesWithoutClusterNotification(Serializable) method which allows to publish a notification only for UI nodes attached to the current backend node.

Non-transactional put / publish methods

The boolean distributeOverCluster overloads have been removed. Use the single-argument variant; cluster distribution is now always performed.

Old method New method

void putForUser(String userId, Serializable notification, boolean distributeOverCluster)

removed - use putForUser(String, Serializable)

void putForUsers(Set<String> userIds, Serializable notification, boolean distributeOverCluster)

removed - use putForUsers(Set<String>, Serializable)

void putForSession(String sessionId, Serializable notification, boolean distributeOverCluster)

removed - use putForSession(String, Serializable)

void putForAllSessions(Serializable notification, boolean distributeOverCluster)

removed - use putForAllSessions(Serializable)

void putForAllNodes(Serializable notification, boolean distributeOverCluster)

removed - use putForAllNodes(Serializable)

void publish(ClientNotificationAddress address, Serializable notification, boolean distributeOverCluster)

removed - use publish(ClientNotificationAddress, Serializable)

void publishWithoutClusterNotification(Collection<? extends ClientNotificationMessage> messages)

removed - Adapt invoking code in order to allow publishing this notification for all UI nodes. In the future, we’ll have a stateless Scout backend without knowing which UI node is attached to a specific backend.

void publishWithoutClusterNotification(Collection<? extends ClientNotificationMessage> messages, NodeId excludedUiNodeId)

removed - Adapt invoking code in order to allow publishing this notification for all UI nodes. In the future, we’ll have a stateless Scout backend without knowing which UI node is attached to a specific backend.)

Transactional put methods

The boolean distributeOverCluster overloads have been removed. Use the single-argument variant; cluster distribution is now always performed.

Old method New method

void putTransactionalForUser(String userId, Serializable notification, boolean distributeOverCluster)

removed - use putTransactionalForUser(String, Serializable)

void putTransactionalForUsers(Set<String> userIds, Serializable notification, boolean distributeOverCluster)

removed - use putTransactionalForUsers(Set<String>, Serializable)

void putTransactionalForSession(String sessionId, Serializable notification, boolean distributeOverCluster)

removed - use putTransactionalForSession(String, Serializable)

void putTransactionalForAllSessions(Serializable notification, boolean distributeOverCluster)

removed - use putTransactionalForAllSessions(Serializable)

void putTransactionalForAllNodes(Serializable notification, boolean distributeOverCluster)

removed - use putTransactionalForAllNodes(Serializable) or putTransactionalForAllNodesWithoutClusterNotification(Serializable) (new, legacy - publishes only to client nodes known to this backend, no cluster notification; will be removed in a future release)

void putTransactional(ClientNotificationAddress address, Serializable notification, boolean distributeOverCluster)

removed - use putTransactional(ClientNotificationAddress, Serializable)

ClientNotificationMessage

org.eclipse.scout.rt.shared.clientnotification.ClientNotificationMessage

The distributeOverCluster flag is deprecated. A new constructor without the flag (defaulting to true) has been added.

HybridManager API improvements (Scout JS)

The HybridManager provides API to dispose formerly created widgets. Former implementations calling the hybrid Action scout.DisposeWidgets manually using the remote ids can be migrated.

Listing 3. Old: Disposing a Widget using the hybrid action scout.DisposeWidgets.
// create widget
const hybridManager = await HybridManager.get(this.session, true);
const id = hybridManager.callAction('example.CreateMyFancyWidget');
const myFancyWidget = (await hybridManager.when(`widgetAdd:${id}`)).widget;

// dispose widget
hybridManager.callAction('scout.DisposeWidgets', scout.create(DisposeWidgetsHybridActionDo, {ids: [id]}));
Listing 4. New: Disposing a Widget using HybridManager.disposeWidgets.
// create widget
const hybridManager = await HybridManager.get(this.session, true);
const id = hybridManager.callAction('example.CreateMyFancyWidget');
const myFancyWidget = (await hybridManager.when(`widgetAdd:${id}`)).widget;

// destroy widget
myFancyWidget.destroy();

EventSupport API changes for subtypes (Scout JS)

The EventSupport provides API to register callback functions in order to handle events with subtypes. Consider e.g. a FancyEvent that is always triggered with the type fancy but has a property subType which can hold the values foo or bar. In order to support listeners for fancy:foo or fancy:bar such a callback needs to be registered. Earlier this was done using a subtype predicate, that was handed over the event and the subtype and returned a boolean flag whether the subtype matches. This was changed to a subtype provider, that is handed over the event and returns the subtype. All places using these subtype callbacks need to be migrated.

Listing 5. Old: Registering a predicate that checks if the subType of the FancyEvent matches.
this.events.registerSubTypePredicate('fancy', (event: FancyEvent, subType: string) => event.subType === subType);
Listing 6. New: Registering a provider that returns the subType of the FancyEvent.
this.events.registerSubTypeProvider('fancy', (event: FancyEvent) => event.subType);

Default timeout for JAX-WS requests

  • The default connect timeout for a JAX-WS request (scout.jaxws.consumer.connectTimeout) has been changed from infinite to 5 minutes.

  • The default read timeout for a JAX-WS request (scout.jaxws.consumer.readTimeout) has been changed from infinite to 30 minutes.

In case these timeouts are too low for your setup, update the corresponding config properties.

WrappedFormField (Scout JS)

The defaults of the following properties have changed:

  • labelVisible to false

  • statusVisible to false

  • gridDataHints.useUiHeight to true

  • gridDataHints.weightY to 1

If you use the WrappedFormField in your Scout JS code, please verify the layout still looks and behaves as expected.

ITreeUIFacade.setNodeSelectedAndExpandedFromUI Moved

The method has been moved to IOutline and renamed to drillDown.

It is called when double-clicking a table row in the detail table of a page to select and expand the corresponding child page. But, expanding is actually not desired for table pages, so now only node pages are expanded.

If you need a specific table page or IJsPage to be expanded on this operation, you can override the method IPage.computeExpandOnDrillDown.

Tab Box: Mark Strategy renamed

ITabBox.MARK_STRATEGY_EMPTY has been renamed to ITabBox.MARK_STRATEGY_NOT_EMPTY because the tab is marked if it is not empty.

Tab Box: Mark Strategy Added (Scout JS)

A tab item is now marked if it has content or if it needs to be saved (if used in a search form).

In most cases, this should work as expected without a code migration. However, it may happen that a tab item will be marked even it looks empty at first glance, for example if it has a hidden field with a value. In that case you can set checkEmpty on the field to false, or provide a function to implement a custom empty computation. When providing a function, it may be necessary to call updateEmpty whenever a condition changes that you use in your empty computation.

Disabling the empty check also affects the mandatory handling: if checkEmpty is set to false on a mandatory field, the form cannot be saved anymore because the field would always be invalid. However, this mainly affects ValueFields, it can safely be disabled for composite fields like a GroupBox.

To disable the marking completely without affecting the mandatory handling, you can set TabBox.markStrategy to null.

Tab Box: Stricter Handling of Tab Items (Scout JS)

The tab items of a tab box (TabBox.tabItems) need to have the type TabItem. This is nothing new, but until now it kind of worked with a regular GroupBox as well. This was never intended.

To ensure the tab items have the correct type, the tab box now throws an error if a tab item doesn’t have the type TabItem.

To make sure you won’t get the error, you should check your tab boxes and extensions for tab boxes. You should find most of them by searching for objectType: TabBox and property: 'tabItems'.

Form Field: Renamed _updateEmpty (Scout JS)

The protected method FormFeld._updateEmpty() has been made public and renamed to FormFeld.updateEmpty().

Permission checks

  • A new method ACCESS.checkAndThrow(permission, accessCheckFailedMessage) has been added that allows to set a custom error message if the permission check fails.

    Listing 7. Previous code
    if (!ACCESS.check(new ReadBakeryOutlinePermission())) {
      throw new AccessForbiddenException("My special error message");
    }
    Listing 8. New code
    ACCESS.checkAndThrow(new ReadBakeryOutlinePermission(), "My special error message");
  • The AccessForbiddenException now includes a permission code – use .withPermission(p) when manually throwing an AccessForbiddenException caused by a permission check.

    Listing 9. Example of a manually thrown AccessForbiddenException
    ReadBakeryOutlinePermission permission = new ReadBakeryOutlinePermission();
    if (!ACCESS.check(permission)) {
      throw new AccessForbiddenException(TEXTS.get("YouAreNotAllowedToReadThisData"))
        .withTitle("My special title")
        .withPermission(permission);
    }

Simplify System.getEndpointUrl (Scout JS)

The function System.getEndpointUrl only takes one argument now. The first one has been removed and only the second argument (default URL) is used for both the endpoint identifier and default URL.

Migrate from System.getEndpointUrl('name', 'default/url') to System.getEndpointUrl('default/url').

In case an existing named URL has been replaced using System.setEndpointUrl('name', 'new/url') it must be migrated to System.setEndpointUrl('default/url', 'new/url').

Locking of Transitive Node Dependencies

Scout includes support to lock the Node dependencies. See the Technical Guide for details.

To enable the feature perform the following:

  1. Replace all occurrences of pnpm install --ignore-scripts with pnpx @eclipse-scout/releng@~26.2.0 install.

    Some places that might change:

    • The pnpm-install script in the package.json files.

    • In Eclipse: The run configuration shell scripts: js build.sh or js build.cmd.

  2. Replace the version specifier of the @eclipse-scout/releng dependency in all package.json files with ~26.2.0.

  3. Delete the pnpm-lock.yaml and add pnpm-lock.yaml to your .gitignore file to ensure it is not commited as it will not be used anyway.

  4. Ensure all package.json files include values for the name and version attributes, otherwise generating the overrides will fail.

  5. Ensure your pnpm-workspace.yaml file only lists packages for which the path exists and contains a package.json file.