Self-Managed Commerce 8.8.x Release Notes
Learn about changes to Self-Managed Commerce for this release. Fixes since the release are summarized in the changelog.
Changelog
The changelog contains the list of fixes and improvements made to Self-Managed Commerce 8.8 since its release date. To learn how to consume the updates, see Consuming Support Fixes.
| Commit | Description | Badges | Release Date |
|---|---|---|---|
| f9b31a5e | Upgraded Spring Security from 6.5.10 to 6.5.11 to address multiple vulnerabilities (fix for previous commit). | Security | 8‑Jul‑2026 |
| 05afaeb9 | Upgraded Spring Security from 6.5.10 to 6.5.11 to address multiple vulnerabilities. | Security | 7‑Jul‑2026 |
| 2578859c | Upgraded Netty from 4.1.133.Final to 4.1.135.Final to address CVE-2026-45416, CVE-2026-50010, and CVE-2026-44249. | Security | 7‑Jul‑2026 |
| 521e6902 | Upgraded Spring from 6.2.18 to 6.2.19 to address multiple vulnerabilities. | Security | 6‑Jul‑2026 |
| 18f0d5a1 | Upgraded Shiro from 1.13.0 to 2.2.1 to address CVE-2026-23901, CVE-2026-43828, and CVE-2026-49268. | Security | 2‑Jul‑2026 |
| 2058cbbd | Upgraded certified PostgreSQL version from 16.10 to 16.14. | Security | 27‑Jun‑2026 |
| a1a5104b | Upgraded certified Oracle version from 19.0.0.0.ru-2025-10.rur-2025-10.r1 to 19.0.0.0.ru-2026-01.rur-2026-01.r3. | Security | 27‑Jun‑2026 |
| e0b8a266 | Validation warnings now appear in the promotion wizard for currency, shipping service level, product attribute, SKU attribute, and cart item modifier fields when an unrecognized code is entered. | 26‑Jun‑2026 | |
| c86ee86b | Fixed an issue where cart recurring cost totals were calculated incorrectly when multiple subscription items with different agreement lengths had overlapping billing periods, including rollover scenarios. | 26‑Jun‑2026 | |
| e93e7a9d | Update default branch to only contain a README | 28‑Jul‑2025 | |
| c80abc22 | The Commerce Manager test-util module no longer uses PhantomJS to run JavaScript tests, fixing build failures on systems with OpenSSL 3.x (such as Debian Trixie); tests now run via HtmlUnit and JUnit. | 26‑Jun‑2026 |
Badge legend
- Security: Indicates that the patch includes security fixes.
- Performance: Indicates that the patch improves system performance.
- Data model changes: Indicates that the patch includes Liquibase scripts that make changes to the data model.
- Requires downtime: Indicates that the Self-Managed Commerce services should be shut down while the Data Population Tool is executed.
- Build Tools: Indicates that the patch includes changes to Build Tools.
8.8.0
Released: June 2026
Release highlights
Recurring pricing
Support has been added to allow business users to define subscription-style pricing — such as weekly, monthly, quarterly, or annual billing — alongside existing one-time (up-front) pricing. Shoppers can be given the option to choose from different recurring billing options or to pay up front when adding an item to their cart. New Cortex APIs have been added to return the estimated recurring charges for all items in the shopping cart.
A new Agreement domain model has been introduced to enable recurring pricing for products on the Self-Managed Commerce platform. Each Agreement
captures key contract details including interval type, billing frequency, agreement length, end behaviour (ROLLOVER or EXPIRE), and
whether the subscription may be paused or cancelled.
Agreements can be optionally associated with both products and price lists. Price list base amounts have been extended with two new fields —
recurring_list_price and recurring_sale_price — which are only valid when an agreement is linked to the price list. Recurring prices support
context-based variation just like up-front prices, allowing flexible selling scenarios.
Cortex now exposes recurring pricing information on cart line items and on the overall cart total. For each line item, both the unit recurring list price and purchase price are displayed. For the cart total, recurring costs are aggregated across all applicable line items. Prices are organized by billing interval (for example, monthly or every three months) and broken down into period ranges with start and end points. Prices that apply beyond the end of an agreement term are flagged as rollover and estimated prices.
Commerce Manager users can create new Agreements using a dedicated Create Agreement wizard. The wizard is accessible via a Create Agreement button in both the main Price List Management toolbar and the Agreements search results view pane toolbar. Users can also associate Agreements with Products and assigned Product Bundles through a new Agreement Association tab in the Product and Product Bundle editors.
For more information see Recurring Pricing.
note
Currently, shoppers will be blocked from completing checkout if their cart contains line items associated with an agreement. When such items are
detected, the purchase form will display a structured error message with the ID cart.contains.line.item.associated.to.agreement. This is a temporary
safeguard put in place because recurring/subscription billing fulfillment is not yet fully supported. For businesses with a
backend billing system, the AgreementLineItemShoppingCartValidatorImpl validator can be disabled.
A future release of Self-Managed Commerce will provide support for recurring billing of purchases with line items associated to agreements.
Optional dependent items
Merchants can now configure Optional Dependent Item product associations, allowing suggested dependent products to be presented to shoppers during add-to-cart operations. Unlike the existing "Auto Dependent Item" association (which adds items to the cart automatically), optional dependent items are displayed as choices that shoppers can explicitly add or remove. This gives merchants greater flexibility in cross-sell and upsell scenarios without forcing unwanted items into the cart.
Bundle products are not supported as the source product for optional dependent associations. This restriction is enforced in the Commerce Manager UI (the "Optional Dependent Item" tab is hidden when editing a bundle product) and during data import.
For more information see Optional Dependent Items.
Deferred customer and shopper record creation for single-session users
Previously, every public access token request resulted in the immediate creation of a single-session customer record in the database. This allowed bots and web scrapers that only checked product availability to generate millions of customer records per day, overwhelming the scheduled cleanup jobs. Customer and shopper records for single-session (anonymous/public) users are now created lazily — only when a resource that actually requires them (such as a cart or profile) is first accessed. Users who only browse navigations, offers, categories, or prices will no longer have database records created on their behalf.
note
Any client lookup request to the /carts/{scope}/default resource will result in a customer and shopping cart record being created. Since many eCommerce sites include a cart icon that shows the number of items in the cart, your front-end may be making this request on every page load.
Therefore, we recommend that you add logic on your front-end to avoid making this call for anonymous shoppers until a known add-to-cart operation has been done. A flag could be stored in browser local storage to determine if the cart count lookup is required.
New promotion conditions for cart item modifiers
Two new promotion conditions have been added to the Self-Managed Commerce promotion engine, enabling merchants to create promotions that trigger based on cart item modifier fields and their values.
The cart-level condition (Line item with cart item modifier [] having value [] is in the shopping cart) evaluates whether any line item in the
shopping cart has a specific cart item modifier field set to a specified value.
The item-level condition (Line item cart item modifier [] has value []) evaluates individual line items, enabling per-item discounts to be
applied only to those line items that have the specified modifier field and value.
For more information see Promotion Rule Conditions.
Support for nested AND/OR condition groups in promotion configuration
Promotion rules can now use nestable AND/OR condition groups to express complex boolean logic for conditions. Previously, all conditions on a
promotion were evaluated using a single flat AND or OR operator. With this change, conditions can be organized into a tree structure — for example, a
promotion can fire when (Brand is X AND quantity > 2) OR (Brand is Y AND quantity > 2 AND (Color is Red OR Color is Yellow)). This unlocks significantly
more expressive and targeted promotional logic without requiring custom extensions.
The Commerce Manager promotions editor also now supports these more complex nested promotion conditions. Merchants can create
condition groups with AND/OR operators, nest groups within groups, add or remove conditions at any level of the hierarchy, and switch operators
between AND and OR using drop-down controls. The hierarchical structure is displayed using indented, bordered containers with alternating background
colors to make nesting depth easy to read. An error is shown if a group is left empty, preventing the rule from being saved in an invalid state.
Import/export support has been updated to handle condition groups. Promotions exported from or imported into the system will reflect the full
condition group tree using nested <and> and <or> XML elements.
For more information see Promotion Rules.
Advanced time conditions for promotions and price list assignments
Merchants can now create promotions and price list assignments that activate only during specific, recurring time windows — going well beyond simple start/end date ranges. Supported patterns include hour-of-day windows (e.g., happy hours from 5–7 PM), day-of-week restrictions (e.g., weekend-only sales), day-of-month targeting (e.g., payday specials on the 1st and 15th), specific date inclusion or exclusion (e.g., Black Friday, excluding holidays), and custom interval-based recurrence (e.g., every 3 days from a given start date).
To support this, Commerce Manager now provides a dedicated Time Conditions configuration page for both promotions and price list assignments. Merchants can choose between keeping a promotion or price list assignment active throughout its entire date range (the default behavior) or restricting activity to specific time windows. When specific time windows are selected, merchants can add one or more windows using an intuitive dialog that supports scheduling by days of the week, days of the month, specific dates, or recurring intervals, combined with flexible time-of-day ranges. Exceptions such as excluded weekdays or specific blackout dates can also be added to each window. Configured windows are displayed as at-a-glance summary cards.
For more information see Promotion Rules.
Ability for Buyers to view and edit shared account carts
Buyers associated with the same account can now view and edit all shopping carts belonging to that account, enabling collaborative purchasing
workflows within B2B account hierarchies. Access is governed by role-based permissions: users with the OWNER Shiro role can read and browse account carts,
while the new MODIFY_CARTS Shiro role grants full create, read, update, and delete access to carts within an account.
A new carts sub-resource has been added to the accounts API ({account}/carts), allowing buyers to list and access all active carts associated with
their account. Cart descriptor responses now include an owner field containing the email address of the buyer who originally created the cart,
making it easier to identify cart ownership in multi-buyer scenarios.
For more information see Read carts from account.
Peak Mode: Pause non-critical batch jobs during high-traffic events
A new "peak mode" capability has been introduced that allows operators to temporarily disable non-critical background batch jobs during peak
transactional periods (e.g., product launches or promotional events). This ensures that system resources are fully available for order processing
rather than being consumed by cleanup and maintenance tasks. When active, non-critical jobs such as abandoned cart cleanup, anonymous customer purge,
OAuth2 token cleanup, import job cleanup, data point processing, and others are skipped automatically. Critical jobs — including shipment release (
releaseShipmentsJob), inventory journal rollup (inventoryJournalRollupJob), and outbox message relay (relayOutboxMessagesJobInvoker) — are never
paused and continue to run normally.
A Job Pause Settings screen has been added to the Configuration section of Commerce Manager, enabling administrators to enable and pre-schedule the job pause functionality. The UI supports pausing immediately for a preset duration (15 minutes, 30 minutes, 1 hour, 2 hours, 4 hours, or 8 hours), scheduling a pause to begin at a future date and time, pausing indefinitely until manually resumed, and cancelling or modifying an active or scheduled pause. Current pause status, start time, and expiration time are displayed in the user's local timezone, and the screen auto-refreshes every 60 seconds to reflect the latest state.
Access to the Job Pause Settings screen is controlled by a new permission, ADMIN_JOBS_PAUSE_MANAGE. Administrators who should be able to manage job
pauses must be assigned a role that includes this permission. Teams that define their own Commerce Manager user roles should review these roles to
determine whether ADMIN_JOBS_PAUSE_MANAGE should be granted.
Integration Server REST API for Shipping Notifications
A new REST endpoint has been added to the Integration Server to allow external systems to notify Self-Managed Commerce when a shipment has been
shipped. Previously, the only supported mechanism for completing a shipment — which triggers payment capture and updates the order status to
COMPLETE — was through Commerce Manager, which was impractical for enterprise-scale operations and typically led customers to build custom
integrations.
The new POST /shipping/v1/shipments/complete-shipment endpoint accepts a shipment number and an optional carrier tracking number, and is secured
with HTTP Basic authentication.
The API is designed with idempotency in mind: if a shipment has already been completed (e.g., due to a duplicate or concurrent request), the endpoint
returns a 409 Conflict response rather than an error, allowing calling systems to safely retry without risk. Standard error responses are returned
for invalid requests (400), shipment not found (404), and unexpected failures (500). An OpenAPI/Swagger specification is available at
/shipping/v1/shipments/api-docs.
For more information see Shipment Completion API.
AI coding assistant context
An AGENTS.md file and a suite of supplementary AI context guides have been added to the ep-commerce repository to help AI coding tools (such as
GitHub Copilot, Claude, and similar assistants) understand the platform's structure, conventions, and best practices. The guides cover coding
standards, extension approaches (Extension Modules and the Extension Point Framework), Cortex REST API patterns, performance guidelines, testing
practices, and how to search the codebase effectively.
For customer implementation teams, the documentation reinforces which areas of the codebase are safe to modify and how to use extension mechanisms to maintain upgrade compatibility. It also provides quick-reference patterns for entities, services, Spring configuration, data mappings, Liquibase schema changes, and more. These files are intended to reduce onboarding friction, improve AI-assisted code generation quality, and promote consistent implementation patterns across both core and extension development.
Automatic IntelliJ IDEA resolution of Eclipse P2 plugin dependencies for Commerce Manager
Developers working on Commerce Manager customizations in IntelliJ IDEA no longer need to manually configure Tycho/Eclipse P2 dependencies so that Commerce Manager dependencies are resolved. Previously, this required a complex and error-prone setup process documented in a separate support article. Eclipse RAP and other P2 plugin classes are now resolved automatically when the project is opened in IntelliJ.
To support this, three new Maven modules have been added under commerce-manager/cm-modules/eclipse-p2-platform: a feature module declaring all
required Eclipse P2 plugins, a repository module that packages them into a P2 repository ZIP, and an intellij-support module that unpacks those
plugin JARs and aggregates their classes into a single Uber JAR. This Uber JAR is wired into the project using a Maven profile (activeInIdea) that
activates automatically in IntelliJ IDEA environments, using system scope for reliable resolution.
Developers who have customized Commerce Manager plugins (including extensions under ext-cm-modules) will benefit from this change automatically, as
the activeInIdea profile has been applied to both the core cm-plugins and the ext-plugins modules. No changes to existing customizations are
required, and the standard Maven build is unaffected.
Customizable Checkstyle suppressions for extensions modules
A new Checkstyle suppressions file has been introduced specifically for code under the extensions folder
(extensions/code-checking-rules/src/main/resources/rulesets/suppressions/checkstyle-elasticpath-extensions.xml). This separates the code quality
enforcement between the core Elastic Path Product team and project team customizations, allowing the Product team to introduce stricter Checkstyle
rules in the platform without inadvertently breaking builds for extension code.
Project teams can now tailor Checkstyle enforcement for their custom code by modifying this suppressions file — adding suppressions to relax rules or removing them to enforce stricter standards. To minimize upgrade conflicts, custom suppressions should be added in the designated section of the file, below the comment marked for project team use.
Added ast-grep recipes for structured search and replace during patching and upgrades
The Self-Managed Commerce source code repo now includes a new folder structure for automated ast-grep upgrade recipes. These recipes are designed to automatically transform customer customization code when upgrading between platform versions, significantly reducing the manual and AI effort required when breaking changes are introduced — such as migrations to Jakarta EE, Spring 6, or JUnit 5.
The new upgrade/recipes/<version>/ directory structure organizes transformation recipes by target version, with each recipe defined as a flat YAML
file. An AI recipe authoring guide (ai/ast-grep-recipes.md) has also been added, documenting tested patterns for Java and XML code transformations,
critical authoring rules (e.g., uppercase metavariable names, atomic single-line fix templates), design principles, and debugging techniques.
These recipes are read and executed by the Self-Managed Commerce Upgrader Tool when running in AI Assist Mode. These transformations are executed before Claude attempts to fix any issues, so that relatively simple transformations can be completed without unnecessary AI token use.
PromoIQ: Externalized promotions APIs
New REST API endpoints have been introduced in the ep-promoiq-api Integration Server module to expose the PromotionsCalculator extension
point. These APIs enable external promotion engines to integrate with the Self-Managed Commerce platform by delegating promotion
evaluation, rule retrieval, and coupon management operations over HTTP.
The following capabilities are now available via REST:
- Evaluate promotions for catalog items and shopping carts
- Retrieve promotion rules by GUID
- Look up coupons by GUID or coupon code
- Retrieve applicable coupon codes for a customer and store
- Validate coupon rule and usage for checking suspension status and remaining uses
- Trigger actions at checkout for executing actions on applied promotions during the checkout process
- Disable coupon auto-apply for a customer's cart
An OpenAPI specification (v1.0) is available for all PromoIQ REST APIs, accessible by calling the GET /promoiq/v1/promotions/api-docs endpoint.
A new embedded Extension Point Framework extension, PromoIQPromotionsCalculator, has been introduced to support delegating promotion evaluation to
the PromoIQ APIs running on a separate instance. This extension implements the PromotionsCalculator extension point and handles all key promotion operations.
This enables merchants to offload complex promotion logic to a separate Self-Managed Commerce environment rather than relying on the built-in
promotion engine.
A new system configuration setting COMMERCE/SYSTEM/PROMOIQ/enable (defaulting to false) has been introduced to gate access to the PromoIQ
promotion evaluation REST APIs. When disabled, all PromoIQ API requests return an HTTP 403 with the message PromoIQ feature is disabled.
For more information see PromoIQ API.
note
Use of the PromoIQ APIs requires a separate license for production use — contact your Customer Success Manager for details.
Java 21
Self-Managed Commerce now requires a Java 21 JDK for builds and a Java 21 JRE at runtime.
Supporting Java 21 provides several benefits:
- Improved security: Many security updates have been added between Java 17 and Java 21.
- New language features: Many significant changes have been made to the JDK to benefit developers.
Additionally, the Java 21 upgrade required us to update many library dependencies to newer versions that provide Java 21 support. These upgrades further improve security and stability of the application.
For more information about upgraded dependencies, see Dependency Changes.
Multiple extension point framework improvements
See the Extension Point Framework release notes.
Fixed issues
Core
Replaced deprecated ServiceMix dependencies with Elastic Path-maintained wrapped bundles
The Apache ServiceMix project has been retired and will no longer release new versions. To ensure
long-term supportability of the Self-Managed Commerce platform, the ServiceMix bundle dependencies have been removed and replaced with custom
OSGi-wrapped bundles created and maintained by Elastic Path. These new bundles are published under the Maven group ID com.elasticpath.wrappedbundles
and cover key libraries including Spring Framework modules, AspectJ, EhCache, ANTLR, and Commons Collections.
Improved promotion category exclusion handling for products in overlapping category hierarchies
When configuring a promotion condition such as "at least 1 item from category A, excluding items from subcategory B," products assigned to both the parent category A and the excluded subcategory B are now correctly treated as eligible for the promotion. Previously, such products were incorrectly excluded, preventing the promotion from applying even though the product was directly assigned to the intended included category. Products that belong to an excluded category that is not part of the included category hierarchy remain ineligible as expected.
For example:
Given the following category structure:
,--------------.
|Category T1_L1|
|--------------|
`--------------'
|
,--------------. ,--------------.
|Category T1_L2| |Category T2_L1|
|--------------| |--------------|
`--------------' `--------------'
| |
,--------------. ,--------------.
|Category T1_L3| |Category T2_L2|
|--------------| |--------------|
`--------------' `--------------'
Assume that we have the following products:
- ProductX which belongs to categories
T1_L1andT1_L3. - ProductY which belongs to category
T1_L3only. - ProductZ which belongs to categories
T1_L3andT2_L2.
And assume we have the following cart promotions:
- ExcludedCategoryTestPromotion:
- Condition:
[At Least][1]items of category[T1_L1]are in the shopping cart, excluding items of category[T1_L2] - Action: Get
[50]% off[1]items in category[T1_l1], excluding items of category[T1_L2]
- Condition:
- ExcludedCategoryTestPromotion2:
- Condition:
[At Least][1]items of category[T1_L1]are in the shopping cart, excluding items of category[T2_L1] - Action: Get
[10]% off[1]items in category[T1_l1], excluding items of category[T2_L1]
- Condition:
Then the promotions will apply as follows:
- ExcludedCategoryTestPromotion promotion applies to ProductX because it is assigned to included category
T1_L1, and the excludedT1_L3category is ignored because it is a descendent. - ExcludedCategoryTestPromotion promotion does not apply to ProductZ because it is assigned to category
T1_L3, which is a descendent of excluded categoryT1_L2. - ExcludedCategoryTestPromotion2 promotion applies to ProductY because it is assigned to category
T1_L3, which is a descendent of categoryT1_L1. - ExcludedCategoryTestPromotion2 promotion does not apply to ProductZ because it is assigned to category
T2_L2, which is a descendent of excluded categoryT2_L1.
Fixed several issues that were causing InvalidStateException to be thrown
Intermittent InvalidStateException: The context has been closed exceptions were being thrown in several Self-Managed Commerce services, especially
under high load.
One cause was that several JPA query executor classes (NamedQueryWithListExecutor, NamedQueryExecutor, DynamicQueryExecutor, and
JpaPersistenceEngineImpl) were casting JPA Query objects to OpenJPAQuery via OpenJPAPersistence.cast() in order to use the setParameters()
convenience method. This cast forced Spring's DeferredQueryInvocationHandler to immediately materialize the underlying EntityManager. When no
transaction-bound EntityManager was available, Spring created a temporary one, used it to create the query, then closed it — leaving the query
referencing a closed broker and causing the subsequent setParameter() call to fail. This was fixed by removing all uses of
OpenJPAPersistence.cast() from query executor classes and replaces OpenJPAQuery.setParameters(Object[]) and OpenJPAQuery.setParameters(Map) with
standard JPA positional and named parameter binding via Query.setParameter(int, Object) and Query.setParameter(String, Object). A new utility
method, JPAUtil.setQueryParameters(), centralizes this logic. By retaining the standard JPA Query proxy, Spring defers EntityManager
materialization until getResultList() or executeUpdate() is called, at which point a transaction-bound or freshly allocated (and properly scoped)
EntityManager is used for the full query lifetime.
Another cause was that StrictDetachmentStrategyImpl, which detaches entities before storing them in the cache, was not replacing OpenJPA
proxy collections and maps with plain Java equivalents. These proxy objects retained internal references to the JPA StateManager and Broker, which
became invalid after the transaction closed. When property change listeners (e.g., ProductImpl.propertyChange) later operated on these proxy
collections, OpenJPA would assert the broker was still open and throw the exception. To fix this, StrictDetachmentStrategyImpl was updated to
replace all OpenJPA proxy Collection and Map fields with standard Java collections (ArrayList, HashSet, or HashMap) via the corresponding
setter methods during the detachment process.
The third cause was that JPA entities were being placed into EhCache while still attached to an OpenJPA state manager. When the database transaction ended and the underlying broker was closed, any subsequent read of those cached entities would fail. The fix ensures that entities are detached from the OpenJPA persistence context before being stored in any EhCache-backed cache.
Simplified EhCache Spring XML configuration via custom ep-caches:cache namespace
A new custom Spring XML namespace (ep-caches:cache) has been introduced to streamline the declaration of EhCache-backed caches. Previously, each
cache required two separate Spring bean definitions — one to configure the underlying EhCache instance (EhCacheDefaultConfigurationFactoryBean) and
one to create the EP cache wrapper via localCacheFactory. These can now be replaced with a single, concise XML element, for example:
<ep-caches:cache id="taxCodeByCodeCache" timeToLive="3600" timeToIdle="3600" maxEntries="10000"/>
For more information, see the related upgrade notes.
JDBC drivers removed from webapps
The H2 database driver JAR (h2-2.2.224.jar) was unintentionally included in the ext-integration-webapp and ext-sync-webapp web assembly files.
This occurred because the ep-sync-message-listener-email and ep-sync-message-listener-camel modules declared the H2 dependency with the default
compile scope rather than test scope. JDBC drivers should be provided at the container (Tomcat) level rather than bundled inside the webapp, so this
represents both a security concern and a packaging issue.
The H2 dependency in the affected modules has been corrected to test scope, ensuring it is no longer included in the packaged webapp artifacts.
Additionally, all supported JDBC drivers (H2, MySQL, Oracle, PostgreSQL) are now explicitly provided on the Tomcat classpath via the Cargo container
configuration in the root POM.
A Maven enforcer rule (enforce-banned-dependencies-for-webapp) has been added to all webapp modules to prevent JDBC drivers from being accidentally
bundled into webapp assemblies in the future.
Cortex
Zoom graph builder removed from Cortex Studio
The Zoom Graph Builder tab and all associated functionality have been removed from Cortex Studio. This feature allowed developers to visually explore Cortex API zoom paths via an interactive graph, but it contained known bugs and was rarely used.
Custom request header support in Cortex Studio
Cortex Studio now allows users to define custom HTTP headers that are sent with every API request. A new Custom Headers section has been added to the Request Headers tab, where users can add headers by providing a header name and value, clear individual header values, or remove headers entirely.
Custom header definitions and their values are persisted in the browser's local storage, so they are retained across browser sessions — consistent with how standard header values are already preserved. This makes it easier for developers and testers to work with APIs that require non-standard or environment-specific headers without needing to re-enter them each session.
Added limited Shopping Cart caching for improved performance
A new cache has been introduced for some shopping cart operations with values that are not expected to change frequently.
The findOrCreateDefaultCartGuidByShopper method in ShoppingCartServiceImpl is now cached using a shopper GUID → shopping cart GUID cache (
defaultCartGuidByShopperGuidCache). This eliminates redundant database queries for default cart lookups on every shopper session interaction,
providing measurable performance improvements under load. The cache has a default TTL of 60 minutes and is invalidated automatically through
message-based events. Cache invalidation is triggered when a shopping cart is created, deactivated, or deleted — including the new
deactivateAllShoppingCartsByShopperGuid method, which replaces the now-deprecated deactivateAllShoppingCartsByShopperUid. Cart events now carry a
shopperGuid field in their event data to enable targeted cache invalidation. A new CacheEventType.SHOPPER_DEFAULT_CART event type and a
corresponding ShopperDefaultCartCacheInvalidationProcessorImpl have been introduced to handle invalidation across nodes.
Additionally, the findAccountGuidByCartGuid method in ShoppingCartServiceImpl is now cached using a shopping cart GUID → account GUID cache (
accountGuidByCartGuidCache). This eliminates redundant database queries for account resolution operations. The cache has a default TTL of 60 minutes
and is invalidated automatically through message-based events.
Promotion rule base cache now avoids unnecessary database reloads
Previously, the Drools promotion rule base cache had a 5-minute TTL, causing the full rule base to be reloaded from the database on every cache expiry — even if nothing had changed. Because rule base records can be very large, this resulted in costly and unnecessary database reads that degraded promotion evaluation performance.
This fix introduces a two-tier caching strategy: the rule base itself is now cached eternally, while a separate, shorter-lived "freshness indicator" cache tracks when the last-modified date was verified. When the freshness indicator expires, a lightweight query fetches only the last-modified date for the rule base. The full rule base blob is reloaded from the database only if the date has actually changed.
Promotion selling context conditions evaluated when adding coupon codes to cart
Previously, shoppers could add coupon codes to their cart even if they did not meet the promotion's selling context conditions (such as belonging to a required customer segment). The coupon would be silently accepted but would never apply, providing no feedback to the shopper. With this change, the platform now validates selling context conditions at the time a shopper adds a coupon code to the cart and returns a clear error if the shopper does not qualify.
When a coupon code is rejected due to unmet selling context conditions, the API returns a structured error response with the coupon.not.valid error
ID, the coupon code, and a validation-failure-code of ERROR_SELLING_CONTEXT_CONDITIONS_NOT_SATISFIED. Only Groovy selling context conditions are
evaluated during this check; Drools conditions are not. If a coupon code is associated with multiple promotions, each promotion's selling context is
evaluated independently.
Commerce Manager
Commerce Manager platform modules can now access ext-core services directly
Commerce Manager modules have been updated to allow direct access to ext-core classes and services at runtime and compile-time. Previously,
developers who needed Commerce Manager modules to interact with custom ext-core services were forced to copy entire Commerce Manager modules into
extensions/cm/ext-cm-modules and modify the configuration to use those copies. This workaround is no longer supported since an upgraded version of
Tycho causes build-time failures ("Duplicate reactor project IUs" errors) when multiple modules share the same artifact ID.
With this fix, customers can integrate ext-core customizations directly into the standard commerce-manager/cm-modules/cm-plugins modules without
needing extension copies. Customers who have previously applied the copy-module workaround must migrate their customizations back into the
corresponding platform CM modules and delete the copied modules from extensions/cm/ext-cm-modules as part of the upgrade process.
Technically, this was achieved by adding DynamicImport-Package: com.elasticpath.extensions.* to all CM bundle manifests, explicitly declaring
platform package imports in ext-cm-libs, adding Require-Bundle wiring for platform OSGi bundles, and enforcing build-time reactor ordering to
ensure ext-cm-libs is built before Tycho resolves plugin dependencies. A Maven enforcer rule was also added to prevent ep-messaging-camel from
entering the ext-cm-libs dependency tree, which can cause Commerce Manager startup delays of several minutes.
"Not Set" option added for optional boolean customer profile attributes
Commerce Manager now supports distinguishing between an unset boolean customer profile attribute and one that has been explicitly set to a value.
Previously, optional boolean fields (such as HTML Email and Newsletter preferences) displayed "No" regardless of whether the value was absent or
had
been explicitly set to false, making it impossible to tell the difference.
Optional boolean fields now render as a dropdown with three choices: "Not Set", "Yes", and "No". When a customer profile is loaded, fields with no stored value will display "Not Set". When a user saves a record with "Not Set" selected, the underlying customer profile attribute value record is removed entirely, ensuring a clean and accurate data state.
Attribute value editor now accessible in read only mode for locked products, SKUs, and categories
When changesets are enabled (COMMERCE/SYSTEM/CHANGESETS/enable=true), Commerce Manager previously prevented users from opening the attribute value
editor for products, SKUs, or categories that had not yet been added to a changeset (i.e., items in a "locked" state). Users are now able to open the
attribute value editor in read-only mode by double-clicking an attribute value in the Attributes tab, making it easier to review attribute data
without needing to add the item to a changeset first. Note that simply selecting (highlighting) an attribute row will not enable the Edit Attribute
Value… button.
When the editor is opened in read-only mode, all controls are appropriately restricted: the OK button is disabled; Boolean fields display a disabled combo box; text-based fields (Short Text, Long Text, Integer, Decimal, File, and Image) are read-only but allow text selection and copying; Date and Date/Time fields are read-only with the calendar icon disabled; and for multi-value attributes (Short Text Multi-Value, Long Text Multi-Value), the Add Value, Edit Value, and Remove Value buttons are all disabled.
New DRL Code tab added to promotion editors in Commerce Manager
A new read-only DRL Code tab is now available in both cart promotion and catalog promotion editors in Commerce Manager. The tab displays the
underlying Drools rule language code that is generated from the promotion's configured conditions and actions, with syntax highlighting applied for
readability. A Copy to Clipboard button is included so developers can easily extract the code for further analysis.
This feature is primarily useful for developers who are debugging custom promotion conditions or actions, as it allows them to inspect the generated rule code directly within Commerce Manager without requiring access to backend systems or logs. The Drools rule language code is generated from the current saved state of the promotion; unsaved promotions will display a message indicating that the promotion must be saved before code can be shown.
Promotion conditions and actions editable without catalog data in database
Promotion conditions, actions, and exclusions in Commerce Manager can now be viewed and modified even when the associated catalog data — such as products, product SKUs, categories, brands, currencies, attributes, and shipping service levels — is not present in the Promotions database. This is particularly relevant for deployments where catalog data is managed separately from the Promotions service.
Fields that previously relied on database-backed dropdowns or combo boxes now present a text input alongside a [select] link. Users can either
type the identifier code directly into the text field or use the [select] link to open a new generic list selection dialog, which displays
available options and supports filtering by code or name. Category code fields require the compound format categoryCode|catalogCode, and validation
provides a specific error message if the format is incorrect.
Inline validation warnings for invalid promotion condition codes
When building promotion rules in Commerce Manager, users can now see an immediate inline warning when a condition references a product, SKU, category, or brand code that does not exist in the database. The warning appears as an amber icon next to the condition field as soon as the user moves focus away, and a tooltip displays the full message (for example, "Product 'INVALID_PROD_001' was not found in the database"). The warning is non-blocking, meaning users can continue editing and saving the promotion without any extra steps.
This change helps prevent promotions that silently fail to apply due to typos or references to deleted catalog items, making it easier to diagnose promotion configuration issues before they reach customers.
Brand is now optional on products and product bundles
Previously, a brand was required when creating or editing a product or product bundle. This requirement has been removed — brand is now an optional field. Commerce Manager wizards and editors have been updated to include an empty option in the brand selection dropdown, allowing merchants to create products and bundles without specifying a brand, and to remove a brand from existing products or bundles.
Import/export has also been updated to support products where no brand is specified. An empty <brand> element in an import file is now treated as no
brand, rather than causing an error. Search indexing already handled null brand values and required no changes.
A database migration is included that removes any existing brand records with the code "None" (case-insensitive) and sets the brand field to null on any products that previously referenced those records. Customers who have used a "None" brand as a placeholder should be aware that this migration will remove those records automatically on upgrade.
Export search results to CSV from Commerce Manager list views
Commerce Manager now includes an Export List button on the following search result list views: shopping cart promotions, catalog promotions, price lists, price list assignments, products, SKUs, orders, customers, and accounts. Clicking the button downloads a CSV file containing all rows that match the current search criteria, not just the items visible on the current page. The exported file includes a UTF-8 byte order mark so that it opens correctly in Microsoft Excel without character encoding issues.
Ability to switch shopping cart promotion activation mode without recreating the promotion
Merchandisers can now change the activation mode of an existing shopping cart promotion — between no coupon, public coupon, and private coupon — directly from the promotion editor, without needing to delete and recreate the promotion. Previously, the "Activation Rules" and "Coupon Codes" tabs were only visible on promotions that already had a coupon configuration, making it impossible to add coupon activation to a promotion after it was created.
The "Activation Rules" tab is now always visible and presents all three activation options as radio buttons. If a promotion already has coupon codes associated with it, switching directly between public and private coupon modes is not permitted; users must first switch to "not activated by coupons" and save, which will delete all related coupon codes. A confirmation dialog is shown before any coupon codes are deleted, and the save is blocked if any coupon codes are currently in use on active shopping carts or orders.
Batch Server
Batch server job schedules can now be configured via properties
The scheduled batch jobs on the batch server previously had fixed run schedules defined in the Spring XML configuration file (quartz.xml). Operators
who needed to adjust when jobs ran — for example, to avoid peak traffic periods or align with maintenance windows — had to override the XML
configuration directly.
Cron expression schedule overrides can now be set for each batch job using properties in ep.properties, following the naming pattern
ep.batch.job.<jobName>.cronExpression (for example, ep.batch.job.cleanupAbandonedCarts.cronExpression). If a property is not set, the job
continues to run on its existing default schedule.
For more information, see Batch Server Properties.
Import/Export
GUID Filtering added to Import/Export EPQL queries
The Import/Export feature supports an optional EPQL query clause that allows users to filter which records are included in an export. Previously, most object types did not expose a GUID field as a filterable option, limiting operators to filtering by other attributes such as name or code. GUID fields have now been added as supported filter fields across a wide range of exportable object types, including Price Lists, Price List Assignments, Promotions, Categories, Products, Customers, CM Users, Shipping Service Levels, Shipping Regions, Warehouses, Gift Certificates, and CM Import Jobs.
This enhancement allows operators to export a specific, known record by its GUID using queries such as
FIND PriceListAssignment WHERE GUID = '492c9662-7b9b-4223-afea-da5b12024e6b', which is particularly useful when integrating with external systems or
automating data migration workflows where GUIDs are the primary reference identifiers.
Fixed issue with duplicate TCARTTYPE records created during store imports
Repeated imports of stores via the Import/Export feature were incorrectly creating duplicate TCARTTYPE records in the database instead of updating
existing ones.
The root cause was in StoreDtoAssembler#populateCartTypesForDomain, which always instantiated new transient CartType objects (with no database
identity) during import, causing JPA to issue INSERT statements instead of UPDATEs. Additionally, a flawed equals() implementation on CartType
that compared modifier collections could prevent deduplication from working correctly. The fix updates the assembler to look up and reuse existing
CartType entities by GUID before falling back to creating new ones, and removes the problematic equals()/hashCode() implementation in favor of
identity-based comparison.
A Liquibase migration is included that removes orphaned duplicate TCARTTYPE records from affected databases and adds a unique constraint on the
TCARTTYPE.GUID column to prevent this issue at the database level. Missing indexes and foreign keys on the TSTORECARTTYPE and TCARTTYPEMODIFIERS
tables are also added as part of this migration.
Improved Import/Export error and warning log messages
Previously, warnings and errors logged during Import/Export operations — including during Data Population execution — were output as raw internal
representations such as Message[jobType=<null>,code=IE-10103,params={MobileCatalog},exception=null], which were difficult to interpret without
cross-referencing internal message property files. Example:
[EP-DataPopulation] [INFO] Begin importing CATEGORY
[EP-DataPopulation] [ERROR] Message[jobType=,code=IE-10103,params={MobileCatalog},exception=null]
Import/Export log messages now display fully resolved, human-readable text by leveraging the existing MessageResolver to translate message codes and
parameters at log time. Example:
[EP-DataPopulation] [INFO] Begin importing CATEGORY
[EP-DataPopulation] [ERROR] Catalog with code MobileCatalog does not exist
The Message.toString() method has been updated to use the resolver when available, and LogAppenderUtil has been updated with a
setMessageResolver() method that is called at the start of import and export jobs.
Named import configurations via query parameter
The Import/Export API now accepts an optional configuration query parameter on import requests, allowing clients to select different import
configuration files at runtime. For example: POST integration/api/importexport/import?configuration=insertonly. When specified, the API will use a
configuration file named {configuration}-importconfiguration.xml instead of the default importconfiguration.xml. If the specified configuration
file does not exist, the API will return an error.
This enhancement gives operators greater flexibility when importing data, as different import scenarios may require different behaviors — such as
using an INSERT-only strategy to prevent updates to existing records, or adjusting dependent element handling between CLEAR_COLLECTION and
RETAIN_COLLECTION for elements like product associations or SKU pricing.
Custom import configuration files must be created in advance and placed in the extensions/importexport/ext-importexport-api/src/main/resources
folder.
For more information, see Import endpoint parameters.
Tests
New functionality for interacting with RAP widgets in Selenium test step definitions
Several new RAP test wrapper components — including RAPTable, RAPCombo, RAPText, RAPButton, and others — have been added to the Commerce
Manager test utilities, alongside a new AbstractRAPWidget base class to reduce code duplication across the growing library of test widgets. These
additions provide a consistent and simplified API for interacting with UI elements in automated tests.
The new WidgetBy and WidgetLocator factory classes provide a fluent API (e.g., WidgetBy.byWidgetId("Store").parentCSS(...).combo()) to locate
and work with RAP widgets without needing to know their internal document object model structure.
A number of existing Dialog page objects and Cucumber step definitions have been refactored to use the new widgets. Notably, several verify* and
action methods have had unused attributeName parameters removed, payment configuration step definitions now correctly distinguish between select and
deselect actions, and checkbox state detection in RAP tables has been improved via client-side JavaScript (EPTest.isChecked) with a fallback
image-comparison mechanism.
Fixed intermittent Selenium test failures caused by ambiguous RAP Widget selector lookups
The findRwtIdForSelector function in ep-test-support.js previously used querySelector, which silently returned only the first matching element
when multiple elements match a given CSS selector. This non-deterministic behavior caused intermittent and difficult-to-diagnose test failures in the
Commerce Manager UI automation suite.
The function has been updated to use querySelectorAll combined with a new _assertSingleElement helper that throws a detailed, descriptive error —
including element IDs, widget types, and automation IDs — when more than one element matches the selector. This makes selector ambiguity immediately
visible rather than silently producing unreliable results. Additionally, CSS selectors in several page objects (StoresResultPane, ProductEditor,
CreateCategoryWizard, and CreateEditShippingRegionDialog) have been tightened with more specific attribute constraints (e.g., adding parent
context selectors, [seeable='true'], or [widget-type='Shell']) to ensure only the intended element is targeted.
JPQL Query Test console now shows generated SQL queries
The JPQL Query Test interactive console has been enhanced to capture and display the native SQL statements that OpenJPA generates when executing queries. Previously, the console only showed the results of a query without revealing the underlying SQL, limiting its usefulness for debugging and performance analysis. Now, each query execution displays the generated SQL statements, the total number of queries executed, and the overall execution time.
ActiveMQ broker now runs as a Cargo container to support concurrent integration test execution
Previously, ActiveMQ was started during integration tests using an embedded Maven plugin (activemq-maven-plugin). This approach prevented multiple
ActiveMQ brokers from running within the same Java Virtual Machine, causing build failures with errors such as "A local broker is already running"
or "Address already in use" when integration test modules were executed concurrently.
ActiveMQ is now started and stopped as a Cargo-managed web application container, consistent with how other test infrastructure components (such as
Cortex and Search) are managed. The TCP and STOMP ports used by ActiveMQ are dynamically reserved at build time from module-specific port ranges,
preventing conflicts between concurrently running test modules. The activemq.xml configuration now reads the ports from the ep.activemq.tcp.port
and ep.activemq.stomp.port system properties, with default values of 61616 and 61613 respectively.
Build Tools
Optional in-cluster proxy cache for Eclipse plugin downloads
Build scripts (build_deployment_package.sh, build_source_tree.sh, build_container_layout.sh, run_extensions_tests.sh, and
run_cortex_system_tests.sh) now accept additional Maven arguments that are passed directly to the underlying Maven command. This allows operators to
supply options such as proxy configuration or mirror overrides without modifying the scripts themselves.
This change also introduces support for an optional reverse-proxy service that caches Eclipse plugin repository (P2) files within the cluster. When
enabled, subsequent builds retrieve Eclipse plugins from the local cache instead of reaching out to external Eclipse mirror servers, reducing
intermittent download failures and improving build reliability. The proxy can be enabled by setting use_p2_proxy: true in the Maven settings
configuration, and the proxy base URL can be overridden via the p2_proxy_base_url variable to support non-standard environments.
New container layout module simplifies Commerce container image builds
A new Maven module, ext-container-layout, has been introduced to streamline the process of building Commerce container images. Previously, the build
pipeline produced an intermediate deployment package (a zip archive) that was then unpacked and rearranged before container images could be built.
This unnecessary step has been eliminated: the container layout file structure and per-application Dockerfiles are now produced directly by the Maven
build and consumed directly by the image build tools.
The build tools have been updated to reflect this change. The previous build_deployment_package.sh script has been split into two new scripts:
build_source_tree.sh, which compiles the full source tree, and build_container_layout.sh, which produces the container layout. The Ansible
playbooks used to build images have also been simplified, with much of the file-rearrangement logic removed.
Additional build process enhancements
- SLF4j was upgraded from 1.7.x to 2.0.x and Logback from 1.2.x to 1.5.x to remediate security vulnerabilities CVE-2024-12798, CVE-2024-12801, and
CVE-2025-11226. Log4j was also been upgraded from 2.17.x to 2.24.x and the SLF4j bridge artifact updated from
log4j-slf4j-impltolog4j-slf4j2-impl. - Eclipse Sisu has been upgraded from version 0.3.5 to 0.9.0.M4 to resolve a build-time compatibility failure caused by Sisu's previously embedded,
outdated
ASMlibrary being incompatible with Java bytecode 15+. As part of this change,ASMand several Jakarta API dependencies are now explicitly included in the runtime bundle. - Resolved a failure in the
bomsmodule during Maven deploy operations by explicitly configuringmaven-deploy-pluginversion 2.8 withdeployAtEnd=true. - Fixed a duplicate
maven-dependency-plugindeclaration in theperformance-cucumber-testsPOM file that generated warnings during the Maven build process (mvn clean install). - Fixed an issue where building the
com.elasticpath.cmclient.coreEclipse plugin module would fail with an unresolvedcom.elasticpath.ep-baseOSGi bundle dependency when Maven goals such ascheckstyle:checkwere run without a precedinginstallphase. - Eliminated spurious Maven build warnings caused by the
ext-plugin-configassembly descriptor attempting to include its own POM artifact and defining an exclusion filter that never matched. The fix adds<useProjectArtifact>false</useProjectArtifact>to the dependency set and removes the unnecessary exclusion, resulting in a cleaner build output. - Resolved
requireUpperBoundDepsviolations in the extensions module by upgradingASMlibraries (asm,asm-analysis,asm-commons,asm-tree) from version 7.2 to 9.3, removing stale dependency exclusions, and enabling strict enforcement of upper-bound dependency rules across all modules. - Removed unnecessary Apache Geronimo spec dependencies (
geronimo-jpa_2.2_spec,geronimo-jta_1.1_spec,geronimo-stax-api_1.0_spec) from multiple modules, replacing them with standard Jakarta/javax API equivalents and reducing transitive dependency noise in built artifacts. - Synchronized the Maven dependency exclusions between
ep-coreandext-coreinext-commerce-engine-wrapperto ensure the Cortex "fat bundle" does not embed JARs (e.g., Spring, Jackson, slf4j, OpenJPA, EhCache) that are already deployed as independent OSGi bundles, preventing duplicate class problems, version conflicts,Bundle-Activatorerrors, and unnecessary bundle bloat. - Updated
ci-settings.xmlto remove the obsoleteeclipse-p2-updatesmirror and replace it with theeclipse-p2-birt-updatesmirror targetingBIRTrelease 4.19.0, ensuring Maven CI mirror configuration aligns withcm-rap.targetlocations. - Updated
.gitignoreconfiguration to exclude the.claude/directory from source control, preventing AI assistant configuration files from being accidentally committed. - The Maven Enforcer Plugin has been updated to fail the build when duplicate POM dependency version declarations are detected, ensuring build stability and encouraging clean dependency management across.
- Removed the unused
org.apache.felix.webconsoledependency and thefelix.webconsole.versionproperty from thebill-of-materialsPOM, reducing unnecessary dependency management overhead. - The
camel-directcomponent has been embedded inep-camel-bundle, resolving an issue where customers usingdirect:endpoint references in their custom Camel routes would encounter failures due to the component not being exported by the bundle. - Per-module JaCoCo code coverage threshold overrides have been removed across all Cortex REST resource Maven modules, so builds will no longer fail due to unmet coverage ratios. Code coverage metrics are still reported, but no minimum thresholds are enforced.
- Removed duplicate
checkstyle-cmclient-suppressions.xmlfiles from the Commerce Manager modules, consolidating all Checkstyle suppression rules into thecode-checking-rulesproject. This eliminates the need for developers to manually addCHECKSTYLE:OFF/CHECKSTYLE:ONannotations in Commerce Manager JUnit test code, as the centralized suppressions now include the full set of expected suppression configurations. - Fixed an issue where the
code-checking-rulesJAR was unnecessarily included in Commerce Manager (cmclient.libs) andext-commerce-engine-wrapperassembly files. This was resolved by removing thecode-checking-rulesdependency from the grandparent POM, reducing assembly bloat and preventing unintended packaging of build-time tooling into runtime artifacts. - Cleaned up redundant and duplicate
.gitignorefiles across the repository by consolidating entries into the root.gitignore. These changes prevent build-generated files from appearing as untracked files ingit status. - The Maven Checkstyle plugin has been upgraded from version 2.17 (using Checkstyle 6.11.2) to version 3.6.0 (using Checkstyle 9.3), improving code quality enforcement with an up-to-date ruleset. Elastic Path's code-checking rules configuration has been updated for compatibility, including adjustments to Javadoc, suppression filter, and modifier rules.
- Removed all
OWASP ESAPIdependencies from the platform, eliminating several vulnerable transitive dependencies (includingbsh-core,commons-configuration,commons-fileupload, andcommons-lang). ESAPI was not actively filtering or protecting any API endpoints, so its removal has no impact on runtime security behavior. - Upgraded the Maven Compiler Plugin from version 3.9.0 to 3.14.1, resolving an issue where Java compilation warnings that caused build failures did not display their root cause in the build output, making failures difficult to diagnose.
- Fixed the assembly enforcer so that database-specific driver JARs (MySQL, PostgreSQL, Oracle, and H2) are no longer included in expected assembly list files and are filtered out during validation. This means running the assembly enforcer reset or validate steps will no longer fail due to a mismatched or missing database driver, regardless of which database profile was used during the build.
- Fixed an issue where
feature.xmlfiles referenced locally built Commerce Manager plugins withversion="0.0.0", causing the build system to resolve the highest available version from the local Maven repository instead of the locally built snapshot. This could result in unexpected errors and required developers to manually delete the local P2 repository cache when switching between platform versions. - The deprecated
hamcrest-coreandhamcrest-librarytest dependencies have been replaced with the consolidatedhamcrest2.2 dependency across the platform; the older artifacts contain no classes in version 2.2 and exist only for backwards compatibility. - Updated the compiler configuration to add the
-Xlint:-serialflag, which suppresses Java 18+ compiler warnings for non-serializable fields in serializable classes. - Updated the compiler configuration to add the
-Xlint:-this-escapeflag, which suppresses warnings raised by Java 21 about possiblethisescape before a subclass is fully initialized. This flag is applied only when running Java 21, as it is not compatible with Java 17. - Fixed a missing distribution management configuration in
boms/pom.xmlthat caused the boms module to fail during Maven deploy operations, preventing accelerator builds from completing successfully. - Duplicate Maven distribution management blocks (defining release and snapshot repository URLs) have been removed from 13 submodule POM files across the codebase, as these settings are now inherited from the root POM.
- The Helix Maven plugin validation process for Cortex modules, which was disabled after the Jakarta migration broke dependency injection in the Maven plugin framework, has been re-enabled by refactoring the validator to use direct instantiation instead of injection.
- Reconciled mismatched version property names for
JAXBdependencies between/pom.xmland/bill-of-materials/pom.xml, replacingcom.sun.xml.bind.jaxb-core.versionandcom.sun.xml.bind.jaxb-impl.versionwithjaxb.versionandjaxb-impl.versionrespectively.
Additional core enhancements
- Fixed a bug where the "Line item product is from category" promotion condition always evaluated to
true, causing promotions targeting a specific category to incorrectly apply to products in any category. The fix ensuresPromotionRuleDelegateImpl#lineItemProductCategorynow properly validates that the line item's product belongs to the specified category before applying the promotion. - Fixed an issue where promotions using product or SKU attribute value conditions (e.g.,
lineItemProductAttributeValueCondition,cartProductSkuAttributeValueCondition) silently failed to apply when the attribute key contained any lowercase characters. Attribute value comparisons are now also case-insensitive, so promotions will correctly evaluate regardless of the case used in attribute keys or values. - Stacked discounts no longer exceed line item subtotal: Fixed a bug where applying multiple stacked promotions to a cart line item could result in a
total discount amount greater than the item's subtotal, causing over-discounting on orders. The fix moves subtotal cap enforcement into
AbstractShoppingItemImplso that each successive discount is limited to the remaining undiscounted value of the line item. - Fixed a bug in the credit/refund processing logic where the presence of
REVERSE_CHARGEpayment events would incorrectly cause refund operations to fail, even when a valid approved charge was available to refund against. The fix ensures that reverse-charged amounts are correctly accounted for when calculating refundable balances, allowing refunds to proceed as expected. - Fixed an incorrect exception message in
CreditProcessorImplthat displayed a cancel reservation failure message instead of a refund failure message when a refund could not be processed. - Fixed a bug where attempting to check out after a previous payment failure would throw a database unique constraint violation
(
TORDERSKU_GUID_UNIQUE). Order SKU GUIDs are now generated using a combination of the order ID and the cart line item GUID, ensuring uniqueness across multiple order attempts for the same cart. - Fixed
incompatible-configurationwarnings that appeared in logs during service startup when using the EhCache OpenJPA data cache manager, by updating theopenjpa.DataCacheproperty value fromtruetoehcacheand removing the incompatibleopenjpa.RemoteCommitProviderproperty. - Fixed product and SKU reindexing after updating SKU option values: index notifications (
TINDEXNOTIFYrecords) are now correctly created for only the products and SKUs affected by the changed SKU option value, and product last-modified dates are no longer incorrectly updated as a side effect. - Fixed an issue where services started locally with
mvn cargo:runhad a maximum JVM heap size of only 500MB, which was insufficient for large data sets and could cause OutOfMemoryErrors (e.g., in Search Server). The default max heap size has been increased to 2048MB. - Fixed a bug where SKU, product, and category exclusions on shopping cart promotion conditions (line item product, line item product category, and product-in-cart conditions) were being ignored, causing excluded items to incorrectly receive promotion discounts.
- Fixed an issue where promotion actions were limited to a maximum of 10 parameters due to the use of
Map.of()inAbstractRuleActionImpl#createRuleCode. The method has been refactored to useMap.ofEntries(), allowing an unlimited number of promotion action parameters. Promotions with more than 10 action parameters will now function correctly. - The
InventoryDtoCacheKeyheld a fullProductSkuobject in memory, causing excessive EhCache memory consumption. The cache key has been refactored to store only the SKU code string, withProductSkuLookup(which is itself cached) used to retrieve theProductSkuwhen needed. - Updated all MySQL JDBC driver class references from the deprecated
com.mysql.jdbc.Driverto the currentcom.mysql.cj.jdbc.Driveracross the platform. - Resolved an issue where Order objects passed between methods within a context object but not refreshed after database updates, which could cause
subsequent operations to overwrite changes made by previous operations. This affected gift certificate creation during checkout (
CreateGiftCertificatesCheckoutAction) and several batch job processes. - The default Cargo container startup timeout has been increased from 120 to 180 seconds to prevent local services from timing out due to taking too
long to start. The timeout is now configurable via the
ep.cargo.prop.startupTimeoutMaven property. - Fixed a
NullPointerExceptionthat occurred when checking availability of a product bundle containing "Always available" constituent products or nested empty bundles (bundles with no constituents), which previously resulted in a server error during item lookups in Cortex. Null safety was added to the constituent inventory details sorting logic inProductInventoryShoppingServiceImpl, and empty bundles are now correctly treated as not available. - Removed the unused
CartHasItemsServiceImplclass, its related interface, and associated tests. - Removed deprecated shopping cart deletion methods (
deleteShoppingCartsByGuidanddeleteAllShoppingCartsByShopperUid) and their associated named queries fromShoppingCartService, enforcing that all cart deletions are handled exclusively by thePurgeCartsBatchProcessor. - Removed unused fields (
codeValid,mergedNotification,itemWithNoTierOneFromWishList,giftCertificateService,discountCalculator) and methods (getSubtotalOfShippableItems,getCustomerEmailAddress,getCustomerBusinessNumber,isCustomerAnonymous) fromShoppingCartImpland theShoppingCartinterface. - The deprecated
com.elasticpath.commons.util.Collectionsutility class has been removed fromep-core. - Removed the unused
greenmail(com.icegreen) test dependency from the bill-of-materials and all affected module POMs, includingep-email,ep-test-application, andep-core-fittests. - Removed the unused
ActiveRuleinterface andActiveRuleImplclass fromcom.elasticpath.domain.rules. These classes were legacy Drools rule ID wrappers that were no longer in use. - Removed the unused
PropertyServiceinterface andPropertyServiceImplclass, along with the associatedpropertyServiceSpring bean definition and thePROPERTIES_SERVICEconstant fromContextIdNames. - Removed unused fields (
promotionRuleDelegate,ruleEngineSessionFactory,ruleEngineRuleStrategy,couponConfigDao,productSkuConverter,shoppingCartConverter) along with their getters, setters, and Spring bean injections fromAbstractRuleEngineImpl. - The caching configuration for Performance Insights tests has been separated into a dedicated
ehcache-performance-insights.xmlfile (generated fromehcache-fast-updates.xml) with infinite time-to-live and unlimited cache sizes, ensuring query counts are consistent between runs so that genuine performance regressions are easier to identify. - Fixed a regression where cached tax results from cart pricing were not being reused during checkout, causing unnecessary recalculation. This was
resolved by introducing a new cache key class (
XPFTaxCalculationContextAlternateKey) and updating theOrderSkuGUID format to{order_id}|{cart-item-guid}, allowing the cache to correctly match cart and order SKUs while avoiding database unique key constraint violations. - The
allConditionsandallActionslists are now autowired extensible Spring lists, so customRuleConditionandRuleActionbeans are automatically discovered and registered. - All internal usages of
org.drools.core.util.StringUtilshave been replaced withorg.apache.commons.lang3.StringUtils, and the Drools class has been added to the CheckstyleIllegalImportlist to prevent future use. - Fixed a memory inefficiency in
StoreProductSkuFactoryImplwhere every cachedStoreProductSkuproxy unnecessarily held a reference to theStoreProductSkuFactoryImplSpring singleton. This was caused by a lambda capturingthisdue tohashCode(ProductSku, PerStoreProductSkuAvailability)being declared as an instance method despite using no instance state; converting it tostaticresolves the unintended object retention. - Dozens of private methods, fields, and constants across the Commerce platform core, services, search, checkout, tax, promotions, and Commerce
Manager UI layers have been changed to
protected(orpublicwhere necessary), and new protected getters/setters have been added, significantly reducing the need for workarounds when customizing platform behavior. - Spring XML configuration files across the platform have been updated to declare beans using
idinstead ofname, standardizing bean definition practices and ensuring bean identifiers are unique within the Spring container. - A new
ShoppingItemDtoBuilderinterface andShoppingItemDtoBuilderImplimplementation have been introduced to replace the multi-methodShoppingItemDtoFactorypattern for constructingShoppingItemDtoobjects. The existingShoppingItemDtoFactoryImplhas been refactored to use the new builder internally. - The eager JPA fetch from
CustomerGroupImpltoCustomerRoleImpl(via theTCUSTOMERGROUPROLEXtable) has been eliminated, reducing the number of database queries executed when loading customers. TheROLE_CUSTOMERSpring Security authority is now hardcoded directly inCustomerImpl.getAuthorities(). - Improved shopping cart performance by refactoring
ShoppingCartImplto retrieve cart items directly from the flat cart memento list instead of performing a costly recursive tree-flattening operation. This change affects several cart methods, and a null-pointer issue inCartDirectorImplwhen processing bundles with missing parent items has also been resolved. - A performance optimization prevents an unnecessary database query when calculating available coupon discount quantities for shopping carts that have no applied coupon codes, reducing database load during cart and checkout processing.
- Fixed an issue where promotion carrots were not displayed for products belonging to a category referenced by a shopping cart promotion condition.
The root cause was incorrect category identifier comparison logic, which has been resolved by converting
CategoryGuidUtilfrom a standalone class to a Spring-managed bean and refactoringRuleParameterUtilityto use the promotion rule delegate for category matching. - The
EnumLoaderclass has been updated to use wildcard generic type parameters, making it easier to work with extensible enum implementations. This reduces the complexity of custom code, such as unit tests, that referencesEnumLoadermethods likegetEnumsandsetEnums. - Several extension point framework converter classes that convert extension point entities back into domain objects have been moved to the new
com.elasticpath.xpf.converters.outputpackage. Any customizations that reference these classes (includingStructuredErrorMessageConverter,OrderHoldConverter,InventoryDtoConverter, and others) must update their Java imports and Spring XML bean definitions accordingly. Upgrade recipes are provided to assist with this migration. - Fixed an issue where promotion rule validity checks ignored the
SHOPPING_CONTEXT_DATE_OVERRIDErequest header, causing coupons belonging to future-dated promotions to be incorrectly rejected when a shopper used a date override trait. - Removed an obsolete reference to a non-existent method (
getCurrentLupNumber) from the sync service merge filter bean configuration. - The non-functional
hot-deploy-sling,felix-deploy, andosgi-deployMaven build profiles and their associated Apache Sling plugin configuration have been removed from all modules, as these profiles did not work reliably and provided no practical value.
Additional Cortex enhancements
- Fixed a race condition where two simultaneous checkout requests for the same cart (e.g., from a double-click or network retry) could cause a duplicate order constraint violation to be silently swallowed, resulting in shoppers receiving a misleading "Payment method must be present" error and a failed cart requiring retry. The fix ensures unrecognized persistence exceptions are re-thrown rather than ignored, and improves duplicate constraint detection to handle varying OpenJPA exception nesting structures across MySQL, Oracle, PostgreSQL, and H2.
- Fixed issue with Cortex logging in deployed environments. After applying the Logback 1.5 upgrade patch, Cortex produced no log output when deployed
via Tomcat (while local Cargo deployments were unaffected). This was caused by a syntax change in Logback 1.5's conditional configuration; the fix
replaces the deprecated
if/thenconditional blocks with Logback's native property default syntax (e.g.,${ep.logback.console.threshold:-ALL}). - A non-fatal
BundleException(Bundle symbolic name and version are not unique: jakarta.el-api:5.0.1) was logged as anERRORduring every Cortex startup. This was resolved by movingjakarta.el-apito the correct dependency scope and removing the duplicate bundle from the OSGi bundle load path. - Checkout payment instrument reliability improvement: Cart order payment instruments and the customer's default payment instrument are now loaded
once at the start of checkout and stored as transient fields on the
ShoppingCartobject, eliminating redundant database calls and preventing intermittent checkout failures (e.g., "Payment method must be present" errors) that could occur if payment instruments changed mid-checkout. - Fixed an issue where Cortex returned a
500 Internal Server Errorwhen loading a shopper's profile if the customer record contained a Date-type profile attribute with a null value; the profile resource now loads normally in this scenario. - Resolved an issue where the autocomplete dropdown in the Cortex Studio Zoom field was incorrectly displayed at the top of the page rather than beneath the input field. This was caused by a jQuery UI incompatibility and was fixed by upgrading jQuery UI from version 1.11.4 to 1.13.2.
- Resolved an issue where
XPFTaxableShoppingItemgenerated a new GUID on every tax calculation call, causing theElasticPathTaxCalculatorcache to always miss and redundantly recalculate taxes for identical requests. The GUID is now derived from the shopping cart line item GUID, ensuring consistent cache hits for repeated tax lookups on the same cart items. - Fixed a
NoSuchElementException("No value present") server error in Cortex that occurred when a new SKU option value was added and assigned to a new product SKU before the SKU option cache (default 60-minute TTL) had expired. When the missing option value is detected, the stale SKU option entry is now evicted from the cache and reloaded from the database. - Fixed spurious "Invalid cookie header" warnings appearing in logs during OpenID Connect authentication handshakes by updating the
HttpClient in
OidcHttpRequestUtilto use the RFC-compliant standard cookie specification (CookieSpecs.STANDARD). - A new
cortex.headers.ignoreJVM parameter has been added to Cortex, allowing administrators to specify a comma-separated list of HTTP request headers to unconditionally remove before processing. Unlike headers configured via the OSGi "Headers to Remove" list, headers specified in this parameter are stripped in all circumstances, including when trusted header mode is enabled or when requests target the authentication endpoint. - Fixed an intermittent Cortex startup failure where the Spring JMS bundle could not find a required Spring Transactions class during startup. This
was caused by an unpredictable bundle load order; the fix moves the Spring Transactions bundle to load at an earlier stage (
bundles-level4) to guarantee it is available before Spring JMS needs it. - A warning logged when the
auth.modeproperty is missing fromauthentication.propertiesnow appears only once per session instead of on every Cortex request; additionally, the default configuration now includesauth.mode=OAUTH_PASSWORDto prevent the warning from appearing in standard deployments. - Product SKU availability validation errors now return
available-dateandexpiry-datefields in ISO 8601 format (e.g.,2026-09-04T00:00:00) instead of a localized US short date format (e.g.,9/4/26 12:00 AM).
Additional Commerce Manager enhancements
- Fixed an issue in Commerce Manager where performing a new Price List Assignment search that returns no results would fail to clear the previous search results if the user had navigated away from the first page, leaving stale results visible alongside the "No results found" message.
- Removed unused BouncyCastle (
bcprovandbcutil) plugins from Commerce Manager to remediate three security vulnerabilities: CVE-2026-0636 (CVSS 5.3), CVE-2026-5598 (CVSS 10.0), and CVE-2025-14813 (CVSS 9.0). - Fixed broken JMX
get/setLogLeveloperations in Commerce Manager that were failing with aNoClassDefFoundError. Theep-jmx-logging-apiandep-jmx-logging-log4jlibraries are now explicitly packaged as part of the Commerce Manager webapp rather than relying on transitive dependency resolution. - Fixed an issue where coupon codes created in Commerce Manager with leading or trailing whitespace (including Unicode whitespace characters) would fail validation when used by customers; the coupon service now automatically strips whitespace from coupon codes on both create and update operations, including via Import/Export.
- Fixed an issue in Commerce Manager where clearing customer profile fields (e.g., Business Number, Tax Exemption ID) would not save correctly, causing values to revert to their previous entries. The fix ensures that setting a short-text customer profile attribute to blank removes the corresponding database record rather than retaining the old value.
- Resolved an issue in Commerce Manager that caused a
NoSuchBeanDefinitionExceptionwhen attempting to copy a shopping cart promotion that contained rule exclusions (e.g., category, SKU, or product exclusions); theDuplicateShoppingCartPromotionWizardnow correctly resolves the bean using the exception's type rather than a hardcoded bean name. - Fixed an issue in the Commerce Manager promotion editor (both Catalog and Cart Promotions) where changes to Store or Catalog assignments made after an initial save would not be persisted — the editor now correctly reads assignment state from the current editor model rather than a stale reference captured at editor open time.
- Fixed an issue in Commerce Manager where the shipping service level dropdown for a Shipping Discount promotion action retained stale options after the store selection was changed. If the newly selected store has no applicable shipping service levels, the dropdown is cleared and disabled, and an error is displayed to prevent saving an invalid promotion.
- Descender characters (g, p, y, j, q) were being visually clipped at the bottom of column headings in Commerce Manager lists and grids. This was
resolved by injecting a client-side JavaScript override that adds padding to the RAP
GridColumnLabelcell height, and updating the$table_header_paddingvariable. - Removing a product or SKU attribute from a product type no longer incorrectly deletes attribute values for products in other product types that share the same attribute — only attribute values belonging to products of the modified product type are now removed.
- In Commerce Manager, required boolean customer profile attributes were missing the required field (red
!) icon and displayed a raw exception message instead of a user-friendly error when left unset on save. Both issues are now resolved, bringing behavior in line with other required attribute types. - Fixed an issue in
AbstractCmClientFormEditorwhere aCancelSaveExceptionduring a save operation (e.g., saving a cart promotion with no stores assigned) would cause an unwanted system error dialog to appear alongside the validation error dialog. The save operation now correctly handles this exception, displaying only the relevant validation message and keeping the editor open without triggering a spurious system error. - The
PromotionRulesWidgetUtilclass has been made extendable by removing thefinalmodifier and changing the constructor andLayingOutMouseAdapterinner class toprotected, enabling custom implementations of promotion rules widget behavior. - When editing an existing cart promotion, switching between "Define cart level rules" and "Define line item level rules" in the Promotion Rules tab now properly displays only the relevant conditions and actions for the selected level, and removes incompatible rule elements when the promotion is saved — matching the behavior already present in the Create Shopping Cart Promotion wizard.
BaseConditionalExpressionActionhas been renamed toAbstractConditionalExpressionActionand made abstract, with the placeholdergetTargetIdentifier()implementation removed.- Fixed an error that occurred when opening a newly created master catalog configured with all available languages. The root cause was that certain locales returned by the JVM could not be round-tripped through their string representation, causing a persistence exception; these incompatible locales are now filtered out.
- The changeset icon in the Commerce Manager top menu has been updated to reflect the current visual style and now displays a text label beneath the icon.
- Fixed a bug where copying a shopping cart promotion in Commerce Manager caused the copy to share the original promotion's shopper conditions (selling context), meaning edits to one promotion's conditions would unexpectedly affect the other. A database migration script runs automatically on upgrade to separate any previously affected promotions.
- Validation dialogs shown when saving shopping cart or catalog promotions with missing store or catalog assignments now display as standard warning dialogs consistent with the Commerce Manager interface, including a proper title and warning icon instead of a plain, untitled message box.
Additional Search Server enhancements
- Fixed an issue where the Search Server query cache (configured via
openjpa-querycacheinehcache.xml) was preventing index update notifications from being processed for up to an hour; the cache timeout has been reduced from 3600 seconds to 5 seconds, ensuring near-real-time index updates. - Resolved a date truncation error that occurred during Search Server startup when the
TRULESTORAGEtable was empty. A timezone transformation in the MySQL driver caused an epoch-based date (Date(0)) to shift before the Unix epoch (1969-12-31), producing an invalid datetime value that prevented theTJOBEXECUTIONrecord from being written and blocked promotion rule compilation. The fix replaces the epoch date write with a delete operation on the job execution record.
Additional Batch Server enhancements
- Fixed a bug in the
AbandonedCartsCleanupJobwhere cart UIDs were incorrectly passed to a service method expecting shopper UIDs, causing abandoned shopping carts to remain active instead of being deactivated. The job now correctly fetches cart GUIDs and uses the appropriatedeactivateShoppingCartsByGuidservice method. - Fixed an issue where shopping cart line items soft-deleted via Cortex only permanently removed from the database when the
underlying shopping cart expired. A new
InactiveCartItemsCleanupJobnow runs hourly (at 20 minutes past the hour) to purge these records, respecting the existingCOMMERCE/SYSTEM/INACTIVECARTSCLEANUPJOB/minAgesetting (default: 60 minutes) before deletion. - Fixed an issue where the "Order Cleanup" jobs failed with a foreign key constraint error when attempting to delete orders that had associated order
hold records. This was resolved by updating the
FK_TORDERHOLD_TORDERforeign key constraint on theTORDERHOLDtable to use cascade deletion via a Liquibase database migration. - The
PurgeExpiredCompletedOrdersBatchProcessorandPurgeExpiredFailedOrdersBatchProcessorclasses have been consolidated into a singlePurgeOrdersBatchProcessorclass, which is now shared by both the expired completed and expired failed order cleanup Quartz jobs. - Fixed intermittent promotion compilation failures where some promotions were not recompiled properly after edits. The
ruleUpdate.propertiesandcatalogPromo.propertiesfiles used by the Search Server to track rule compilation and catalog promotion check timestamps were vulnerable to race conditions from concurrent access and could be lost during deployments. These files have been replaced with a newTJOBEXECUTIONdatabase table, ensuring reliable, consistent state tracking across all nodes.
Additional Data Sync enhancements
- Fixed unnecessary product reindexing when publishing new SKU option values. Publishing a new SKU option value via the Data Sync Tool no longer
incorrectly creates
TINDEXNOTIFYrecords for all products associated with the SKU option, preventing unnecessary reindexing of unaffected products in the live environment.
Additional Import/Export enhancements
- Performance improvement for inventory imports: Redundant calls to the expensive
getInventorymethod (which queries bothTINVENTORYandTINVENTORYJOURNAL) have been eliminated during inventory import processing, improving import time by about 3X. - Fixed a
NullPointerExceptionin the Import/Export API'sSummaryAggregationStrategythat caused the API to return an unhelpful500 Internal Server Errorwhen an import failed (e.g., when an invalid changeset GUID was provided); the API now correctly returns a400 Bad Requestwith a meaningful error message. - Fixed a spurious
Error during type conversionstack trace that appeared in Integration Server logs after every Import/Export Export API request. The error was caused by Apache Camel'sOnCompletionprocessor attempting to cache aPipedInputStreamwhose write end had already been closed; the fix configuresonCompletion()to use the original message instead, avoiding the closed-stream read. Export API functionality was unaffected, but the noise in logs could obscure real errors. - Fixed a bug in
ImportRouteBuilderwheresuper.configure()was called twice, which could cause duplicate route registration and unexpected behavior during Import/Export operations. - Removed unused
productServiceandproductLoadTunerfields, associated setter methods, and theproductTunerForPricingSpring bean definition fromPricingExporterImpl. - When an import fails due to an invalid attribute value (e.g., a value exceeding the maximum length), the error message now identifies the specific
attribute key responsible, such as
Invalid attribute 'catName' with validation error message 'AttributeValue length must be less than or equal to 255', replacing the previous generic error that required log inspection to diagnose. - Importing a new catalog through the Import/Export API was failing with a
pcStateManager is nullexception. The issue was resolved by changing the default OpenJPA detachment strategy fromStrictDetachmentStrategyImpltoNonDetachingDetachmentStrategyImpl, while retaining strict detachment for Cortex.
Additional performance enhancements
- Fixed a critical performance issue where Cortex became unresponsive due to a slow-running database query against the
TCOUPONUSAGEtable when looking up automatically applicable coupons. A new index (I_TCOUPONUSAGE_CUSTOMEREMAILADDRESS) on theCUSTOMER_EMAIL_ADDRESScolumn has been added via a Liquibase changeset to resolve this. - The
saveShoppingCartmethod now skips pricing snapshot evaluation (which triggers the promotion rule engine) when no active free-item promotions ( e.g., "buy N, get M free") exist for the store. The result is cached per store with a 10-minute TTL, reducing unnecessary rule engine overhead on every cart save in stores without such promotions.
Additional test enhancements
- Fixed an issue where the JaCoCo Maven plugin was silently skipping test coverage report generation and threshold enforcement because the Surefire
plugin's
argLinewas not using late-binding (@{jacocoArgLine}) for the JaCoCo agent argument. As a result, JaCoCo execution data was never written and coverage checks were bypassed entirely. - Fixed an intermittent failure in the Create Catalog Selenium tests where the default language dropdown would not finish populating in time, causing test failures. A retry mechanism now replaces the previous fixed sleep delay, making the test more reliable.
- Fixed an intermittent test failures caused by a race condition where shipment line item tax values were being checked before asynchronous
post-capture checkout actions (such as tax application) had finished writing to the order. A new
ORDER_READYevent type has been introduced, which is fired byPostCaptureCheckoutServiceImplonly after all post-capture actions have completed, providing a reliable signal that order data is fully populated. - Fixed a duplicate
FACET_GUIDvalue in the Mobee demo data (liquibase-changelog.xml), which caused intermittent test failures. The duplicate GUID for the "Rental Days" facet entry has been replaced with a unique value. - Removed the
Mockito.reset-basedtearDownmethod and eliminated unnecessary mock stubs inPromotionRuleDelegateImplTest, ensuring that Mockito's strict stubbing checks are no longer suppressed and unused stubs are properly detected. This improves test reliability and prevents false confidence from silently ignored stub violations. - Fixed an intermittent integration test failure caused by a missing teardown in
MergeEngineImplITest, which left aCacheManagerinstance running and prevented subsequent Data Sync Tool tests from initializing correctly. The fix ensures the Spring application context is properly closed after each test run. - Created new Cucumber functional tests for Import/Export functional scenarios in
commerce-engine/importexport/ep-importexport-acceptance-tests. These tests include validating idempotent imports, selling context conditions, andINSERT/UPDATE/INSERT_OR_UPDATEimport strategies. A sharedreadZipEntryAsStringutility method was also refactored into the base test class for reuse across step definitions. - Resolved intermittently failing
AddToAndRetrieveItemsFromWishlisttest scenarios where search retry logic incorrectly fell back to searching by product name only instead of maintaining the original name-and-code criteria, causing intermittent false test failures. - The Cucumber test EhCache default cache time-to-live has been updated from 60 seconds to 1 second to align with the production EhCache configuration, preventing stale data from causing intermittent test failures when values are changed in Commerce Manager and accessed via Cortex.
- Updated
TokenStoreStrategyImplTest,OAuth2AccessTokenTransformerTest, andAccessTokenDtoTransformerTestto generate random UUID-based tokens instead of static hardcoded token values, improving test isolation and reducing potential false positives in authentication token testing. - Fixed an invalid Scenario Outline (missing its examples table) in
gift-certificate-payment-instruments.featureby converting it to a standard Scenario. This resolves warnings raised by the Cucable plugin and IntelliJ, and allows the test to execute correctly. - Fixed an intermittent race condition in automated tests where the "Move item" button was incorrectly reported as disabled when splitting an order shipment, causing tests to fail unpredictably. The fix adds retry logic around the item selection and button click in the order editor test helper.
- Fixed intermittent automated test failures in the Manage Virtual Catalog scenarios, specifically when adding or removing linked categories and deleting a virtual catalog. The failures were caused by menu-dismissal side effects in the test framework's click logic, which have been resolved by introducing a dedicated menu item click method.
- Fixed an intermittent failure in the catalog syndication category flow test where a randomly generated category name could land on a second page of search results, causing the category finder dialog's pagination logic to never execute due to catching the wrong exception type.
- Fixed a test reliability issue in
FatalExceptionCheckerTestwhere theignoreFatalJsExceptionsflag was being reset after each test run rather than before, which could cause tests to behave incorrectly if a previous test left the flag in a modified state. - Retry logic in
retryFunctionandretryAttemptshas been updated to more precisely classify which exceptions should trigger a retry versus fail immediately.InvalidElementStateExceptionandNotFoundException(includingNoSuchElementException) are now retried, whileInvalidSelectorExceptionis treated as a fatal error and will stop retrying immediately. These changes reduce false negatives from transient element state issues and prevent unnecessary retries when a locator is fundamentally broken. - Selenium automated tests now support a fail-fast mechanism for critical JavaScript errors: exceptions with a
FATAL:prefix in their message will immediately break the retry loop instead of being silently retried. This is disabled by default (lenient/legacy behaviour) and can be enabled by setting theep.selenium.ignore.fatal.js.exceptionsproperty tofalse. TheassertSingleElement()helper inep-test-support.jshas been updated to emit aFATAL:-prefixed error when an ambiguous element selector matches more than one element. - Corrected automated test column references throughout the Commerce Manager test suite to use precise column names (such as "Display Name", "Product Code", "Order #", and "SKU Configuration"), ensuring compatibility with strict table column matching and improving test reliability.
- Fixed intermittent Selenium test failures caused by nested
retryFunction()calls, where inner retry exhaustion was incorrectly wrapped in a timeout exception that the outer retry could not handle. A newretryAttempts()method has been introduced as a safe alternative for inner retry logic, re-throwing the original assertion error on exhaustion rather than wrapping it. - Resolved intermittent failures in wishlist management automated tests by replacing unreliable element-existence checks with a direct negative
assertion method. As part of this fix, the test widget library was refactored to use a new fluent
.as("description")pattern for supplying custom failure messages, replacing the previous approach of passing message strings as method parameters. - Commerce Manager system tests now explicitly log out at the end of each test scenario to release server-side sessions, preventing memory exhaustion caused by session accumulation when tests complete faster than the configured session timeout.
- Fatal JavaScript exception checking in system tests is now strict by default; tests will immediately fail when a fatal JavaScript exception is
detected rather than treating it as a retryable error. To restore the previous lenient behavior, set the property
ep.selenium.ignore.fatal.js.exceptionstotrue. - Fixed intermittent Performance Insights test failures by removing code that reset the database between test scenarios. This reset was dropping all database tables while applications were still running, leaving them in an unknown state and causing unpredictable failures.
- Fixed an intermittent automated test failure caused by a page element becoming detached from the document between being located and clicked. The fix moves the element lookup, scrolling, and focus steps inside the retry loop so all actions are retried together if a stale element is encountered.
- Fixed an intermittent automated test failure where creating a return in the Order editor would occasionally throw a stale element reference error. The fix removes redundant viewport-checking logic in the test definition that was re-querying a page element after it had already been refreshed or replaced by the browser.
- Fixed an intermittent error where order shipment release failed emails could not be sent due to duplicate test execution listener registration in Cucumber tests, causing the entity manager factory to close twice and resulting in a null pointer exception during transaction commits.
- Improved reliability of Selenium test infrastructure by adding automatic retry logic (up to 3 attempts) when initializing a remote Chrome browser session, and ensuring the WebDriver session is always properly cleaned up even if an error occurs during shutdown.
- Fixed intermittent test failures in the "Move Object between Changesets" test scenarios caused by multiple scenarios competing for the same product when tests ran concurrently; each scenario now uses a distinct product to avoid conflicts, since an object can only belong to one changeset at a time.
- Fixed an issue where browser HTML snapshots captured during Selenium test failures were partially rendered in test reports, making them unreadable. The HTML source is now properly escaped before being embedded, allowing developers to inspect the state of page elements at the time of failure.
- Fixed a race condition in the
Utils.uniqueCode()test utility method that could generate duplicate codes when multiple threads ran concurrently, causing intermittent database unique constraint violations during integration test execution. The fix replaces a non-thread-safe static integer with an atomic integer and incorporates the process ID into the generated code to ensure uniqueness across parallel test forks. - Fixed intermittent failures in order payment modification test scenarios caused by race conditions during parallel test execution. The test payment provider plugin was updated to use thread-safe data structures, ensuring that call counts per order number and transaction type are tracked correctly across concurrent tests.
- Fixed a resource leak in programmatic test data generation by converting
TestEpCoreProviderto a singleton with proper shutdown handling, resulting in lower memory usage, reduced CPU load, and fewer peak database connections during test suite execution. - Commerce Manager automated test steps for search result validation have been updated with retry logic to handle cases where search results take longer to load, resolving intermittent test failures that were most commonly seen on Oracle databases but could also affect MySQL and PostgreSQL environments.
- Fixed an intermittent issue where
clearAndTypeText()would silently accept a partially entered text string as successful, causing automated tests to fail unexpectedly. The validation check now confirms the full text value was entered into the field, rather than only checking that the field is non-empty. - Fixed intermittent failures in the automated tests for the promotion SKU search and account search features in Commerce Manager. The failures were caused by timing issues where tests checked for results before the UI had finished loading them. Retry logic and proper result-waiting behavior have been added to make these tests more reliable.
- Fixed an intermittent test failure in the Customer Data Policy feature caused by a JavaScript error when attempting to move focus to a page element;
the automated test framework's retry logic now ignores
JavascriptExceptionand retries the action automatically. - Separate port ranges are now assigned during integration test builds to prevent port conflicts: cargo web applications use ports 30000–39999 and the embedded ActiveMQ broker uses ports 40000–49999. Previously, the two port reservation steps could accidentally reserve the same port, causing intermittent build failures.
- Improved debugging output in Commerce Manager automated test step definitions, providing more detailed error messages when payment transaction verifications or payment reservation assertions fail, making it easier to diagnose intermittent test failures.
- Upgraded the Cucable plugin from version 1.9 to 1.15.2 and expanded parallel test execution support across multiple system test modules by adding
runner templates, parallel-runners build profiles, and custom report/rerun output directory placeholders. Several test feature files had their
isolation tags (
@runIsolated) added or removed to improve reliability when tests run concurrently. - Fixed an intermittent failure in the Tags System where concurrent automated test scenarios modifying the same tag dictionary simultaneously caused database unique constraint violations, preventing tag definitions from being saved in Commerce Manager.
- Improved the Cortex API automated test suite by enhancing assertion failure messages to include more diagnostic detail, making test failures easier
to investigate. Validation and order-related error message step definitions have been consolidated into a single
AdvisorStepsclass, and cart-related steps have been moved toConfigurableCartSteps. - Duplicate feature path entries have been removed from Cucumber test runner configurations, and duplicate columns have been removed from feature tables. These changes eliminate warning messages during test runs and fix an incompatibility that prevented scenarios from being parallelized correctly.
- Selenium tests for the Commerce Manager now enforce exact table column name matching, throwing a clear error message that identifies the invalid column name and lists the available columns when a mismatch occurs. This improves test reliability and makes failures easier to diagnose and debug.
- Fixed intermittent automated test failures in Commerce Manager caused by ambiguous element selectors that could match multiple widgets; the test support library now throws a descriptive error when a selector matches more than one element, and several selectors have been made more specific to target the correct element reliably.
- Added support for programmatic commerce data generation in Cucumber test step definitions, allowing new isolated stores to be created per test scenario. This replaces slow UI-driven store creation and prevents intermittent test failures caused by concurrent scenarios sharing and conflicting over the same store's payment configurations.
- Fixed a race condition that caused intermittent test failures when Commerce Manager user creation tests were run in parallel. The previous
implementation used direct SQL inserts to create users in the database, which could produce unique constraint violations; it has been replaced with
a proper service-layer approach using
CmUserTestPersisterand theTestEmbeddedEpCoreframework. - Updated payment configuration automated tests to create a unique store for each test scenario, preventing intermittent test failures caused by shared store state when tests run concurrently.
- Fixed intermittently failing pre-order and back-order automated tests where inventory was incorrectly being added to the wrong warehouse, causing order allocation to fail.
- Fixed an intermittent failure in the catalog batch integration test (
CatalogBatchIntegrationTest) caused by an incorrect expected message count. The fix corrects the count from 1 to 2 (since both the cleanup and build batch jobs send messages) and moves the message listener setup to run before test data is persisted, ensuring all relevant messages are captured. Messages are also now filtered by option code to avoid interference from unrelated test activity. - Fixed intermittently failing catalog syndication integration tests. The tests previously relied on counting an exact number of messaging events within a time window, which was inherently fragile; they now assert directly against database state instead. The expiry projection job tests were also fixed by invoking the job directly rather than sleeping for 125 seconds and waiting for the scheduler to run it.
- Fixed an intermittent test failure in the
Order Item Detailautomated tests where the cleanup hook would fail to locate the Merchandising tab element because the correct product editor pane was not explicitly activated before interacting with it. The cleanup logic was updated to close the order pane and navigate to the correct product editor tab before proceeding.
Additional Build Tools enhancements
- The ActiveMQ container startup script (
start-activemq.sh) now validates that required and optional environment variables are set to valid values before starting the broker. If an invalid value is detected, the script exits with a descriptive error message rather than starting with a misconfigured state. - Fixed an issue where property files from a secure configuration repository were not being applied during data population, causing the tool to run without the expected environment-specific configuration.
- The
ext-container-layoutbuild has been updated to fail immediately if any declared artifacts are missing, rather than issuing a warning and continuing. This prevents broken container images — where missing dependencies such as messaging client libraries would only cause errors at runtime — from being produced silently. - Build log files generated during pipeline jobs are now saved as artifacts when those jobs fail, restoring previously removed behavior and making it easier to diagnose build failures.
- The explicit reserved code cache size setting of 128 MB has been removed from Maven build options, allowing Java 21 to use its default of 240 MB and enabling proper segmented code cache allocation, which improves build reliability.
- Added a
run_cortex_system_tests.shscript and updated the Maven settings configuration playbook to support a CI-specific settings template, enabling the branch validation job to use centralized build tools instead of inline commands in the pipeline definition. - Build Tools now support MySQL 8.4 container images, which is now the default version built by the
build_base_images.ymlplaybook. MySQL 8.0 remains supported and can be selected by overriding thedatabase_idvariable at runtime (e.g.,ansible-playbook -e database_id='mysql-8.0' build_base_images.yml). - The MySQL live (DST target) database connection parameters in the build tools and Commerce containers were missing the
allowPublicKeyRetrievalparameter, causing them to be out of sync with the author database parameters. BothEP_DST_TARGET_PARAMSandEP_DST_TARGET_URLhave been updated to include this parameter, ensuring consistent database connection configuration across author and live environments. - The Tomcat connector (port 8080) in Build Tools now has a default
maxThreadsvalue of 250, aligning the self-managed commerce platform with Operational Insights recommendations for optimal performance.
Additional database enhancements
- Fixed three Liquibase changesets (
2021-09-create-FK-BATCH_JOB_EXECUTION-index,2021-09-create-FK-BATCH_JOB_EXECUTION_PARAMS-index,2021-09-create-FK-BATCH_STEP_EXECUTION-index) that were incorrectly configured withrunAlways="true", causing duplicate entries to be inserted into theDATABASECHANGELOGtable on every data population run. This could cause failures for databases that have a primary key or unique constraint on theDATABASECHANGELOGtable'sID,AUTHOR, andFILENAMEcolumns. - Fixed data type mismatches in the
TRMAGENERATORandTORDERNUMBERGENERATORtables where sequence number columns were incorrectly typed asVARCHARinstead ofBIGINT, and the identifier column was misaligned with OpenJPA expectations. A newIDcolumn has been added to each table as the JPA identifier, while the existingUIDPKcolumn is retained for backwards compatibility. This fix resolves failures on PostgreSQL, which does not perform the implicit casts that other databases use to work around these inconsistencies. - Fixed a failure in the
reset-dbstep for local Oracle database setup. The Oracle reset script was reworked to drop and recreate the Pluggable Database (orclpdb1) instead of attempting to drop the default permanent tablespace, and theoracle-dev-dbMaven settings profile was updated with corrected defaults (usernameCOMMERCEDB, tablespacesCOMMERCE/COMMERCETEMP). Developers using a local Oracle database will need to update theirsettings.xmlto match the new profile configuration. - The
FACET_GUIDcolumn in theTFACETdatabase table has been renamed toGUIDand a unique constraint has been added to enforce data integrity. TheFacetinterface andFacetImplnow extendEntityinstead ofPersistable, and thegetFacetGuid()/setFacetGuid()methods have been replaced with the standardgetGuid()/setGuid()methods. - Fixed a failure during Liquibase updates where duplicate GUID values in the
TCARTTYPEtable caused a unique constraint violation (I_CARTTYPE_GUID_UNQ) when applying the2026-03-carttype-guid-unique-constraintchangeset; the Liquibase changeset now resolves pre-existing duplicates by reassigning their GUIDs before applying the constraint, and the Import/Export assembler has been corrected to no longer retain cart types that are absent from the import data, which could previously result in duplicate GUIDs being persisted. - A
CREATION_DATEcolumn has been added to theTSHOPPINGCARTtable, andShoppingCartMementoImplnow implements theDatabaseCreationDateinterface so the creation timestamp is automatically populated for new shopping carts. Existing cart records will have anullcreation date. - The
TORDERAUDIT.DETAILdatabase column has been converted from aCLOBtype toVARCHAR(20000), reducing potential performance overhead associated with large object storage for order audit detail records. A database migration will run automatically via Liquibase; note that if any existingDETAILvalues exceed 20,000 characters, the migration will halt and must be resolved before upgrading. - A Liquibase changeset has been added that automatically runs
ANALYZEon PostgreSQL databases during each data population run, ensuring the query planner has up-to-date table statistics. This prevents significant query performance degradation that can occur after a major PostgreSQL version upgrade, which clears existing table statistics.
Supported technology updates
Self-Managed Commerce 8.8.0 is compatible with the following Elastic Path releases:
| Elastic Path Component | Compatibility |
|---|---|
| Extension Point Framework | Extension Point Framework compatibility matrix |
| CloudOps for Kubernetes | CloudOps for Kubernetes compatibility matrix |
| Self-Managed Commerce Docker | Self-Managed Commerce Docker compatibility matrix |
Additionally, the following changes have been made to the Supported Technologies:
- Removed support for MySQL 5.7. MySQL 5.7 reached its end-of-life on October 31, 2023. Customers should upgrade to MySQL 8.0 or MySQL 8.4.
Dependency changes
Many dependencies were updated as part of Self-Managed Commerce 8.8.0. The highlights are shown below:
- Upgraded
ASMfrom 7.x to 9.x. - Upgraded commons-lang from 3.10.x to 3.18.x.
- Upgraded Drools from 7.x to 8.x.
- Upgraded Jackson from 2.19.x to 2.21.x.
- Upgraded Log4j from 2.17.x to 2.25.x.
- Upgraded Logback from 1.2.x to 1.5.x.
- Upgraded okhttp from 3.x to 4.x.
- Upgraded SLF4j from 1.7.x to 2.0.x.
- Upgraded SOLR from 9.8.x to 9.10.x.
- Upgraded Eclipse Sisu from 0.3.5 to 0.9.0.M4.
- Upgraded Eclipse Remote Application Platform from 4.2 to 4.6.
Database changes
- Added new setting definition records:
COMMERCE/SYSTEM/PROMOIQ/enableCOMMERCE/SYSTEM/JOBS/PAUSENONCRITICAL/enabledCOMMERCE/SYSTEM/JOBS/PAUSENONCRITICAL/startsAtCOMMERCE/SYSTEM/JOBS/PAUSENONCRITICAL/expiresAt
- Added new setting value context records:
COMMERCE/SYSTEM/MESSAGING/SHOPPINGCARTS/channelUriwith contextshoppingCartCacheHandler
- Added
TAGREEMENTtable:UIDPK:BIGINTCODE:VARCHAR(50)NAME:VARCHAR(255)DESCRIPTION:VARCHAR(1024)INTERNAL_TYPE:VARCHAR(50)BILLING_FREQENCY:INTAGREEMENT_LENGTH:INTEND_BEHAVIOUR:VARCHAR(50)CANCEL_ALLOWED:BOOLEANPAUSE_ALLOWED:BOOLEAN
- Added
TORDERAGREEMENTtable:UIDPK:BIGINTORDER_UID:BIGINTCODE:VARCHAR(50)NAME:VARCHAR(255)DESCRIPTION:VARCHAR(1024)INTERNAL_TYPE:VARCHAR(50)BILLING_FREQENCY:INTAGREEMENT_LENGTH:INTEND_BEHAVIOUR:VARCHAR(50)CANCEL_ALLOWED:BOOLEANPAUSE_ALLOWED:BOOLEAN- Added index
I_ORDERAGREEMENT_ORDERUIDonORDER_UIDcolumn. - Added foreign key constraint
FK_ORDERAGREEMENT_ORDERUIDonORDER_UIDcolumn (referencingTORDER.UIDPK).
- Added
TORDERLOCALIZEDPROPERTIEStable:UIDPK:BIGINTOBJECT_UID:BIGINTLOCALIZED_PROPERTY_KEY:VARCHAR(255)VALUE:VARCHAR(255)TYPE:VARCHAR(50)- Added index
I_ORDERLOCALIZEDPROPERTIES_OBJECTUIDonOBJECT_UIDcolumn. - Added index
I_ORDERLOCALIZEDPROPERTIES_LOCALIZEDPROPERTYKEYonLOCALIZED_PROPERTY_KEYcolumn. - Added index
I_ORDERLOCALIZEDPROPERTIES_TYPEonTYPEcolumn.
- Added
TORDERSKURECURRINGPRICEPERIODtable:UIDPK:BIGINTORDERSKU_UID:BIGINTRECURRING_PRICE_TYPE:VARCHAR(50)PAYMENT_FREQUENCY_AMOUNT:INTPAYMENT_FREQUENCY_UNIT:VARCHAR(50)PAYMENT_START:INTPAYMENT_END:INTAMOUNT:DECIMAL(19,2)ROLLOVER:BOOLEAN- Added index
I_ORDERSKURECURRINGPRICEPERIOD_ORDERSKUUIDonORDERSKU_UIDcolumn. - Added foreign key constraint
FK_ORDERSKURECURRINGPRICEPERIOD_ORDERSKUUIDonORDERSKU_UIDcolumn (referencingTORDERSKU.UIDPK).
- Modified
TPRICELISTtable:- Added
AGREMENT_CODE:VARCHAR(50)column. - Added index
I_PRICELIST_AGREEMENTCODEonAGREMENT_CODEcolumn. - Added foreign key constraint
FK_PRICELIST_AGREEMENTCODEonAGREMENT_CODEcolumn (referencingTAGREEMENT.CODE).
- Added
- Modified
TBASEAMOUNTtable:- Added
RECURRING_LIST:DECIMAL(19,2)column. - Added
RECURRING_SALE:DECIMAL(19,2)column.
- Added
- Added
TPRODUCTAGREEMENTtable:UIDPK:BIGINTPRODUCT_UID:BIGINTAGREEMENT_CODE:VARCHAR(50)ORDERING:INT- Added index
I_PRODUCTAGREEMENT_PRODUCTUIDonPRODUCT_UIDcolumn. - Added foreign key constraint
FK_PRODUCTAGREEMENT_PRODUCTUIDonPRODUCT_UIDcolumn (referencingTPRODUCT.UIDPK). - Added index
I_PRODUCTAGREEMENT_AGREEMENTCODEonAGREEMENT_CODEcolumn. - Added foreign key constraint
FK_PRODUCTAGREEMENT_AGREEMENTCODEonAGREEMENT_CODEcolumn (referencingTAGREEMENT.CODE).
- Modified
TCARTITEMtable:- Added
AGREEMENT_CODE:VARCHAR(50)column. - Added index
I_CARTITEM_AGREEMENTCODEonAGREEMENT_CODEcolumn. - Added foreign key constraint
FK_CARTITEM_AGREEMENTCODEonAGREEMENT_CODEcolumn (referencingTAGREEMENT.CODE).
- Added
- Modified
TORDERSKUtable:- Added
AGREEMENT_CODE:VARCHAR(50)column. - Added index
I_ORDERSKU_AGREEMENTCODEonAGREEMENT_CODEcolumn. - Added foreign key constraint
FK_ORDERSKU_AGREEMENTCODEonAGREEMENT_CODEcolumn (referencingTAGREEMENT.CODE).
- Added
- Modified
TSTORECARTTYPEtable:- Added index
I_STORECARTTYPE_STOREUIDonSTORE_UIDcolumn. - Added foreign key constraint
FK_STORECARTTYPE_STOREUIDonSTORE_UIDcolumn (referencingTSTORE.UIDPK). - Added index
I_STORECARTTYPE_CARTTYPEUIDonCARTTYPE_UIDcolumn. - Added foreign key constraint
FK_STORECARTTYPE_CARTTYPEUIDonCARTTYPE_UIDcolumn (referencingTCARTTYPE.UIDPK).
- Added index
- Modified
TCARTTYPEMODIFIERStable:- Added index
I_CARTTYPEMODIFIERS_MODIFIERUIDonMODIFIER_UIDcolumn. - Added foreign key constraint
FK_CARTTYPEMODIFIERS_MODIFIERUIDonMODIFIER_UIDcolumn (referencingTMODIFIERGROUP.UIDPK). - Added index
I_CARTTYPEMODIFIERS_CARTTYPEUIDonCARTTYPE_UIDcolumn. - Added foreign key constraint
FK_CARTTYPEMODIFIERS_CARTTYPEUIDonCARTTYPE_UIDcolumn (referencingTCARTTYPE.UIDPK).
- Added index
- Modified
TCARTTYPEtable:- Added unique constraint index
I_CARTTYPE_GUID_UNQonGUIDcolumn.
- Added unique constraint index
- Modified
TORDERNUMBERGENERATORtable:- Added
ID:VARCHAR(50)column.
- Added
- Modified
TRMAGENERATORtable:- Added
ID:VARCHAR(50)column.
- Added
- Modified
TFACETtable:- Renamed
FACET_GUIDcolumn toGUID.
- Renamed
- Modified
TCOUPONUSAGEtable:- Added index
I_TCOUPONUSAGE_CUSTOMEREMAILADDRESSonCUSTOMER_EMAIL_ADDRESScolumn.
- Added index
- Modified
TORDERAUDITtable:- Changed
DETAILcolumn type fromCLOBtoVARCHAR(20000).
- Changed
- Modified
TORDERHOLDtable:- Added cascade delete on
FK_ORDERHOLD_TORDERforeign key.
- Added cascade delete on
- Modified
TSHOPPINGCARTtable:- Added
CREATION_DATE:DATETIMEcolumn.
- Added
- Modified
TOAUTHACCESSTOKENtable:- Dropped foreign key constraint
FK_OAUTH_CUSTOMER.
- Dropped foreign key constraint
- Created
TJOBEXECUTIONtable:UIDPK:BIGINTNAME:VARCHAR(255)LAST_EXECUTION_DATE:TIMESTAMP
- Dropped
TCUSTOMERGROUPROLEXtable.