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:
-
26.2.0-beta.1 on Maven Central
-
26.2.0-beta.1 on mvnrepository.com
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: UseITileGrid.ASYNC_LOAD_JOBNAME_PREFIXinstead. -
ITileGrid.PROP_ASYNC_LOAD_IDENTIFIER_PREFIX: UseITileGrid.ASYNC_LOAD_IDENTIFIER_PREFIXinstead. -
ITileGrid.PROP_WINDOW_IDENTIFIER_PREFIX: UseITileGrid.WINDOW_IDENTIFIER_PREFIXinstead. -
BasicCache: The constructors withoutlabelSupplierhave been removed. Use the ones includinglabelSupplier. A label supplier can be retrieved usingCacheBuilder.getLabelSupplier(). -
EncryptionKey: The constructor withoutcompatibilityHeaderhas been removed. -
FileUtility.extractArchivehas been removed. It used a dangerous special handling for zip directories with the same name as the target directory. UseFileUtility.extractZipinstead. If top-level directories exist, they should be removed manually as required. -
Config property
scout.rest.api.exposed.enforcehas been removed without replacement. If the feature is not required, remove theApiExposedFilterfrom your filter chain. -
TrivialAccessController.TrivialAuthConfig.getPathInfoFilterhas been removed. UseTrivialAccessController.TrivialAuthConfig.getExclusionFilterinstead. -
The package
org.eclipse.scout.rt.server.commons.servlet.filter.gzipand 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
UrlHintsandUrlHintsHelperhave 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 flexibleCodeType.codes(options?: CodeTypeCodesOptions). It provides an optionrootOnlyamongst others. -
Page.getOutline()function was replaced withPage.outlineproperty. -
Page._pageParam()function was removed as it was never used. -
PageWithTable.createChildPage()function was replaced withPageWithTable._createChildPage(). -
Form._withBusyHandling()was renamed toForm.withBusyHandling(). -
Column.isVisible()function was replaced withColumn.visibleproperty. -
Table.removeAllRows()was deleted. UseTable._removeAllRows()to only remove DOM elements, otherwise useTable.deleteAllRows()(recommended). -
Table.groupColumn()was deleted. UseTable.group()instead. -
Table.removeColumnGrouping()was deleted. UseTable.removeGroupColumn()instead. -
Table.removeAllColumnGroupings()was deleted. UseTable.removeGroupColumn()instead. -
Table.isHierarchical()was deleted. UseTable.hierarchicalproperty instead. -
Table.getVisibleRows()was deleted. UseTable.visibleRowsproperty instead. -
TableRow.getTable()was deleted. UseTableRow.tableproperty instead. -
TileGrid.tilesWithoutPlaceholders()has been deleted. UseTileGrid.tilesinstead. -
TreerNode.getTree()has been deleted. UseTreeNode.treeproperty instead. -
objects.isPlainObject()has been deleted. Useobjects.isObject()orobjects.isPojo()instead. -
Widget.isVisible()has been deleted. UseWidget.visibleproperty instead. -
Widget.getFocusableElement()has been deleted. UseWidget.get$Focusable()instead. -
widgets.createUniqueId()has been deleted. UseObjectIdProvider.get().createUiSeqId()instead. -
ObjectFactory.createUniqueIdhas been removed. UseObjectIdProvider.get().createUiSeqId()decorator instead. -
ObjectFactoryOptions.ensureUniqueIdhas 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: Useanimationproperty directly. So instead of e.g.#scout.animation(show-axis-select 0.5s ease-in-out 1);useanimation: show-axis-select 0.5s ease-in-out 1;. -
#scout.animation-duration: Useanimation-durationproperty directly. So instead of e.g.#scout.animation-duration(0.5s);useanimation-duration: 0.5s;. -
#scout.animation-name: Useanimation-nameproperty directly. So instead of e.g.#scout.animation-name(slideout-right);useanimation-name: slideout-right;. -
#scout.animation-delay: Useanimation-delayproperty directly. So instead of e.g.#scout.animation-delay(400ms);useanimation-delay: 400ms;. -
#scout.animation-fill-mode: Useanimation-fill-modeproperty directly. So instead of e.g.#scout.animation-fill-mode(forwards);useanimation-fill-mode: forwards;. -
#scout.animation-timing-function: Useanimation-timing-functionproperty directly. So instead of e.g.#scout.animation-timing-function(linear);useanimation-timing-function: linear;. -
#scout.animation-iteration-count: Useanimation-iteration-countproperty directly. So instead of e.g.#scout.animation-iteration-count(1);useanimation-iteration-count: 1;. -
#scout.transform: Usetransformproperty directly. So instead of e.g.#scout.transform(rotatex(180deg));usetransform: rotatex(180deg);. -
#scout.transform-origin: Usetransform-originproperty directly. So instead of e.g.#scout.transform-origin(top);usetransform-origin: top;. -
#scout.cursor-grab: Usecursorproperty directly. So instead of e.g.#scout.cursor-grab();usecursor: grab;. -
#scout.cursor-grabbing: Usecursorproperty directly. So instead of e.g.#scout.cursor-grabbing();usecursor: 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.AbstractRestLookupCall → org.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.
tree.visitNodes(node => {
return true;
});
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.sessionandorg.eclipse.scout.rt.shared.session.test -
Server session code was moved into new module
org.eclipse.scout.rt.server.sessionandorg.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 |
|---|---|
|
|
|
|
|
|
|
|
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 |
|---|---|
|
|
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 |
|---|---|
|
|
|
or |
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.CURRENTprovides access to the id of the client session which is associated with the current thread. -
Implementations of
org.eclipse.scout.rt.server.session.IInitialSharedVariableContributorallow 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 |
|---|---|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
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 |
|---|---|
|
|
|
|
|
|
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 |
|---|---|
|
removed - use |
|
removed - use |
|
removed - use |
|
removed - use |
|
removed - use |
|
removed - use |
|
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. |
|
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 |
|---|---|
|
removed - use |
|
removed - use |
|
removed - use |
|
removed - use |
|
removed - use |
|
removed - use |
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.
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]}));
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.
subType of the FancyEvent matches.this.events.registerSubTypePredicate('fancy', (event: FancyEvent, subType: string) => event.subType === subType);
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:
-
labelVisibletofalse -
statusVisibletofalse -
gridDataHints.useUiHeighttotrue -
gridDataHints.weightYto1
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 codeif (!ACCESS.check(new ReadBakeryOutlinePermission())) { throw new AccessForbiddenException("My special error message"); }Listing 8. New codeACCESS.checkAndThrow(new ReadBakeryOutlinePermission(), "My special error message"); -
The
AccessForbiddenExceptionnow includes a permission code – use.withPermission(p)when manually throwing anAccessForbiddenExceptioncaused by a permission check.Listing 9. Example of a manually thrownAccessForbiddenExceptionReadBakeryOutlinePermission 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:
-
Replace all occurrences of
pnpm install --ignore-scriptswithpnpx @eclipse-scout/releng@~26.2.0 install.Some places that might change:
-
The
pnpm-installscript in thepackage.jsonfiles. -
In Eclipse: The run configuration shell scripts:
js build.shorjs build.cmd.
-
-
Replace the version specifier of the
@eclipse-scout/relengdependency in allpackage.jsonfiles with~26.2.0. -
Delete the
pnpm-lock.yamland addpnpm-lock.yamlto your.gitignorefile to ensure it is not commited as it will not be used anyway. -
Ensure all
package.jsonfiles include values for thenameandversionattributes, otherwise generating the overrides will fail. -
Ensure your
pnpm-workspace.yamlfile only listspackagesfor which the path exists and contains apackage.jsonfile.