Broadleaf Microservices
  • v1.0.0-latest-prod

Extension Common Release Notes

Release Notes for 3.0.0

Spring Boot Upgrade

  • As of Broadleaf Release Train 3.0.0-GA, all common libraries have been upgraded to support Spring Boot 4.1 and Java 25.

  • This version includes all changes up to 2.0.8

A Shared, Measurable Connection Pool for Internal Service-to-Service Calls

This release introduces a named connection pool for internal service-to-service traffic, as well as a factory that services build their connectors from, so all of that traffic is pooled and reported in one place.

See A Shared, Measurable Connection Pool for Internal Service-to-Service Calls for a comprehensive overview of how this works and how to utilize it in your own code.

  • When upgrading to 3.0.0, if you are currently overriding the internal connector beans (e.g., pricingClientHttpConnector), it is highly recommended to update them to build from the new CommonInternalServiceClientConnectorFactory instead of defining your own HttpClient directly to take advantage of these shared settings.

Internal Service-to-Service Calls Authorize Off the Request Thread

Under Spring Boot 4, a service-to-service call issued from a background worker or an @Async method can fail to obtain its token if the lookup depends on thread-local state that only exists on a request thread.

A client_credentials access token for an internal call can now be resolved without an ambient request or security context.

See Internal Service-to-Service Calls Authorize Off the Request Thread for more details and how to configure this on a WebClient builder.

Spring Boot 4 Jackson Property Bridging

Spring Boot 4 binds Jackson 2 configuration under spring.jackson2., while Broadleaf remains on Jackson 2. An EnvironmentPostProcessor now mirrors every spring.jackson. property to its spring.jackson2.* counterpart whenever Jackson 2 is the preferred JSON mapper, so existing configuration keeps applying.

  • An explicit spring.jackson2.* value always wins over a mirrored one.

  • For project hygiene, move spring.jackson. properties to spring.jackson2.. See Upgrade to 3.0.0 for the platform-wide picture.

Dedicated Connection Pools for External Third-Party Service Calls

Integrations with external, third-party services now utilize a dedicated blc-external-service external pool so they no longer share configurations with internal service calls.

See Dedicated Connection Pools for External Service Calls for a complete explanation of this new pool and examples of how to override or create customized external connection configurations.

  • Third-party services have been updated to utilize a new commonExtlSvcClientConnector.

  • If you have overridden the WebClient beans for third-party modules (like Adyen or PayPal) in the past, please ensure you update your overrides to similarly inject and use the new ClientHttpConnector beans.

Centralized SSL Configuration Utilities

As part of the external connection pool consolidation, we refactored SSL logic into a CommonWebClientSslUtils to centralize and share the configuration of customized and disabled SSL contexts for HttpClient.

See Centralized SSL Configuration Utilities for more information on how to utilize these utilities.

Release Notes for 2.0.8

Upgrade from Apache Fury to Apache Fory

The default serialization library behind Broadleaf’s Caffeine and EHCache caching support has been Apache Fury.

Starting with Broadleaf Release Trains 3.0.0, 2.2.3, and 2.1.7, Apache Fury has been upgraded to Apache Fory. Apache Fory is a renamed continuation of the original library. While it introduces minor API changes, it brings a host of bugfixes and improvements that warrant the upgrade. Most notably, the upgrade fixes an issue that could corrupt serialized output in highly concurrent environments.

Migration Steps

Warning

Most clients do not need to do anything to absorb this change, as the dependencies and classes involved are rarely directly used or extended outside the framework itself.

However, if your project has explicitly configured or overridden Fury-related behavior, this section provides a short list of key changes that may be required.

Swap the dependency coordinates
<!-- Before -->
<dependency>
    <groupId>org.apache.fury</groupId>
    <artifactId>fury-core</artifactId>
</dependency>

<!-- After -->
<dependency>
    <groupId>org.apache.fory</groupId>
    <artifactId>fory-core</artifactId>
    <!-- Version is managed by the Broadleaf base dependencies pom -->
</dependency>
Rename the Broadleaf serializer and cloner

Both classes stay in com.broadleafcommerce.common.extension.serialization:

Before After

FurySerializer

ForySerializer

FuryCloner

ForyCloner

FurySerializer.getInstance() becomes ForySerializer.getInstance(). The Serializer and Cloner interfaces, and the defaultSerializer and defaultCloner bean names, are unchanged, so a project that injects Serializer or Cloner rather than the implementation needs no change.

Update a custom class checker

If using a custom ClassChecker instead of the default RegexAllowListChecker, it must be migrated to the renamed TypeChecker interface:

Before After

org.apache.fury.resolver.ClassChecker

org.apache.fory.resolver.TypeChecker

checkClass(ClassResolver, String)

checkType(TypeResolver, String)

Update the serialization allow list

The default value of com.broadleafcommerce.serialization.convert.standard-allow-list previously included org.apache.fury.*, but now contains org.apache.fory.* instead. A project that replaced com.broadleafcommerce.serialization.convert.standard-allow-list wholesale, or that added a Fury package to additional-allow-list, must update those entries to point to Fory instead.

Remove the pool properties that no longer exist

Fory’s instance pool is fixed-size and eagerly allocated: max-pool-size instances are created at startup, retained for the pool’s lifetime, and never evicted, and a caller blocks once every instance is checked out. max-pool-size still sets the size, so existing configuration keeps working, but the two properties that described a growing pool no longer map to anything and must be removed from both the convert and clone sections:

Removed property Note

com.broadleafcommerce.serialization.convert.min-pool-size

Remove. The pool has one size, set by max-pool-size.

com.broadleafcommerce.serialization.convert.expire-time-seconds

Remove. Pooled instances are never evicted.

com.broadleafcommerce.serialization.clone.min-pool-size

Remove. The pool has one size, set by max-pool-size.

com.broadleafcommerce.serialization.clone.expire-time-seconds

Remove. Pooled instances are never evicted.

If a deployment set min-pool-size above max-pool-size, review max-pool-size before upgrading - that is now the only size the pool has.

Centralization of Internal Service-to-Service WebClient OAuth2 Token Flows

A variety of Broadleaf microservices and common libraries duplicated the oAuth2FilterFunctionSupplier bean definition for access token management during 'internal' service-to-service communication (ex: services within the same deployment cluster).

In practice, the shared bean name meant that only the configuration defined by one library or service would win in a flexpackage environment (and the winner was non-deterministically determined via Spring auto-configuration ordering). However, the implementation in each service was fulfilled by duplicated definitions of classes such as SynchronizedDelegatingOAuth2AuthorizedClientManager, SSLVerificationProperties, and OAuth2ClientCredentialsAccessTokenResponseClient.

This release of MicroExtensionCommon aims to centralize this logic by superseding the classes/beans defined in the individual services with configuration that is easily overridable when needed.

  • Introduced centralized configuration for the oAuth2FilterFunctionSupplier, including classes for the various components that are involved in supporting this (CommonInternalServiceSynchronizedOAuth2AuthorizedClientManager, CommonInternalServiceSSLVerificationProperties, and CommonOAuth2ClientCredentialsAccessTokenResponseClient)

  • The new configuration is defined with a high autoconfiguration order, guaranteeing that it supersedes the bean and class definitions at the service levels, which all back off due to their @ConditionalOnMissingBean annotations

  • Clients can still override the default filter function supplier bean if necessary by supplying a replacement with the same oAuth2FilterFunctionSupplier name, and ensuring that the configuration registering that bean is ordered ahead of CommonInternalServiceConnectionAutoConfiguration

Enhancement to Increase Token Reuse During Internal Service-to-Service WebClient Flows

In addition to the aforementioned centralization effort, there has also been an enhancement made to improve the reuse of access tokens for service-to-service flows.

OAuth2AuthorizedClientService uses the currently authenticated principal’s name as part of the key to store and load access tokens. This is unnecessary, because the service-to-service calls are a backend implementation flow and are independent of whatever the current authentication may be.

CommonInternalServiceSynchronizedOAuth2AuthorizedClientManager introduces an enhancement to force a consistent principal name in these flows, guaranteeing token reuse regardless of the initiating authentication state.

Bug Fixes

  • Fixed a bug where AutoProjection classes were not whitelisted for Apache Fury serialization by default, preventing caching with Caffeine and EHCache

Release Notes for 2.0.7

Ignite Metrics Collection Changes

  • Ignite metrics collection is resource-expensive and has been disabled by default. Previously, there was no mechanism available to disable this metrics collection. New properties have been introduced to control whether metrics collection is enabled.

  • Ignite metrics collection has been fully reworked with a new implementation.

    • This fixes a variety of bugs, including value miscalculations, overly aggressive metrics gathering in a looping structure, lazily instantiated caches being omitted from metrics, and large numbers of background tasks that continually run and consume resources. Hit percentage is no longer reported, as this can be calculated by the tooling gathering the data.

  • New Caffeine and Ehcache options for Spring Cache. See Caching for more information.

Tomcat Metrics Collection Enhancements

Release Notes for 2.0.6

  • Fix the issue when a currency field can be lost (nulled) during a clone operation. A new ModelMapper converter has been introduced.

  • Fix the rare issue that messaging can be broken and not working silently after the startup.

  • Enhance the provider approach to use a single, unified API for interacting with other service APIs. To provide an approach to call the external API either via webclient, or via reflection. The reflection approach is qualified if the external API happens to be co-located in the same flexpackage

Release Notes for 2.0.5

  • Fix a bug where an infinite loop can occur in ProjectionManager at startup if a projection class is more than 2 levels descended from Object

  • Added support for modernization of Billing Service.

    • Add billing & subscription operations data routes

    • Support ordering of spring cloud stream consumers

    • Add diagnostic logging for message send failures

  • Improved the environment report to skip any unresolvable properties.

  • Improved service-to-service calls within a single flex package to skip overhead of external calls.

    • Added support for optional direct method call in loopback interlink scenarios

    • Disabled by default, see com.broadleafcommerce.common.extension.intercommunication.ExternalClientProperties for details on enabling.

Release Notes for 2.0.4

  • Support non-blocking retry use cases

    • More robust support for message retry handling cases

    • More resilience options around message processing failures

    • Support message takeover for previously abandoned processes

Release Notes for 2.0.3

  • Fixed possible start up errors for pods with dependent services due to said service appearing down despite having available pods.

    • This was happening after one of the dependent service’s pods was evicted.

    • Now the service will be reported as up as long as one of its pods is running, ignoring the evicted pod(s).

Release Notes for 2.0.2

  • Introduce support for extension updates of annotations at the type, method, and field level.

    • Now makes use of byte code weaving to support overriding Annotations a target class, including adding, updating, or deleting annotations.

      Sample Target Class to receive annotation overrides
      @Setter
      @DataRouteByKey("test")
      public class TargetClass {
          @JsonProperty("test")
          private String test;
          @JsonProperty("test")
          private String intersection;
          @JsonProperty("test")
          private String deletion;
          private String notAnnotatedVariable;
          @Transactional("test")
          public String getTest() {
              return test;
          }
          public String updateTest(String test) {
              this.test = test;
              return test;
          }
          public String otherUpdate(@JsonProperty("otherUpdate") String test) {
              this.test = test;
              return test;
          }
          @Transactional("test")
          public String intersectionMethod(@JsonProperty("test") String test, String other) {
              this.test = test;
              return test;
          }
          @Transactional
          @NonNull
          public void deletionMethod(@JsonProperty("test") String test) {
              // do nothing
          }
          public void notAnnotated() {
              // do nothing
          }
      }
      Sample Template Class to provide new annotations
      @DataRouteByKey("changed")
      @Transactional
      public class TemplateClass {
          @JsonProperty("changed")
          private String test;
          @JsonProperty("changed")
          @NonNull
          private String intersection;
          private String deletion;
          @Transactional("changed")
          public String getTest() {
              return test;
          }
          public String updateTest(@NonNull String test) {
              this.test = test;
              return test;
          }
          public String otherUpdate(@JsonProperty("myUpdate") String test) {
              this.test = test;
              return test;
          }
          @NonNull
          @Transactional("changed")
          public String intersectionMethod(@JsonProperty("changed") @NonNull String test,
                  @NonNull String other) {
              this.test = test;
              return test;
          }
          public void deletionMethod(String test) {
              // do nothing
          }
      }
      Sample class-transformation.yaml
      transformations:
        - template: 'com.mycompany.common.extension.loadtimeweaving.TemplateClass'
          target: 'com.mycompany.common.extension.loadtimeweaving.TargetClass'
          transformAnnotations: 'true'
      injectors:
        - 'com.broadleafcommerce.common.extension.ltw.AnnotationClassTransformationInjector'

Ignite Cache Node Configuration Support

  • Introduce new IgniteCacheNodeProperties under broadleaf.common.cache.ignite.node prefix to configure Ignite node memory consumption

  • Reduce default data region maximum size to 1GiB from previous 2GiB

  • Rename IgniteConfiguration bean in IgniteCacheAutoConfiguration from igniteConfiguration to igniteCacheNodeConfiguration, and make the @ConditionalOnMissingBean check by name rather than type to allow other IgniteConfiguration beans to exist in the system for non-cache purposes

    Note
    Clients who are currently overriding this default IgniteConfiguration bean should rename their bean to igniteCacheNodeConfiguration to ensure the CacheManager injects the correct instance.
  • Update CacheManager bean in IgniteCacheAutoConfiguration to inject IgniteConfiguration with @Qualifier in method parameters instead of calling the bean method directly

Release Notes for 2.0.1

  • Workflow transition performance refactoring. See Workflow Transition Performance.

  • Fix message listener extensions no longer receiving messages via the @StreamListener annotated method in the parent class.

2.0.0-GA

Spring Boot Upgrade

  • As of Broadleaf Release Train 2.0.0-GA, all common libraries have been upgraded to Spring Boot 3.

  • This version includes all changes up to 1.4.20-GA

Release Notes for 1.4.20

  • Add check to prevent ClassCastExceptions in DataRouteByKeyAspect.

Release Notes for 1.4.19

  • Fix issue reporting on properties that have a placeholder reference to another property.

Release Notes for 1.4.18

  • Fixed type mismatch bug causing missing properties in the Environment Report.

Release Notes for 1.4.17

  • Fixed possible duplication of cache keys when caching a method’s result that takes a list of inputs (e.g., a list of context IDs).

NOTE Build errors resulted in gap from v1.4.14 - v1.4.16

Release Notes for 1.4.13

  • Introduced basic tenant discriminated property support with auto refresh enhancement

  • Added enhancements for streamlined extension experience

  • Introduced support for ModelMapper cache as maven compile lifecycle step

  • Added a library of routes for easy route demarcation configuration

Release Notes for 1.4.12

  • Support resetting the blocking status on a LazyCacheController instance

Release Notes for 1.4.11

  • Fixed the issue where it’s possible (e.g. during startup) that a data route may not be available when/if a flow is engaged that exercises the LazyCacheController compilation logic

  • Fixed the issue where it’s possible (e.g. during startup) that a data route may not be available when/if a flow is engaged that exercises the LazyCacheController compilation logic

Release Notes for 1.4.10

  • Add more debug logging for why the conditions of lazy full cache expiry are not met

  • Fixed the issue where it’s possible (e.g. during startup) that a data route may not be available when/if a flow is engaged that exercises the LazyCacheController compilation logic

Release Notes for 1.4.9

  • Fixed the issue where the LazyCacheController process is not resetting the cache member TTL upon full cache build

Release Notes for 1.4.8

  • Fixed CacheStateManager may return incorrect results during cache fetch

Release Notes for 1.4.7

  • Respond with the evicted cache members during an eviction call.