Broadleaf Microservices
  • v1.0.0-latest-prod

Upgrade to 2.0.0-GA Additional Notes

Spring Security

  • Broadleaf’s OAuth2 resource server and client functionality was already migrated long ago off of the deprecated Spring Security OAuth library and onto first-class Spring Security OAuth2 modules. Thus, the migration guide for resource server and client logic is no longer needed/applicable.

  • Update password encoding

    • The PasswordEncoder migration steps described here only apply to Pbkdf2PasswordEncoder, SCryptPasswordEncoder, and Argon2PasswordEncoder. Broadleaf uses BCryptPasswordEncoder, and thus no change is necessary.

  • Stop using Encryptors.queryableText

    • Broadleaf is already not using the Encryptors.queryableText function anywhere, so no changes required.

  • Session management

    • Require Explicit Saving of SecurityContextRepository

      • No change needed because Broadleaf already uses .sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS), and we do not save authentications in SecurityContextRepository

    • Change HttpSessionSecurityContextRepository to DelegatingSecurityContextRepository

      • No change needed because Broadleaf already uses .sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS), and we do not save authentications in SecurityContextRepository

    • Address SecurityContextRepository Deprecations

      • No change needed because Broadleaf already uses .sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS), and we do not save authentications in SecurityContextRepository

    • Optimize Querying of RequestCache

      • This is a performance optimization limited to those who are using HttpSessionRequestCache. Two classes have been affected by this: HttpSessionRequestCache, and DefaultSavedRequest.

        • In 5, HttpSessionRequestCache can optionally accept a value for matchingRequestParameterName, and if set explicitly, it will cause the cache to create the DefaultSavedRequest with that parameter set. Then, on attempts to fetch the saved request, a query will only be performed by HttpSessionRequestCache if the received request contains that parameter.

        • In 6, HttpSessionRequestCache comes by default with matchingRequestParameterName set to continue, changing the behavior to opt-out rather than opt-in. DefaultSavedRequest itself continues to have that parameter null by default, so consumers other than HttpSessionRequestCache which call its constructors will not see continue set.

      • Broadleaf does not use HttpSessionRequestCache and we instead have our own CookieRequestCache. We create DefaultSavedRequest with the DefaultSavedRequest(HttpServletRequest request, PortResolver portResolver) constructor, which continues to set matchingRequestParameterName to null. This means our DefaultSavedRequest will not have any extra parameter set, and our cache will continue not checking for such a parameter before looking for a matching request. This is fine, as examining cookies is not expensive like querying for an HTTP session is. Thus, no action is required.

    • Require Explicit Invocation of SessionAuthenticationStrategy

      • The explanation provided in the migration guide as well as in this comment indicates that the goal of this change is to force each individual authentication filter to directly invoke SessionAuthenticationStrategy as needed. In theory, this means those who use HttpSession will no longer incur the penalty of having it forcefully read each time.

      • Broadleaf has simply set http.sessionManagement().requireExplicitAuthenticationStrategy(false) to restore the traditional behavior and continue using SessionManagementFilter. We don’t use HttpSession anyway, so we aren’t paying any performance penalty.

  • Exploit protection

    • In Broadleaf, CSRF is disabled in all projects except AuthenticationServices, as it is not applicable to our REST APIs.

    • In AuthenticationServices, we use CookieCsrfTokenRepository.

    • Defer Loading CsrfToken

      • In Spring Security 6, the CSRF token is only loaded 'when needed' rather than always.

      • Here are the behavioral differences observed with this change in Broadleaf on a standard visit to the admin site:

        • With the old defaults, the Set-Cookie for XSRF-TOKEN came with the response to /auth/client-discovery?type=ADMIN

        • With the new defaults, the Set-Cookie for XSRF-TOKEN came later, in response to /auth/login?client_id=admin

      • Ultimately, this change is mostly invisible/benign.

    • Protect against CSRF BREACH

      • The XorCsrfTokenRequestAttributeHandler is now the default CsrfTokenRequestHandler implementation and provides CSRF BREACH protection.

      • As a result, the _csrf token value in response bodies (forms) is now a specially encoded value derived from the raw value in the XSRF-TOKEN cookie.

        • Ultimately, this change is mostly invisible/benign, but there may be some impact on integration tests using 'real' requests (ex: RestAssured instead of Spring Mock MVC). For example, any test that is currently extracting the raw token value from the XSRF-TOKEN cookie and passing that directly in the next request will fail. The suggested workaround is to pre-process that raw token value before submitting the request, ideally with the same encoding logic used in XorCsrfTokenRequestAttributeHandler.createXoredCsrfToken. This effectively mimics the token the server is producing in the initial response.

    • CSRF BREACH with WebSocket support

      • Broadleaf does not use WebSockets anywhere at this time.

  • Configuration

    • Add @Configuration annotation

      • @EnableWebSecurity

        • Broadleaf already had @Configuration explicitly on OAuth2ResourceWebSecurityConfiguration, which used this annotation

      • @EnableMethodSecurity

        • Broadleaf did not use this anywhere

      • @EnableGlobalMethodSecurity

        • Broadleaf already had @Configuration explicitly on OAuth2ResourceWebSecurityConfiguration, which used this annotation

    • Use the new requestMatchers methods.

      • Handled by the upgrade plugin

      • The idea behind this is pretty straightforward - mvcMatchers matches more paths than antMatchers, so Spring’s new requestMatchers method now tries to use mvcMatchers semantics whenever possible by default and only falls back to antMatchers if Spring MVC is unavailable.

      • Broadleaf used antMatchers in many places throughout the framework, and all have been migrated to the new syntax

        • In many cases, ant-matching semantics were still explicitly required. For example, some paths did not contain the /** segment, and were used to ignore security. Since MVC-matchers will match more variations, this would have reduced security on subpaths of things like /oauth/authorize. In cases like this, AntPathRequestMatcher.antMatcher() is used to explicitly retain ant-matching behavior.

      • Broadleaf used mvcMatchers in a handful of places, and all have been migrated directly to use requestMatchers, as MVC match behavior should continue with no changes

      • Broadleaf did not use regexMatchers anywhere

    • Use the new securityMatchers methods

      • Broadleaf only had a few uses of the old methods in OAuth2ResourceWebSecurityConfiguration. Those have been migrated to securityMatchers, but still explicitly retain ant-matching semantics as before via AntPathRequestMatcher.antMatcher().

    • Stop Using WebSecurityConfigurerAdapter

      • configure(HttpSecurity http) has been replaced with SecurityFilterChain beans, most notably in OAuth2ResourceWebSecurityConfiguration and AuthorizationServerWebSecurityConfiguration

        Note
        The automated upgrade tool will attempt to migrate simple cases of this for you.
      • configure(WebSecurity web) has been replaced with WebSecurityCustomizer beans, most notably in ForwardedHeaderSecurityConfiguration (in sample configuration)

      • configure(AuthenticationManagerBuilder) has been replaced with a new global AuthenticationManager bean-based configuration (only relevant in AuthorizationServerWebSecurityConfiguration)

  • Authentication

    • Use SHA-256 in Remember Me

      • Broadleaf does not make any use of TokenBasedRememberMeServices or any other 'Remember Me' functionality. No changes required.

    • Propagate AuthenticationServiceExceptions

      • AuthenticationServiceException, as well as InternalAuthenticationServiceException (its only extension) are used to indicate a server-side error has occurred during authentication.

      • The specific documented changes relate to AuthenticationFilter and AuthenticationEntryPointFailureHandler.

        • AuthenticationFilter is an instance of OncePerRequestFilter, and is not used in Broadleaf.

      • In ResourceSecurityDsl, Broadleaf uses http.oauth2ResourceServer(). This implicitly configures a BearerTokenAuthenticationFilter. All the way back in 5.5.0, due to this issue, BearerTokenAuthenticationFilter was already updated to rethrow AuthenticationServiceException by default. The only change going into 6.0 is that this behavior is now moved to also use AuthenticationEntrypointFailureHandler. Importantly, the semantics remain the same.

        • Thus, with the use of BearerTokenAuthenticationFilter, Broadleaf is already implicitly rethrowing the AuthenticationServiceException and 6.0 introduces no change in behavior.

      • Broadleaf does directly reference AuthenticationServiceException and InternalAuthenticationServiceException in a few places. In most scenarios, we throw these exceptions if some key validations fail. Furthermore, in EmbeddedLoginAuthenticationFilter and FormLoginAuthenticationFilter, there is already logic to catch these exceptions and rethrow them.

        • Thus, no change is required.

  • Authorization

    • General context: Spring Security authorization previously used AccessDecisionManager and AccessDecisionVoter, but this has been deprecated in favor of the AuthorizationManager, described here. Further description of Request Authorization is here.

    • Use AuthorizationManager for Method Security

      • Replace global method security with method security.

        • Replaced @EnableGlobalMethodSecurity(prePostEnabled = true) with @EnableMethodSecurity in OAuth2ResourceWebSecurityConfiguration, as they are functionally equivalent

        • After making this change, methods annotated with @PreAuthorize correctly cause AuthorizationManagerBeforeMethodInterceptor to throw AccessDeniedException when appropriate, but this exception is not handled by ExceptionTranslationFilter or AccessDeniedHandler, and thus the HTTP response is 500 instead of 403. There is an open bug in Spring about this.

          • As a workaround for now, we have introduced a new AccessDeniedExceptionAdvisor which will continue to return 403 responses in such cases.

      • Change the order value in @EnableTransactionManagement

        • Broadleaf does not use this annotation anywhere. No changes required.

      • Use a Custom @Bean instead of subclassing DefaultMethodSecurityExpressionHandler

        • Broadleaf does not reference DefaultMethodSecurityExpressionHandler anywhere. No changes required.

      • Publish a MethodSecurityExpressionHandler instead of a PermissionEvaluator

        • Broadleaf uses a DenyAllPermissionEvaluator in PolicySecurityExpressionRoot, but this is not published as a bean. No changes required.

      • Replace any custom method-security AccessDecisionManagers

        • Broadleaf does not have any custom method security AccessDecisionManagers. Thus far, we have used the AccessDecisionManager from GlobalMethodSecurityConfiguration.accessDecisionManager(), which is AffirmativeBased and contains PreInvocationAuthorizationAdviceVoter, RoleVoter, and AuthenticatedVoter.

        • With @EnableMethodSecurity, the configuration will now come from PrePostMethodSecurityConfiguration and MethodSecurityAdvisorRegistrar. Spring says this behavior now defaults to UnanimousBased semantics. They also provide an example of what the default configuration looks like.

        • Broadleaf does not require any special changes and can lean on the defaults, since the default voters usually don’t overlap in what they vote on and thus changes in unanimous/affirmative semantics do not matter.

      • Check for AnnotationConfigurationExceptions

        • This involves checking runtime logs to see if there are any exceptions thrown due to stricter annotation validations.

        • Out of box, Broadleaf does not require any changes.

    • Use AuthorizationManager for Message Security

      • This section is specifically regarding WebSocket messages, which do not apply to Broadleaf since we don’t use WebSocket at this time.

    • Use AuthorizationManager for Request Security

      • Ensure that all requests have defined authorization rules

        • The new Spring Security 6.0 defaults effectively set .anyRequest().denyAll() at the end of configuration.

        • In OAuth2ResourceWebSecurityConfiguration, Broadleaf already explicitly configures 'default' request authorization against /** depending on the value of broadleaf.resource.security.oauth2.defaultAllowAllAnonymous.

          • Semantically, this means we’ve already defined default rules for all non-explicitly-configured requests.

          • Nonetheless, for completeness (and potential performance benefits by skipping ant matching), we updated the syntax from requestMatchers("/**") to anyRequest(). This should be a safe and transparent change, since that configuration is applied after all SecurityEnhancers run.

        • In AuthorizationServerWebSecurityConfiguration, Broadleaf was already using .anyRequest().authenticated(). No change is required here.

      • Switch to AuthorizationManager

        • This section is about changing http.authorizeRequests() to use the new http.authorizeHttpRequests() functionality that leverages AuthorizationFilter/AuthorizationManager rather than FilterSecurityInterceptor.

      • Handled by the upgrade plugin

      • Migrate hasIpAddress to access(AuthorizationManager)

        • Broadleaf does not use this. No changes required.

      • Migrate SpEL expressions to AuthorizationManager

        • Broadleaf does not use SpEL expressions directly in authorizeRequests() or use the access() method. No changes required.

      • Switch to filter all dispatcher types

        • In 6.0, all dispatcher types are automatically filtered by default. The recommendation is to selectively permit access to specific dispatcher types instead.

        • In AuthenticationServices, we have introduced a DispatcherTypeAuthorizationConfigurer component to permit unauthorized access to dispatcher types specified in the new broadleaf.auth.security.dispatcherTypeAuthorization.dispatcherTypeMatchersPermittedWithoutAuthorization property. By default, we allow FORWARD to allow MVC forwarding to views.

        • In the common OAuth2ResourceWebSecurityConfiguration, we now permit unauthorized access to dispatcher types specified in the new broadleaf.resource.security.oauth2.dispatcherTypeMatchersPermittedWithoutAuthorization property. By default, we allow FORWARD to allow MVC forwarding to views, and ASYNC, which was required for the admin metadata service.

      • Replace any custom filter-security AccessDecisionManagers

        • Broadleaf does not directly use AccessDecisionManager or AccessDecisionVoter. No changes required.

      • Replace hasRole with hasAuthority if using GrantedAuthorityDefaults

        • Broadleaf does not use GrantedAuthorityDefaults. No changes required.

  • OAuth

    • Change Default oauth2Login() Authorities

      • The oauth2Login() method is related to SSO support for 3rd party IDP.

      • Broadleaf does not use ROLE_USER anywhere, so no changes are required.

    • Address OAuth2 Client Deprecations

      • ServletOAuth2AuthorizedClientExchangeFilterFunction

        • Broadleaf does not use the setAccessTokenExpiresSkew or setClientCredentialsTokenResponseClient methods from this class. No changes required.

      • OidcUserInfo

        • Broadleaf does not use phoneNumberVerified from this class. No changes required.

      • OAuth2AuthorizedClientArgumentResolver

        • Broadleaf does not use setClientCredentialsTokenResponseClient from this class. No changes required.

      • ClaimAccessor

        • Broadleaf does not use containsClaim. No changes required.

      • OidcClientInitiatedLogoutSuccessHandler

        • Broadleaf does not use setPostLogoutRedirectUri. No changes required.

      • HttpSessionOAuth2AuthorizationRequestRepository

        • Broadleaf does not use setAllowMultipleAuthorizationRequests. No changes required.

      • AuthorizationRequestRepository

        • BroadleafAuthorizationRequestRepository did define removeAuthorizationRequest(HttpServletRequest) to satisfy the interface requirements, but it threw UnsupportedOperationException and was not used anywhere. It is now removed.

      • ClientRegistration

        • Replaced miscellaneous uses of redirectUriTemplate in AuthenticationServices with redirectUri. Notably, the Broadleaf-specific OAuthClientRegistrationWrapper and JpaOAuthClientRegistration classes are excluded from this change and continue with their existing naming.

      • ClientRegistration.Builder

        • Replaced miscellaneous uses of redirectUriTemplate in AuthenticationServices with redirectUri. Notably, the Broadleaf-specific OAuthClientRegistrationWrapper and JpaOAuthClientRegistration classes are excluded from this change and continue with their existing naming.

      • AbstractOAuth2AuthorizationGrantRequest

        • Broadleaf does not directly use AbstractOAuth2AuthorizationGrantRequest(AuthorizationGrantType). No changes required.

      • ClientAuthenticationMethod

        • ClientAuthenticationMethod.BASIC and ClientAuthenticationMethod.POST have been replaced with CLIENT_SECRET_BASIC and CLIENT_SECRET_POST. This includes their underlying values: basic -> client_secret_basic, and post -> client_secret_post.

        • Now that the old constants are fully unsupported, Broadleaf’s ConstantUtils class (previously introduced to support both old and new constants) is removed.

        • Admin metadata for AuthenticationServices has been updated to use the new values instead of the old values.

        • ClientAuthenticationMethod is persisted in JpaOAuthClientRegistration, and Liquibase changesets have been introduced to migrate any existing values in the database away from basic and post to the new constants.

        • Broadleaf clients who use the property-based client registration approach will almost never explicitly specify spring.security.oauth2.client.registration.{id}.clientAuthenticationMethod (and thus default to a valid Spring-provided value). However, if clientAuthenticationMethod is explicitly specified with one of the old values, it will need to be updated.

      • OAuth2AccessTokenResponseHttpMessageConverter

        • Broadleaf does not use tokenResponseConverter, setTokenResponseConverter, tokenResponseParametersConverter, or setTokenResponseParametersConverter. No changes required.

      • NimbusAuthorizationCodeTokenResponseClient

        • Broadleaf does not use NimbusAuthorizationCodeTokenResponseClient. No changes required.

      • NimbusJwtDecoderJwkSupport

        • Broadleaf does not use NimbusJwtDecoderJwkSupport. No changes required.

      • ImplicitGrantConfigurer

        • Broadleaf does not use ImplicitGrantConfigurer. No changes required.

      • AuthorizationGrantType

        • Broadleaf does not use AuthorizationGrantType.IMPLICIT. No changes required.

      • OAuth2AuthorizationResponseType

        • Broadleaf does not use OAuth2AuthorizationResponseType.TOKEN. No changes required.

      • OAuth2AuthorizationRequest

        • Broadleaf does not use OAuth2AuthorizationRequest.implicit

    • Address JwtAuthenticationConverter Deprecation

      • Broadleaf does not directly use or extend JwtAuthenticationConverter or its extractAuthorities method.

      • Broadleaf’s DefaultJwtBearerTokenAuthenticationConverter does have an extractAuthorities method, but this is a custom-defined method and not an override or reference to anything else.

      • No changes required.

  • SAML

    • Broadleaf does not use SAML. No changes required.

  • CAS

    • Broadleaf does not use CAS. No changes required.

Spring Boot 3

  • The default format for the date and time component of log messages for Logback and Log4j2 has changed to align with the ISO-8601 standard.

    • Broadleaf does not directly alter this format, but you can edit the format accordingly if the change is undesired.

  • YamlJsonParser is removed

  • Trailing slash URL matching is removed in Spring MVC and Webflux.

    • Broadleaf has re-introduced this support, so no changes required.

  • Apache HttpClient has been removed from RestTemplate

    • Replaced by HttpClient5

    • This dependency should already be available transitively to your project, should you require a change here

  • While not directly required for a Broadleaf 2.0.0 upgrade, if you use Spring Actuator, you should be aware of some changes.

  • While not directly required for a Broadleaf 2.0.0 upgrade, if you use Micrometer to gather and export metrics, you should be aware of some changes.

Spring Cloud

  • In the latest Spring Cloud Stream, Spring has removed support for annotation based configuration in favor of a functional approach.

    • Broadleaf has re-introduced the removed annotations and includes backward compatible support for the existing Spring Cloud Stream configuration in your project. No change is required.

    • This compatibility layer requires the introduction of two new BLC dependencies for any project module that leverages Spring Cloud Stream messaging. The introduction of these dependencies is generally handled automatically by the upgrade plugin.

    • If the upgrade plugin fails to add the compatibility dependencies for a relevant project module, you can manually add them yourself. They are:

      <dependency>
          <groupId>com.broadleafcommerce.microservices</groupId>
          <artifactId>broadleaf-common-extension-compatibility</artifactId>
      </dependency>
      <dependency>
          <groupId>com.broadleafcommerce.microservices</groupId>
          <artifactId>broadleaf-common-extension-compatibility-test</artifactId>
          <scope>test</scope>
      </dependency>
    • However, you are free to use the new function-based approach for your own messaging configuration. In fact, the backward compatibility support uses the function approach behind the scenes.

IntelliJ Run Configuration VM Options

--add-opens=jdk.management/com.sun.management.internal=ALL-UNNAMED
--add-opens=java.base/jdk.internal.misc=ALL-UNNAMED
--add-opens=java.base/sun.nio.ch=ALL-UNNAMED
--add-opens=java.management/com.sun.jmx.mbeanserver=ALL-UNNAMED
--add-opens=jdk.internal.jvmstat/sun.jvmstat.monitor=ALL-UNNAMED
--add-opens=java.base/sun.reflect.generics.reflectiveObjects=ALL-UNNAMED
--add-opens=java.base/java.io=ALL-UNNAMED
--add-opens=java.base/java.nio=ALL-UNNAMED
--add-opens=java.base/java.util=ALL-UNNAMED
--add-opens=java.base/java.lang=ALL-UNNAMED
--add-opens=java.base/java.lang.reflect=ALL-UNNAMED
--add-opens=java.base/java.lang.invoke=ALL-UNNAMED
--add-opens=java.base/java.time=ALL-UNNAMED
--add-opens=java.base/java.time.format=ALL-UNNAMED

Upgraded Gateway Pom File Examples

  • Root Pom Example

    <?xml version="1.0" encoding="UTF-8" standalone="no"?>
    <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
        <modelVersion>4.0.0</modelVersion>
        <groupId>com.broadleafcommerce.microservices</groupId>
        <artifactId>broadleaf-microservices-gateways-parent</artifactId>
        <version>1.4.12-GA</version>
        <packaging>pom</packaging>
        <name>Broadleaf Microservices Gateways Parent</name>
        <description>
            Parent project that holds Spring Cloud Gateway implementations that hold links to
            the other backend services (and to communicate to the backend portion of a frontend app).
            Allows a centralized point for requests to start to avoid implementing CORS.
        </description>
        <repositories>
            <repository>
                <id>broadleaf-microservices</id>
                <url>https://repository.broadleafcommerce.com/repository/microservices/</url>
            </repository>
        </repositories>
        <pluginRepositories>
            <pluginRepository>
                <id>broadleaf-microservices</id>
                <url>https://repository.broadleafcommerce.com/repository/microservices/</url>
            </pluginRepository>
        </pluginRepositories>
        <scm>
            <connection>scm:git:git@github.com:BroadleafCommerce/MicroservicesGateways.git</connection>
            <developerConnection>scm:git:git@github.com:BroadleafCommerce/MicroservicesGateways.git
            </developerConnection>
            <url>https://github.com/BroadleafCommerce/MicroservicesGateways</url>
            <tag>broadleaf-microservices-gateways-parent-1.4.12-GA</tag>
        </scm>
        <properties>
            <broadleaf.common.dependencies.version>2.0.0-GA</broadleaf.common.dependencies.version>
            <broadleaf.base.dependencies.version>2.0.0-GA</broadleaf.base.dependencies.version>
            <!--
                <broadleaf.base.dependencies.version>1.9999.0-SNAPSHOT</broadleaf.base.dependencies.version>
                <broadleaf.common.dependencies.version>1.9999.0-SNAPSHOT</broadleaf.common.dependencies.version>
            -->
            <blc.config.client.version>2.0.0-GA</blc.config.client.version>
            <blc.starter.version>1.1.0-GA</blc.starter.version>
            <skipAssembly>false</skipAssembly>
            <maven.compiler.release>17</maven.compiler.release>
            <resource.delimiter>@</resource.delimiter>
            <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
            <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
            <maven-compiler-plugin.version>3.11.0</maven-compiler-plugin.version>
            <spring.boot.maven.plugin.version>3.1.2</spring.boot.maven.plugin.version>
            <maven.surefire.version>2.22.2</maven.surefire.version>
            <maven.flatten.plugin.version>1.2.7</maven.flatten.plugin.version>
            <maven.spotless.plugin.version>1.31.3</maven.spotless.plugin.version>
            <maven.spotless.java.formatter.version>4.13.0</maven.spotless.java.formatter.version>
            <broadleaf.codestyle.version>1.0.1-GA</broadleaf.codestyle.version>
            <shared.codestyle.directory>${project.build.directory}/shared-codestyle-resources</shared.codestyle.directory>
            <maven.cyclonedx.version>2.0.3</maven.cyclonedx.version>
            <maven.lombok.plugin.version>1.18.20.0</maven.lombok.plugin.version>
            <lombok.version>1.18.24</lombok.version>
            <maven-javadoc-plugin.version>3.3.1</maven-javadoc-plugin.version>
            <exec.maven.plugin.version>1.6.0</exec.maven.plugin.version>
            <dockerDeploymentRepository>repository.broadleafcommerce.com:5001</dockerDeploymentRepository>
            <dockerBuildBootLayerImageRegistry>repository.broadleafcommerce.com:5001</dockerBuildBootLayerImageRegistry>
            <buildLocalDockerOnly>false</buildLocalDockerOnly>
            <java.17.options>--add-opens=jdk.management/com.sun.management.internal=ALL-UNNAMED
                --add-opens=java.base/jdk.internal.misc=ALL-UNNAMED
                --add-opens=java.base/sun.nio.ch=ALL-UNNAMED
                --add-opens=java.management/com.sun.jmx.mbeanserver=ALL-UNNAMED
                --add-opens=jdk.internal.jvmstat/sun.jvmstat.monitor=ALL-UNNAMED
                --add-opens=java.base/sun.reflect.generics.reflectiveObjects=ALL-UNNAMED
                --add-opens=java.base/java.io=ALL-UNNAMED
                --add-opens=java.base/java.nio=ALL-UNNAMED
                --add-opens=java.base/java.util=ALL-UNNAMED
                --add-opens=java.base/java.lang=ALL-UNNAMED
                --add-opens=java.base/java.lang.reflect=ALL-UNNAMED
                --add-opens=java.base/java.lang.invoke=ALL-UNNAMED
                --add-opens=java.base/java.time=ALL-UNNAMED
                --add-opens=java.base/java.time.format=ALL-UNNAMED</java.17.options>
        </properties>
        <build>
            <pluginManagement>
                <plugins>
                    <plugin>
                        <groupId>org.apache.maven.plugins</groupId>
                        <artifactId>maven-dependency-plugin</artifactId>
                        <executions>
                            <execution>
                                <id>unpack-shared-codestyle-resources</id>
                                <goals>
                                    <goal>unpack</goal>
                                </goals>
                                <phase>initialize</phase>
                                <configuration>
                                    <artifactItems>
                                        <artifact>
                                            <groupId>com.broadleafcommerce</groupId>
                                            <artifactId>broadleaf-codestyle-resources</artifactId>
                                            <version>${broadleaf.codestyle.version}</version>
                                            <outputDirectory>${shared.codestyle.directory}</outputDirectory>
                                        </artifact>
                                    </artifactItems>
                                </configuration>
                            </execution>
                        </executions>
                    </plugin>
                    <plugin>
                        <groupId>com.diffplug.spotless</groupId>
                        <artifactId>spotless-maven-plugin</artifactId>
                        <version>${maven.spotless.plugin.version}</version>
                        <executions>
                            <execution>
                                <id>check</id>
                                <goals>
                                    <goal>check</goal>
                                </goals>
                            </execution>
                        </executions>
                        <configuration>
                            <java>
                                <eclipse>
                                    <version>${maven.spotless.java.formatter.version}</version>
                                    <file>${shared.codestyle.directory}/eclipse-formatter.xml</file>
                                </eclipse>
                                <importOrder>
                                    <file>${shared.codestyle.directory}/broadleaf-java.importorder</file>
                                </importOrder>
                                <removeUnusedImports/>
                            </java>
                            <formats>
                                <format>
                                    <!-- XML files -->
                                    <includes>
                                        <include>src/main/**/*.xml</include>
                                        <include>pom.xml</include>
                                    </includes>
                                    <excludes>
                                        <exclude>src/main/resources/rebel-remote.xml</exclude>
                                        <exclude>src/main/resources/rebel.xml</exclude>
                                        <exclude>**/target/**/pom.xml</exclude>
                                        <exclude>**/node_modules/**</exclude>
                                    </excludes>
                                    <eclipseWtp>
                                        <type>XML</type>
                                        <files>${shared.codestyle.directory}/xml.prefs</files>
                                    </eclipseWtp>
                                    <indent>
                                        <spaces>true</spaces>
                                        <spacesPerTab>4</spacesPerTab>
                                    </indent>
                                    <trimTrailingWhitespace/>
                                </format>
                                <format>
                                    <includes>
                                        <!-- YAML -->
                                        <include>src/main/**/*.yml</include>
                                        <include>src/main/**/*.yaml</include>
                                        <!-- JS within Java projects -->
                                        <include>src/main/**/*.js</include>
                                        <!-- SQL imports -->
                                        <include>src/main/**/*.sql</include>
                                    </includes>
                                    <excludes>
                                        <exclude>**/node_modules/**</exclude>
                                    </excludes>
                                    <indent>
                                        <spaces>true</spaces>
                                        <spacesPerTab>2</spacesPerTab>
                                    </indent>
                                    <trimTrailingWhitespace/>
                                </format>
                            </formats>
                        </configuration>
                    </plugin>
                    <plugin>
                        <groupId>org.apache.maven.plugins</groupId>
                        <artifactId>maven-compiler-plugin</artifactId>
                        <version>${maven-compiler-plugin.version}</version>
                        <configuration>
                            <parameters>true</parameters>
                        </configuration>
                    </plugin>
                    <plugin>
                        <groupId>org.springframework.boot</groupId>
                        <artifactId>spring-boot-maven-plugin</artifactId>
                        <version>${spring.boot.maven.plugin.version}</version>
                        <executions>
                            <execution>
                                <id>repackage</id>
                                <goals>
                                    <goal>repackage</goal>
                                </goals>
                            </execution>
                        </executions>
                        <configuration>
                            <mainClass>${start-class}</mainClass>
                        </configuration>
                    </plugin>
                    <plugin>
                        <!-- IMPORTANT: once this updates to the 3.0 line, we can remove the disableClassPathURLCheck
                            arg line settings -->
                        <!-- See https://stackoverflow.com/questions/53010200/maven-surefire-could-not-find-forkedbooter-class/53016532 -->
                        <groupId>org.apache.maven.plugins</groupId>
                        <artifactId>maven-surefire-plugin</artifactId>
                        <version>${maven.surefire.version}</version>
                        <configuration>
                            <argLine>
                                ${java.17.options}
                                -Djdk.net.URLClassPath.disableClassPathURLCheck=true
                                -Xmx1g
                            </argLine>
                            <!-- Workaround to ensure @Nested classes are executed see https://github.com/junit-team/junit5/issues/1377#issuecomment-381964988 -->
                            <excludes>
                                <exclude/>
                            </excludes>
                            <skip>false</skip>
                        </configuration>
                    </plugin>
                    <plugin>
                        <groupId>org.codehaus.mojo</groupId>
                        <artifactId>exec-maven-plugin</artifactId>
                        <version>${exec.maven.plugin.version}</version>
                    </plugin>
                    <plugin>
                        <groupId>org.codehaus.mojo</groupId>
                        <artifactId>keytool-maven-plugin</artifactId>
                        <version>1.5</version>
                        <executions>
                            <execution>
                                <goals>
                                    <goal>generateKeyPair</goal>
                                </goals>
                                <phase>generate-resources</phase>
                            </execution>
                        </executions>
                        <configuration>
                            <keystore>${project.basedir}/src/main/resources/local.keystore
                            </keystore>
                            <storetype>pkcs12</storetype>
                            <storepass>storepass</storepass>
                            <alias>foo_alias</alias>
                            <dname>cn=localhost, ou=None, L=Dallas, ST=Texas, o=LocalCom, c=US
                            </dname>
                            <sigalg>SHA256withRSA</sigalg>
                            <ext/>
                            <validity>100</validity>
                            <keyalg>RSA</keyalg>
                            <keysize>2048</keysize>
                            <skipIfExist>true</skipIfExist>
                        </configuration>
                    </plugin>
                    <plugin>
                        <groupId>org.cyclonedx</groupId>
                        <artifactId>cyclonedx-maven-plugin</artifactId>
                        <version>${maven.cyclonedx.version}</version>
                        <executions>
                            <execution>
                                <phase>verify</phase>
                                <goals>
                                    <goal>makeAggregateBom</goal>
                                </goals>
                            </execution>
                        </executions>
                        <configuration>
                            <projectType>library</projectType>
                            <schemaVersion>1.2</schemaVersion>
                            <includeBomSerialNumber>true</includeBomSerialNumber>
                            <includeCompileScope>true</includeCompileScope>
                            <includeProvidedScope>true</includeProvidedScope>
                            <includeRuntimeScope>true</includeRuntimeScope>
                            <includeSystemScope>true</includeSystemScope>
                            <includeTestScope>false</includeTestScope>
                            <includeLicenseText>false</includeLicenseText>
                            <outputFormat>all</outputFormat>
                        </configuration>
                    </plugin>
                    <plugin>
                        <groupId>org.projectlombok</groupId>
                        <artifactId>lombok-maven-plugin</artifactId>
                        <version>${maven.lombok.plugin.version}</version>
                        <executions>
                            <execution>
                                <phase>generate-sources</phase>
                                <goals>
                                    <goal>delombok</goal>
                                </goals>
                            </execution>
                        </executions>
                        <configuration>
                            <addOutputDirectory>false</addOutputDirectory>
                            <outputDirectory>${project.build.directory}/delombok</outputDirectory>
                            <sourceDirectory>src/main/java</sourceDirectory>
                        </configuration>
                        <dependencies>
                            <dependency>
                                <groupId>org.projectlombok</groupId>
                                <artifactId>lombok</artifactId>
                                <version>${lombok.version}</version>
                            </dependency>
                        </dependencies>
                    </plugin>
                    <plugin>
                        <groupId>org.apache.maven.plugins</groupId>
                        <artifactId>maven-javadoc-plugin</artifactId>
                        <version>${maven-javadoc-plugin.version}</version>
                        <executions>
                            <execution>
                                <id>attach-javadocs</id>
                                <goals>
                                    <goal>jar</goal>
                                </goals>
                            </execution>
                        </executions>
                        <configuration>
                            <defaultVersion>${project.version}</defaultVersion>
                            <stylesheetfile>${shared.codestyle.directory}/blc-javadoc.css</stylesheetfile>
                            <sourcepath>${project.build.directory}/delombok</sourcepath>
                            <aggregate>true</aggregate>
                            <minmemory>128m</minmemory>
                            <maxmemory>1g</maxmemory>
                            <doclint>none</doclint>
                        </configuration>
                    </plugin>
                </plugins>
            </pluginManagement>
            <plugins>
                <plugin>
                    <groupId>org.apache.maven.plugins</groupId>
                    <artifactId>maven-dependency-plugin</artifactId>
                    <executions>
                        <execution>
                            <id>unpack-shared-codestyle-resources</id>
                        </execution>
                    </executions>
                </plugin>
                <plugin>
                    <groupId>com.diffplug.spotless</groupId>
                    <artifactId>spotless-maven-plugin</artifactId>
                </plugin>
                <plugin>
                    <artifactId>ms-upgrade-maven-plugin</artifactId>
                    <groupId>com.broadleafcommerce.microservices</groupId>
                    <version>2.0.1-SNAPSHOT</version>
                </plugin>
            </plugins>
        </build>
        <profiles>
            <profile>
                <id>deptrack</id>
                <build>
                    <plugins>
                        <plugin>
                            <groupId>org.cyclonedx</groupId>
                            <artifactId>cyclonedx-maven-plugin</artifactId>
                            <inherited>false</inherited>
                        </plugin>
                    </plugins>
                </build>
            </profile>
            <profile>
                <id>javadocs</id>
                <activation>
                    <property>
                        <name>performRelease</name>
                        <value>true</value>
                    </property>
                </activation>
                <build>
                    <plugins>
                        <plugin>
                            <groupId>org.projectlombok</groupId>
                            <artifactId>lombok-maven-plugin</artifactId>
                        </plugin>
                        <plugin>
                            <groupId>org.apache.maven.plugins</groupId>
                            <artifactId>maven-javadoc-plugin</artifactId>
                        </plugin>
                    </plugins>
                </build>
            </profile>
        </profiles>
        <dependencyManagement>
            <dependencies>
                <dependency>
                    <groupId>com.broadleafcommerce.microservices</groupId>
                    <artifactId>broadleaf-config-server-client</artifactId>
                    <version>2.0.0-GA</version>
                </dependency>
                <dependency>
                    <groupId>com.broadleafcommerce.microservices</groupId>
                    <artifactId>broadleaf-microservices-dependencies</artifactId>
                    <version>2.0.0-GA</version>
                    <type>pom</type>
                    <scope>import</scope>
                </dependency>
                <dependency>
                    <groupId>com.broadleafcommerce.microservices</groupId>
                    <artifactId>broadleaf-microservices-common-dependencies</artifactId>
                    <version>2.0.0-GA</version>
                    <type>pom</type>
                    <scope>import</scope>
                </dependency>
            </dependencies>
        </dependencyManagement>
        <modules>
            <module>admin</module>
            <module>commerce</module>
        </modules>
    </project>
  • Commerce Pom Example

    <?xml version="1.0" encoding="UTF-8" standalone="no"?>
    <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
        <parent>
            <groupId>com.broadleafcommerce.microservices</groupId>
            <artifactId>broadleaf-microservices-gateways-parent</artifactId>
            <version>1.4.12-GA</version>
            <relativePath>../pom.xml</relativePath>
        </parent>
        <modelVersion>4.0.0</modelVersion>
        <artifactId>broadleaf-microservices-gateways-commerce</artifactId>
        <name>Broadleaf Microservices Gateways Commerce Frontend</name>
        <properties>
            <skipAssembly>true</skipAssembly>
            <debug.port>8014</debug.port>
            <boot.jvm.args>-Xdebug
                -Xrunjdwp:transport=dt_socket,server=y,suspend=n,address=${debug.port}
            </boot.jvm.args>
            <project.uri>${project.basedir}/../</project.uri>
        </properties>
        <repositories>
            <repository>
                <id>broadleaf-microservices</id>
                <url>https://repository.broadleafcommerce.com/repository/microservices/</url>
            </repository>
        </repositories>
        <build>
            <finalName>commerce-gateway</finalName>
            <plugins>
                <plugin>
                    <groupId>org.springframework.boot</groupId>
                    <artifactId>spring-boot-maven-plugin</artifactId>
                    <configuration>
                        <attach>false</attach>
                        <jvmArguments>${java.17.options}</jvmArguments>
                        <layers>
                            <enabled>true</enabled>
                        </layers>
                    </configuration>
                </plugin>
            </plugins>
        </build>
        <profiles>
            <profile>
                <id>keygen</id>
                <activation>
                    <activeByDefault>true</activeByDefault>
                </activation>
                <build>
                    <plugins>
                        <plugin>
                            <groupId>org.codehaus.mojo</groupId>
                            <artifactId>keytool-maven-plugin</artifactId>
                        </plugin>
                    </plugins>
                </build>
            </profile>
            <profile>
                <id>docker</id>
                <build>
                    <plugins>
                        <plugin>
                            <groupId>org.codehaus.mojo</groupId>
                            <artifactId>exec-maven-plugin</artifactId>
                            <configuration>
                                <workingDirectory>${project.basedir}</workingDirectory>
                                <!-- NOTE - to build multi-platform images, the currently-active docker
                                    builder instance must be using a driver that supports multi-platform
                                    builds.
                                    See https://docs.docker.com/engine/reference/commandline/buildx_create/#driver -->
                                <environmentVariables>
                                    <JAR_FILE>target/${project.build.finalName}.jar</JAR_FILE>
                                    <BOOT_LAYER_DOCKER_IMAGE_REGISTRY>${dockerBuildBootLayerImageRegistry}</BOOT_LAYER_DOCKER_IMAGE_REGISTRY>
                                    <FULLY_QUALIFIED_MAIN_IMAGE_TAG>${dockerDeploymentRepository}/broadleaf/commercegateway-monitored:${project.version}</FULLY_QUALIFIED_MAIN_IMAGE_TAG>
                                    <BUILD_AND_LOAD_LOCAL_PLATFORM_ONLY>${buildLocalDockerOnly}</BUILD_AND_LOAD_LOCAL_PLATFORM_ONLY>
                                </environmentVariables>
                            </configuration>
                            <executions>
                                <execution>
                                    <id>buildDockerImage</id>
                                    <phase>package</phase>
                                    <goals>
                                        <goal>exec</goal>
                                    </goals>
                                    <configuration>
                                        <executable>docker</executable>
                                        <arguments>
                                            <argument>buildx</argument>
                                            <argument>bake</argument>
                                            <argument>-f</argument>
                                            <argument>../common-docker-bake.hcl</argument>
                                        </arguments>
                                    </configuration>
                                </execution>
                                <execution>
                                    <id>buildAndPushDockerImage</id>
                                    <phase>deploy</phase>
                                    <goals>
                                        <goal>exec</goal>
                                    </goals>
                                    <configuration>
                                        <environmentVariables>
                                            <!-- Engages push -->
                                            <OUTPUT_TYPE>type=registry</OUTPUT_TYPE>
                                        </environmentVariables>
                                        <executable>docker</executable>
                                        <arguments>
                                            <argument>buildx</argument>
                                            <argument>bake</argument>
                                            <argument>-f</argument>
                                            <argument>../common-docker-bake.hcl</argument>
                                        </arguments>
                                    </configuration>
                                </execution>
                            </executions>
                        </plugin>
                    </plugins>
                </build>
            </profile>
        </profiles>
        <dependencies>
            <!-- Compile time -->
            <dependency>
                <groupId>com.broadleafcommerce.microservices</groupId>
                <artifactId>broadleaf-microservices-starter-bootstrap</artifactId>
                <version>1.1.0-GA</version>
            </dependency>
            <dependency>
                <groupId>com.broadleafcommerce.microservices</groupId>
                <artifactId>broadleaf-common-extension</artifactId>
            </dependency>
            <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-starter-actuator</artifactId>
            </dependency>
            <dependency>
                <groupId>io.micrometer</groupId>
                <artifactId>micrometer-registry-prometheus</artifactId>
            </dependency>
            <dependency>
                <groupId>org.bouncycastle</groupId>
                <artifactId>bcprov-jdk18on</artifactId>
            </dependency>
            <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-starter-aop</artifactId>
            </dependency>
            <dependency>
                <groupId>org.springframework.retry</groupId>
                <artifactId>spring-retry</artifactId>
            </dependency>
            <dependency>
                <groupId>org.springframework.cloud</groupId>
                <artifactId>spring-cloud-starter-gateway</artifactId>
            </dependency>
            <dependency>
                <groupId>org.springframework.security</groupId>
                <artifactId>spring-security-config</artifactId>
            </dependency>
            <dependency>
                <groupId>org.springframework.security</groupId>
                <artifactId>spring-security-oauth2-client</artifactId>
            </dependency>
            <dependency>
                <groupId>org.apache.commons</groupId>
                <artifactId>commons-lang3</artifactId>
            </dependency>
            <dependency>
                <groupId>net.logstash.logback</groupId>
                <artifactId>logstash-logback-encoder</artifactId>
            </dependency>
            <dependency>
                <groupId>io.grpc</groupId>
                <artifactId>grpc-netty</artifactId>
            </dependency>
            <!-- spring cloud config -->
            <dependency>
                <groupId>org.springframework.cloud</groupId>
                <artifactId>spring-cloud-stream-binder-kafka</artifactId>
            </dependency>
            <dependency>
                <groupId>com.google.cloud</groupId>
                <artifactId>spring-cloud-gcp-pubsub-stream-binder</artifactId>
            </dependency>
            <dependency>
                <groupId>org.springframework.cloud</groupId>
                <artifactId>spring-cloud-stream-binder-kinesis</artifactId>
            </dependency>
            <dependency>
                <groupId>com.azure.spring</groupId>
                <artifactId>spring-cloud-azure-stream-binder-eventhubs</artifactId>
            </dependency>
            <dependency>
                <groupId>com.broadleafcommerce.microservices</groupId>
                <artifactId>broadleaf-config-server-client</artifactId>
            </dependency>
            <!-- Optional/Runtime/non-transitive -->
            <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-configuration-processor</artifactId>
                <optional>true</optional>
            </dependency>
            <dependency>
                <groupId>org.projectlombok</groupId>
                <artifactId>lombok</artifactId>
                <optional>true</optional>
            </dependency>
            <dependency>
                <groupId>org.apache.ignite</groupId>
                <artifactId>ignite-core</artifactId>
                <optional>true</optional>
            </dependency>
            <dependency>
                <groupId>org.apache.ignite</groupId>
                <artifactId>ignite-spring</artifactId>
                <optional>true</optional>
            </dependency>
            <dependency>
                <groupId>org.apache.ignite</groupId>
                <artifactId>ignite-slf4j</artifactId>
                <optional>true</optional>
            </dependency>
            <!-- Tests -->
            <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-starter-test</artifactId>
                <scope>test</scope>
            </dependency>
            <dependency>
                <groupId>jakarta.servlet</groupId>
                <artifactId>jakarta.servlet-api</artifactId>
                <optional>true</optional>
            </dependency>
            <dependency>
                <groupId>org.apache.ignite</groupId>
                <artifactId>ignite-spring-cache-ext</artifactId>
                <optional>true</optional>
            </dependency>
            <dependency>
                <groupId>jakarta.annotation</groupId>
                <artifactId>jakarta.annotation-api</artifactId>
            </dependency>
            <dependency>
                <groupId>jakarta.validation</groupId>
                <artifactId>jakarta.validation-api</artifactId>
            </dependency>
        </dependencies>
    </project>
  • Admin Pom Example

    <?xml version="1.0" encoding="UTF-8" standalone="no"?>
    <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
        <parent>
            <artifactId>broadleaf-microservices-gateways-parent</artifactId>
            <groupId>com.broadleafcommerce.microservices</groupId>
            <version>1.4.12-GA</version>
            <relativePath>../pom.xml</relativePath>
        </parent>
        <modelVersion>4.0.0</modelVersion>
        <artifactId>broadleaf-microservices-gateways-admin</artifactId>
        <name>Broadleaf Microservices Gateways Admin Frontend</name>
        <properties>
            <skipAssembly>true</skipAssembly>
            <debug.port>8001</debug.port>
            <boot.jvm.args>-Xdebug
                -Xrunjdwp:transport=dt_socket,server=y,suspend=n,address=${debug.port}
            </boot.jvm.args>
            <project.uri>${project.basedir}/../</project.uri>
        </properties>
        <repositories>
            <repository>
                <id>broadleaf-microservices</id>
                <url>https://repository.broadleafcommerce.com/repository/microservices/</url>
            </repository>
        </repositories>
        <build>
            <finalName>admin-gateway</finalName>
            <plugins>
                <plugin>
                    <groupId>org.springframework.boot</groupId>
                    <artifactId>spring-boot-maven-plugin</artifactId>
                    <configuration>
                        <attach>false</attach>
                        <jvmArguments>${java.17.options}</jvmArguments>
                        <layers>
                            <enabled>true</enabled>
                        </layers>
                    </configuration>
                </plugin>
            </plugins>
        </build>
        <profiles>
            <profile>
                <id>keygen</id>
                <activation>
                    <activeByDefault>true</activeByDefault>
                </activation>
                <build>
                    <plugins>
                        <plugin>
                            <groupId>org.codehaus.mojo</groupId>
                            <artifactId>keytool-maven-plugin</artifactId>
                        </plugin>
                    </plugins>
                </build>
            </profile>
            <profile>
                <id>docker</id>
                <build>
                    <plugins>
                        <plugin>
                            <groupId>org.codehaus.mojo</groupId>
                            <artifactId>exec-maven-plugin</artifactId>
                            <configuration>
                                <workingDirectory>${project.basedir}</workingDirectory>
                                <!-- NOTE - to build multi-platform images, the currently-active docker
                                    builder instance must be using a driver that supports multi-platform
                                    builds.
                                    See https://docs.docker.com/engine/reference/commandline/buildx_create/#driver -->
                                <environmentVariables>
                                    <JAR_FILE>target/${project.build.finalName}.jar</JAR_FILE>
                                    <BOOT_LAYER_DOCKER_IMAGE_REGISTRY>${dockerBuildBootLayerImageRegistry}</BOOT_LAYER_DOCKER_IMAGE_REGISTRY>
                                    <FULLY_QUALIFIED_MAIN_IMAGE_TAG>${dockerDeploymentRepository}/broadleaf/admingateway-monitored:${project.version}</FULLY_QUALIFIED_MAIN_IMAGE_TAG>
                                    <BUILD_AND_LOAD_LOCAL_PLATFORM_ONLY>${buildLocalDockerOnly}</BUILD_AND_LOAD_LOCAL_PLATFORM_ONLY>
                                </environmentVariables>
                            </configuration>
                            <executions>
                                <execution>
                                    <id>buildDockerImage</id>
                                    <phase>package</phase>
                                    <goals>
                                        <goal>exec</goal>
                                    </goals>
                                    <configuration>
                                        <executable>docker</executable>
                                        <arguments>
                                            <argument>buildx</argument>
                                            <argument>bake</argument>
                                            <argument>-f</argument>
                                            <argument>../common-docker-bake.hcl</argument>
                                        </arguments>
                                    </configuration>
                                </execution>
                                <execution>
                                    <id>buildAndPushDockerImage</id>
                                    <phase>deploy</phase>
                                    <goals>
                                        <goal>exec</goal>
                                    </goals>
                                    <configuration>
                                        <environmentVariables>
                                            <!-- Engages push -->
                                            <OUTPUT_TYPE>type=registry</OUTPUT_TYPE>
                                        </environmentVariables>
                                        <executable>docker</executable>
                                        <arguments>
                                            <argument>buildx</argument>
                                            <argument>bake</argument>
                                            <argument>-f</argument>
                                            <argument>../common-docker-bake.hcl</argument>
                                        </arguments>
                                    </configuration>
                                </execution>
                            </executions>
                        </plugin>
                    </plugins>
                </build>
            </profile>
        </profiles>
        <dependencies>
            <!-- Compile time -->
            <dependency>
                <groupId>com.broadleafcommerce.microservices</groupId>
                <artifactId>broadleaf-microservices-starter-bootstrap</artifactId>
                <version>1.1.0-GA</version>
            </dependency>
            <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-starter-actuator</artifactId>
            </dependency>
            <dependency>
                <groupId>io.micrometer</groupId>
                <artifactId>micrometer-registry-prometheus</artifactId>
            </dependency>
            <dependency>
                <groupId>org.bouncycastle</groupId>
                <artifactId>bcprov-jdk18on</artifactId>
            </dependency>
            <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-starter-aop</artifactId>
            </dependency>
            <dependency>
                <groupId>org.springframework.retry</groupId>
                <artifactId>spring-retry</artifactId>
            </dependency>
            <dependency>
                <groupId>org.springframework.cloud</groupId>
                <artifactId>spring-cloud-starter-gateway</artifactId>
            </dependency>
            <dependency>
                <groupId>org.springframework.security</groupId>
                <artifactId>spring-security-config</artifactId>
            </dependency>
            <dependency>
                <groupId>org.springframework.security</groupId>
                <artifactId>spring-security-oauth2-client</artifactId>
            </dependency>
            <dependency>
                <groupId>org.apache.commons</groupId>
                <artifactId>commons-lang3</artifactId>
            </dependency>
            <dependency>
                <groupId>net.logstash.logback</groupId>
                <artifactId>logstash-logback-encoder</artifactId>
            </dependency>
            <dependency>
                <groupId>io.grpc</groupId>
                <artifactId>grpc-netty</artifactId>
            </dependency>
            <!-- spring cloud config -->
            <dependency>
                <groupId>org.springframework.cloud</groupId>
                <artifactId>spring-cloud-stream-binder-kafka</artifactId>
            </dependency>
            <dependency>
                <groupId>com.google.cloud</groupId>
                <artifactId>spring-cloud-gcp-pubsub-stream-binder</artifactId>
            </dependency>
            <dependency>
                <groupId>org.springframework.cloud</groupId>
                <artifactId>spring-cloud-stream-binder-kinesis</artifactId>
            </dependency>
            <dependency>
                <groupId>com.azure.spring</groupId>
                <artifactId>spring-cloud-azure-stream-binder-eventhubs</artifactId>
            </dependency>
            <dependency>
                <groupId>com.broadleafcommerce.microservices</groupId>
                <artifactId>broadleaf-config-server-client</artifactId>
            </dependency>
            <!-- Optional/Runtime/non-transitive -->
            <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-configuration-processor</artifactId>
                <optional>true</optional>
            </dependency>
            <dependency>
                <groupId>org.projectlombok</groupId>
                <artifactId>lombok</artifactId>
                <optional>true</optional>
            </dependency>
            <!-- Tests -->
            <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-starter-test</artifactId>
                <scope>test</scope>
            </dependency>
            <dependency>
                <groupId>jakarta.annotation</groupId>
                <artifactId>jakarta.annotation-api</artifactId>
            </dependency>
            <dependency>
                <groupId>jakarta.validation</groupId>
                <artifactId>jakarta.validation-api</artifactId>
            </dependency>
        </dependencies>
    </project>

Broadleaf Service Key Reference Table

Sample Directory Name

Broadleaf Service Key

Optional Alt Key

Maven Properties

adminnav

adminNavigation

N/A

<broadleaf-service-key>adminNavigation</broadleaf-service-key>

adminuser

adminUser

N/A

<broadleaf-service-key>adminUser</broadleaf-service-key>

asset

asset

N/A

<broadleaf-service-key>asset</broadleaf-service-key>

cart

cart

N/A

<broadleaf-service-key>cart</broadleaf-service-key>

cartops

N/A

N/A

N/A

catalog

catalog

N/A

<broadleaf-service-key>catalog</broadleaf-service-key>

catalogbrowse

N/A

N/A

N/A

content

content

N/A

<broadleaf-service-key>content</broadleaf-service-key>

creditaccount

creditAccount

N/A

<broadleaf-service-key>creditAccount</broadleaf-service-key>

customer

customer

N/A

<broadleaf-service-key>customer</broadleaf-service-key>

fulfillment

fulfillment

N/A

<broadleaf-service-key>fulfillment</broadleaf-service-key>

import

import

N/A

<broadleaf-service-key>import</broadleaf-service-key><broadleaf-alt-service-key>dataimport</broadleaf-alt-service-key>

indexer

indexer

N/A

<broadleaf-service-key>indexer</broadleaf-service-key>

inventory

inventory

N/A

<broadleaf-service-key>inventory</broadleaf-service-key>

menu

menu

N/A

<broadleaf-service-key>menu</broadleaf-service-key>

metadata

metadata

N/A

<broadleaf-service-key>metadata</broadleaf-service-key>

notification

notification

N/A

<broadleaf-service-key>notification</broadleaf-service-key>

offer

offer

N/A

<broadleaf-service-key>offer</broadleaf-service-key>

order

order

N/A

<broadleaf-service-key>order</broadleaf-service-key>

orderops

orderoperation

N/A

<broadleaf-service-key>orderoperation</broadleaf-service-key>

paymenttransaction

paymentTransaction

N/A

<broadleaf-service-key>paymentTransaction</broadleaf-service-key>

pricing

pricing

N/A

<broadleaf-service-key>pricing</broadleaf-service-key>

ratingandreview

ratings

N/A

<broadleaf-service-key>ratings</broadleaf-service-key>

sandbox

sandbox

N/A

<broadleaf-service-key>sandbox</broadleaf-service-key>

scheduledjob

scheduledJob

N/A

<broadleaf-service-key>scheduledJob</broadleaf-service-key>

search

search

N/A

<broadleaf-service-key>search</broadleaf-service-key>

shipping

shipping

N/A

<broadleaf-service-key>shipping</broadleaf-service-key>

tenant

tenant

N/A

<broadleaf-service-key>tenant</broadleaf-service-key>

vendor

vendor

N/A

<broadleaf-service-key>vendor</broadleaf-service-key>