Broadleaf Microservices
  • v1.0.0-latest-prod

Appendix A - Durable Send

Previously, the OrderOperationService did not offer durable sending of outgoing messages. In a scenario where the message broker is down, this results in messages not being sent and possibly portions of an order remaining in an incomplete state. While this is not a usual scenario, we have added durable message sending for this service (similar to the other services in the stack) to make it more resilient to message broker outages.

Enabling this feature requires configuration changes in several key areas:

  1. Several properties will need to be set to enable the feature

  2. Depending on your deployment, you may need to enable several new message consumer channels

Note
If you do nothing, OrderOperationService will continue to operate in the legacy mode and will not perform durable message sends and will have no database interaction (the same as previous versions).

Properties

How you package OrderOperationService for deployment will determine what properties are required.

Case #1 : OrderOperationService is deployed in a FlexPackage with other Trackable services. This is common for balanced and min flexpackages where OrderOperationService is colocated in the same deployable unit with other services. In this case, you will want to edit your application configuration yaml file similar to this:

Figure 1.1 : General FlexPackage Example

#...#
broadleaf:
  #...#
  orderoperation:
    #...#
    liquibase:
      change-log: 'classpath:/db/changelog/orderoperation.postgresql.changelog-master.yaml'     # (1)
      liquibase-schema: public
      default-schema: orderoperation
    delegating:
      schema: orderoperation
      delegate-ref: composite
    database:
      provider: jpa                                                                             # (2)
#...#
  1. Adjust the reference liquibase changelog according to your platform: postgresql, mysql, mariadb, oracle, or yugabytedb

  2. broadleaf.orderoperation.database.provider=jpa is primarily responsible for enabling the feature (along with broadleaf.database.provider=jpa already defined elsewhere in the flexpackage).

Note
The property spring.liquibase.enabled is true by default. This is needed to cause liquibase to emit the DDL for the schema and tables required by the feature. This is similar to how the DDL to build the required database structure is handled in other services.

Case #2 : OrderOperationService is deployed in a granular fashion separate from any other services. In this case, you will need additional properties to not only enable the feature, but to add new datasource support.

Figure 1.2 : Granular Deployment Example

#...#
broadleaf:
  #...#
  database:
    provider: jpa                                                                               # (1)
  #...#
  composite:
    datasource:
      url: 'jdbc:postgresql://localhost:5432/broadleaf'                                         # (2)
      username: broadleaf
      password: demo
      hikari:
        maximumPoolSize: 3
      properties:
        hibernate:
          jdbc:
            lob:
              non_contextual_creation: true
  jpa:
    transaction-synchronization-manager:
      aop:
        active: true
  #...#
  orderoperation:
    #...#
    liquibase:
      change-log: 'classpath:/db/changelog/orderoperation.postgresql.changelog-master.yaml'     # (3)
      liquibase-schema: public
      default-schema: orderoperation
    delegating:
      schema: orderoperation
      delegate-ref: composite
    database:
      provider: jpa                                                                             # (4)
#...#
spring:
  liquibase:
    enabled: true                                                                               # (5)
  #...#
  jpa:
    hibernate:
      ddl-auto: none
    open-in-view: false
    properties:
      hibernate:
        temp:
          use_jdbc_metadata_defaults: false
        dialect: com.broadleafcommerce.data.tracking.jpa.hibernate.PostgresDialect              # (6)
#...#
  1. broadleaf.database.provider=jpa must be set to inform data tracking in general that JPA is in-play

  2. Set the connection specifics for the datasource. This is similar to any of your other persistent granular services.

  3. Adjust the reference liquibase changelog according to your platform: postgresql, mysql, mariadb, oracle, or yugabytedb

  4. broadleaf.orderoperation.database.provider=jpa must be set to enable the feature

  5. spring.liquibase.enabled=true must be set to cause liquibase to emit the DDL for the database structure

  6. Set the appropriate Hibernate dialect for your platform. Refer to any of your other persistent granular services for reference.

Consumer Channels

Several new channels are defined for the OrderOperationService that react to scheduled job trigger events. If your OrderOperationService is deployed as part of a FlexPackage with other Trackable services (Case #1 above), then you can skip this step, as your FlexPackage should already be configured appropriately to listen for these events. However, if you use a granular deployment, then you will not likely have the two channels configured for it. There are generally two cases for broker channel creation: automatic and manual.

Automatic

If you let Spring Cloud Stream dynamically create the channels for you in the broker (i.e. Kafka), then you may continue to rely on this behavior in this case and nothing more is required of you.

Manual

If you manually define channels in the broker, then you should use the same process to define them that you’ve used in the past for other channels required by the other services. For your reference, the two new channels are internally defined in the Broadleaf component configuration for Spring Cloud Stream as follows:

spring:
  cloud:
    stream:
      bindings:
        #...#
        triggeredJobEventInputPruneNotification:
          group: orderoperation-prune-notification
          destination: triggeredJobEvent
        triggeredJobEventInputPurgeLock:
          group: orderoperation-purge-lock
          destination: triggeredJobEvent