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.1. 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.1.0-beta.1 on Maven Central
-
26.1.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.1.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.1.0-beta.1",
"@eclipse-scout/releng": "^26.1.0"
},
"dependencies": {
"@eclipse-scout/core": "26.1.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
New Build & Runtime Requirements
Scout 26.1 requires at least the following:
-
Build and runtime of Scout 26.1 require Java 25. The compiler target level is set to Java 21.
-
Furthermore, the build requires
-
Node: >= 24.12.0
-
Pnpm: >= 10.26.1
-
Action / Menu: Tabbable Default Changed (Scout JS)
An Action and a Menu is now tabbable and has a keystroke to execute it by default.
This means if you used an action or a menu outside a menu bar, it can now get the focus using the keyboard.
This is important to improve the accessibility of your application.
However, there may be some actions or menus that should not be tabbable.
In that case just set tabbable to false.
WidgetField: Scrollable Default Changed (Scout JS)
A WidgetField has a property scrollable whose default value is true.
This is often not desired as a WidgetField is supposed to be a wrapper for a widget without changing its behavior.
This is why the default value has been changed to false.
So you need to check your widget fields if they really need to be scrollable and if yes set scrollable to true.
Normally, this should not be the case as a surrounding container like the main box is already scrollable.
Switch: Tabbable Default Changed (Scout JS)
A Switch is now tabbable by default.
This is important to improve the accessibility of your application.
However, there may be some switches that should not be tabbable.
In that case just set tabbable to false.
Code Cleanup
JQuery-Scout (Scout JS)
The following functions have been renamed:
-
select(boolean) → setSelected(boolean)
If you followed the naming convention, you can use the following regex to find the occurrences:\$\w+\.select\(
Note:select()also exists on anHTMLInputElement, so make sure you don’t accidentally rename the wrong method (if you use TypeScript the compiler will help you).
The following functions have been removed:
-
selectOne()
Replace withsetSelected(true)andsetSelected(false)on the siblings.
Widget.cssClass: API Changes (Scout JS)
The methods to modify the cssClass property of the Widget were moved to the styles utility (see Release Notes).
The API of setCssClass, addCssClass, removeCssClass, toggleCssClass and hasCssClass remains the same but the method cssClassAsArray and the static method cssClassAsArray were removed.
Code using these methods must be migrated as follows:
cssClassAsArray methods of the Widget.const widget = scout.create(Widget, {
// ...
cssClass: 'foo bar'
});
const widgetCssClassAsArray = widget.cssClassAsArray();
const cssClass = 'foo bar';
const cssClassAsArray = Widget.cssClassAsArray(cssClass);
cssClassAsArray methods of the styles utility.const widget = scout.create(Widget, {
// ...
cssClass: 'foo bar'
});
const widgetCssClassAsArray = styles.cssClassAsArray(widget.cssClass);
const cssClass = 'foo bar';
const cssClassAsArray = styles.cssClassAsArray(cssClass);
widgets Util: Behavior Change of preserveAndSetProperty (Scout JS)
If you use the function widgets.preserveAndSetProperty in your JavaScript code, please make sure that the variable that stores the preserved value is not initialized or initialized to undefined.
If it is initialized to null, remove the initialization.
Service tunnel: Servlet removed, REST resource added
In the past the service tunnel used its own servlet/communication implementation to transfer data between client and server module. The own (proprietary) logic was removed and standard REST communication will be used for data transfer now.
Most applications should not be affected by these changes as for the outside the service tunnel should still function the same way it did previously (most changes are under the hood).
However, for further understanding a few changes included in this change are described here:
The service tunnel client (e.g. HttpServiceTunnel) has been moved from org.eclipse.scout.rt.shared to org.eclipse scout.rt.client; in the past it would have been possible to use the service tunnel for communication between backend servers, this is not possible anymore.
As the class now resides in the client the ClientHttpServiceTunnel has been integrated into the HttpServiceTunnel.
The HttpServiceTunnel does not send the outgoing HTTP request itself anymore, instead a newly created ProcessResourceClient (REST resource client) is used.
This resource client uses the newly added ScoutBackendRestClientHelper for configuration.
The HttpServiceTunnelTransportManager and its configuration properties scout.servicetunnel.maxConnectionsPerRoute and scout.servicetunnel.maxConnectionsTotal have been removed.
On the server-side there is no ServiceTunnelServlet anymore to answer incoming HTTP requests, instead a ProcessResource (REST resource) has been created which delegates the request to the ServiceTunnelService.
Arbitrary IServiceTunnelContentHandler support was removed (and also the SoapServiceTunnelContentHandler implementation), the service tunnel now always uses the BinaryServiceTunnelContentHandler bean (which may still be extended).
The duplicate request detection SequenceNumberDuplicateDetector has been removed.
By default, the service tunnel uses gzip compression for outgoing and incoming requests, this may be configured using the following configuration properties:
-
scout.servicetunnel.compress: Specifies if the service tunnel should use gzip compression for outgoing requests (default: true) -
scout.app.gzip.inflateBufferSize: Set a positive number to enable incoming compressed requests (default: 2048), positive number must be set if previous property is set totrue
For outgoing request compression the org.glassfish.jersey.message.GZipEncoder is installed (by the GzipEncoderContributor, it handles content-encoding possibly set by ProcessResourceClient).
Incoming request decompression and outgoing response compression is handled by the org.eclipse.jetty.compression.server.CompressionHandler with org.eclipse.jetty.compression.gzip.GzipCompression.
The response decompression (if applicable) is handled by the HTTP client org.apache.hc.client5.http.entity.DecompressingEntity.
Applications which are deployed using a web.xml to a Jetty (legacy) may need to add the compression-gzip module.
Also, the process servlet and its mapping must be removed from the web.xml.
The following configuration properties have been changed:
-
server.url(legacy): Removed, usescout.backendUrlinstead. -
scout.servicetunnel.targetUrl: Removed, usescout.backendUrlinstead. -
scout.backendUrl: Moved from shared to client code (not applicable for server backend application anymore) -
scout.createTunnelToServerBeans: Moved from shared to client code (not applicable for server backend application anymore)
For all REST requests the cancellation behavior has been changed, previously a cancel request was sent and the client did wait (blocking) for the backend request to be cancelled. Now the same cancel request is sent to the backend which tries to cancel the possibly running request, but the client-side also aborts the running request itself without waiting for any cancellation response allowing the user to interact quicker with the application again (same behavior as previously in service tunnel).
DefaultAuthToken: Package changed, constant moved
As the DefaultAuthToken was not used exclusively for the service-tunnel the following types and constants have been moved:
| Type/Constant | Target |
|---|---|
|
|
|
|
|
|
|
|
|
|
Session API changes
As part of the move toward a stateless backend server, the API of the session has been changed.
ISession:
-
getSharedVariableMapmoved to theIClientSession. -
getUserIdmoved to theIClientSession. On server, use the ThreadLocalUserId.CURRENTinstead.
IClientSession:
-
replaceSharedVariableMapInternalremoved. To update variables on the client session usesetSharedVariablesor send aSharedContextChangedNotificationfrom the backend.
AbstractServerSession:
-
m_sharedVariableMapremoved. No more data should be stored on the server session. The data should be stored in user-based caches or loaded from the database instead. To add additional variables during client session initialization, implement anIInitialSharedVariableContributor.
AbstractClientSession:
-
initializeSharedVariablesrenamed toloadInitialSharedVariables.
ServiceTunnelRequest:
-
getSessionIdremoved. Replaced by a custom HTTP HeaderX-Scout-Client-Session-Id. -
setSessionIdremoved. Replaced by a custom HTTP HeaderX-Scout-Client-Session-Id.
User Preferences Moved from Shared to Client
As part of the move toward a stateless server session, IPreferences, IUserPreferencesService, IUserPreferencesStorageService, IPreferenceChangeListener and their corresponding implementations have been moved from shared to client.
If you use these classes you need to adjust your import statements.
Data Object Serializer Provider Implementations Supplemented with Order Annotation
The Scout implementation ScoutDataObjectSerializerProvider of serializer/deserializer provider interface IDataObjectSerializerProvider was supplemented with an @Order annotation using value 4500
to achieve a fixed order when looking up all instances by BEANS.all(IDataObjectSerializerProvider.class).
ACTION: Check custom implementations of IDataObjectSerializerProvider interface.
Default order for bean implementations without @Order annotation is 5000, which means your IDataObjectSerializerProvider is invoked as last instance.
Usually this is appropriate if your implementation just adds serializer or deserializers for additional classes.
If you want to override any Scout serializer/deserializer use an order lower than 4500 for your implementation and become the first provider which is invoked.
Simple tab box (Scout JS)
The SimpleTabBox has been improved and can now display the tabs on any side of the box.
As part of these adjustments, the associated SimpleTabAreaLayout has been modified and attributes have been renamed.
-
tabWidthwas renamed totabSize -
tabMinWidthwas renamed totabMinSize -
overflowTabItemWidthwas renamed tooverflowTabItemSize
SearchOutline (Scout Classic)
The SearchOutline now works for both Scout Classic and Scout JS pages (see Release Notes).
With this the property searchStatus was removed as it may no longer be updated manually.
Pages that need to add information to the searchStatus may simply implement ISearchPage and update their provided ISearchState with information about the result count, whether the result is limited or the search is still pending.
The SearchOutline will collect all these information and build an aggregated searchStatus.
JUnit: Runtime assertion for PlatformTestRunner
A new default runtime assertion has been added to the PlatformTestRunner.
If a test method exceeds a specific runtime duration it is still completed but fails afterward (allowing to easier identify unwanted long-running successful tests).
The default runtime limit is set to three minutes.
The limit may be increased by setting a higher timeout on the @Test annotation.
The limit is disabled completely when a negative timeout is set on the @Test annotation.
Removed automatic binding for session variables in SQL statements
Previously, SQL queries could reference session variables as bind parameters without explicitly providing their values. For example:
SELECT :userId;
In this case, the :userId bind was automatically populated from the current session context.
What Changed: Automatic binding of session variables to SQL bind parameters has been removed. Queries now require explicit binding of the session variables during execution.
For compatibility reasons the userId bind is still automatically bound with the current user id. But all the other session variables are not automatically bound anymore.
Action Required: Review and update your queries to explicitly bind the session variables when executing SQL statements.
ApiRestApplication: Mark external accessible REST operations
A new ApiExposedFilter has been created to distinguish between internal and external (proxied) requests, it is installed automatically by the ApiApiExposedFeature for the ApiRestApplication (feature is annotated with @RestApplicationScope(RestApplicationScopes.API) hence ExtRestApplication will ignore it).
All REST operations (methods) available through ApiRestApplication (for all resources)
-
which are accessed externally using an
AbstractRestProxyRequestHandler(accessed from scripts run by the browser) should be marked with@ApiExposedto keep them accessible (either the resource method or the whole class). -
which are only used internally between applications (not accessed externally) may optionally be marked with
@ApiExposed(false).
ESLint Update
Scout updated to the latest version of ESLint. Because ESLint changed their config file format, you need to adjust your ESLint files.
-
Rename
.eslintrc.jstoeslint.config.mjs -
Rewrite the content according to the Scout archetype
-
Add the exclusions from
.eslintignoreand remove that file (**/node_modulesis ignored by default and doesn’t need to be added)
import {defineConfig, globalIgnores} from 'eslint/config';
import scoutConfig from '@eclipse-scout/eslint-config';
export default defineConfig([
scoutConfig,
globalIgnores([
'.git',
'.idea',
'*/dist',
'*/target',
'*/src/main/resources',
'*/src/test/resources',
'*/src/main/java',
'*/src/test/java'
])
]);
ESLint Rule Deprecation
ESlint deprecated their formatting rules and moved them to a plugin called @stylistic.
Scout now uses this plugin, so the existing rules still apply.
This impacts you if you have a customized ruleset in eslint.config.mjs or if you have eslint-disable or eslint-disable-next-line directives in your code.
In either case, just prefix the deprecated rule names with @stylistic.
The easiest way to find these issues is to run eslint . in your workspace.
Example migration:
/* eslint-disable brace-style */
// eslint-disable-next-line max-len
/* eslint-disable @stylistic/brace-style */
// eslint-disable-next-line @stylistic/max-len
For more details about the deprecation please consult the official ESLint announcement.
HTTP Cache Control
In the past the following call was used to disable caching for an HTTP response: HttpCacheControl.checkAndSetCacheHeaders(req, resp, null).
This can now be changed to the more readable variant as the underlying method is public now: HttpCacheControl.disableCaching(resp).
The new function BEANS.get(HttpCacheControl.class).disableCaching(response) can also be used to replace the old pattern of manually setting the HTTP response headers:
response.setHeader("Cache-Control", "no-cache");
response.setHeader("Pragma", "no-cache");
response.setDateHeader("Expires", 0);
Hardening the Content Security Policy
The Content Security Policy used by Scout applications has been hardened.
It now makes use of nonces for JavaScript which may prevent cross-site scripting attacks. Nonces are only used for script tags. style or link tags used for CSS are not affected.
API Changes
-
The bean
org.eclipse.scout.rt.server.commons.servlet.ContentSecurityPolicyhas been moved toorg.eclipse.scout.rt.security.csp.ContentSecurityPolicyand is therefore more widely available.Furthermore, it changed its meaning: In the past it was a builder that was prefilled with the Scout defaults, adapted by your
config.propertiessettings. This is no longer the case. This class represents only a builder now and starts empty on creation.Please note: an empty CSP does not mean everything is blocked. Instead, not configuring a directive means: all allowed! Therefore, it is recommended to replace the former
ContentSecurityPolicyclass with the newConfigurableContentSecurityPolicyorBlockAllContentSecurityPolicyclass (see below). -
New bean
org.eclipse.scout.rt.security.csp.ConfigurableContentSecurityPolicywhich replaces the oldContentSecurityPolicyclass. It is still preloaded with the same Scout default directives which still can be adapted in yourconfig.properties. -
New bean
org.eclipse.scout.rt.security.csp.BlockAllContentSecurityPolicywhich by default blocks all. It can be used as starting point to create a policy as restrictive as possible, by selectively opening directives. -
The CSP
ConfigPropertyclasses have been moved fromorg.eclipse.scout.rt.server.commons.ServerCommonsConfigPropertiestoorg.eclipse.scout.rt.security.csp.ContentSecurityPolicyConfigProperties. -
org.eclipse.scout.rt.server.commons.servlet.HttpServletControl.HTTP_HEADER_CSPhas been moved toorg.eclipse.scout.rt.security.csp.ContentSecurityPolicy.HTTP_HEADER. -
org.eclipse.scout.rt.server.commons.servlet.HttpServletControl.CSP_REPORT_URLhas been moved toorg.eclipse.scout.rt.security.csp.ContentSecurityPolicy.REPORT_URL. -
org.eclipse.scout.rt.server.commons.servlet.HttpServletControl.HTTP_HEADER_CSP_LEGACYhas been removed as it was only used by legacy browsers no longer supported.
Content Security Policy Migration
-
Responses to REST resources now include a
BlockAllContentSecurityPolicyby default. This prevents possible attacks if the response is of typetext/html,image/svgortext/javascript(which would be interpreted by a browser).If you need REST responses to be interpreted by the browser, you have to apply your own CSP header with your rules to the response. If the header is already present, the default header is not added.
-
If you manually (without using
$.injectScript) load new JavaScript code: Consider migrating to$.injectScriptor add thenonceattribute where necessary. The current value can be retrieved on the Scout App:App.get().nonce. -
If you use an
AbstractHtmlFieldorAbstractHtmlTilethat contains inline JavaScript code, thesescripttags require thenonceattribute to be executed.The value can be obtained:
-
In Scout Classic by using
org.eclipse.scout.rt.shared.ui.webresource.SessionNonce.provide(). -
In Scout JS from the App:
App.get().nonce. -
In the JSON layer from the UiSession:
org.eclipse.scout.rt.ui.html.IUiSession.getNonce().
-
-
'unsafe-inline': If you did use the CSP expression'unsafe-inline': This expression is ignored by browsers if nonces are used. Therefore, this CSP expression can be removed. Instead, add thenonceattribute to your inlinescripttags as described above. -
External
scripttags in your entrypoint html files: If you use hardcodedscripttags in your entrypoint html files (instead of usingscout:scriptse.g. to point to an external script), add the following attribute:nonce="scout:nonce". This expression will then be replaced with the correct nonce automatically.
New Features
-
If you load content to
AbstractBrowserFieldby using aBinaryResource: Until now the CSP of the resources loaded into theBrowserFieldused the same CSP as the Scout application itself (this is still the case, but as the policy is more restrictive now, scripts from the Scout server are no longer automatically accepted).Now you have more control: The
AbstractBrowserFieldnow allows configuring the CSP for each instance and resource. It is recommended to use specific CSP rules for such fields which should be as restrictive as possible.As a starting policy the new
BlockAllContentSecurityPolicycould be used and then opening directives as necessary. The created policies can be applied to a field in e.g. theexecInitFieldmethod by using the following methods:-
setContentSecurityPolicy: One CSP for the whole field (all resources of the field). -
putContentSecurityPolicy: A CSP for a specific resource of the field.
-
-
The
ConfigurableContentSecurityPolicyis more flexible now. It is recommended to harden your CSP with these new features:-
As in older releases it can still be configured using the config property
scout.cspDirective. Directives added to this property completely replace the hard-coded directive coming from the Scout defaults and should be configured as minimal as possible (same as in older releases). -
A second config property
scout.cspDirectiveAppendwas added. Its directives do not replace but append instead. It may append to the Scout defaults (if nothing is configured) or to the ones configured usingscout.cspDirective.This allows to e.g. set some always-valid directives in the
scout.cspDirectiveproperty within theconfig.propertiesfile and then adding more expressions to a directive e.g. using an environment variable for specific installations. -
For both properties it can be specified for which html entry point the directive is valid by using a suffix. Example:
# directive valid for all entry points scout.cspDirective[script-src]=https://my.cdn.org/ # additional url only for login.html scout.cspDirective[script-src#login.html]=https://login.cdn.org/
To set this value as environment variable it is required to use the JSON synthax as explained in the Technical Guide.
-
-
If you need to change the response of a resource (e.g. to finetune its CSP response header), the new interface
org.eclipse.scout.rt.ui.html.res.loader.WebResourceLoader.IWebResourceResponseInterceptorContributorcan be implemented. Such contributors are called for each web resource loaded and return a list oforg.eclipse.scout.rt.server.commons.servlet.cache.IHttpResponseInterceptorfor a request. These interceptors are then called before sending the response to the client. You can e.g. identify a request withresponseObject.getCacheKey().getResourcePath().