Documentation Home

6.0 Migration

These migration notes assumes that you are going from 5.2 demo to the 6.0 demo. There might be additional migration steps necessary for your particular implementation of Broadleaf. If so, please let us know through our Gitter, our Google Group, or by submitting a pull request to this documentation repo at https://github.com/BroadleafCommerce/docs.

Overview of new features in the 6.0.0-GA release are detailed within 6.0.0-GA Release Notes.

Module Compatibility with 6.0

If you are using any other Broadleaf modules, then those module versions will need to be updated to be compatible with broadleaf framework 6.0. Here is a compatibility chart listing all of the module versions that are compatible with broadleaf 6.0.

Module Name Version Migration Notes
broadleaf-menu 3.0.0-GA -
broadleaf-multitenant-singleschema 4.0.0-GA -
broadleaf-theme 3.0.0-GA -
broadleaf-pricelist 4.0.0-GA -
broadleaf-custom-field 3.0.0-GA -
broadleaf-advanced-cms 3.0.0-GA -
broadleaf-advanced-offer 3.0.0-GA -
broadleaf-account-credit 4.0.0-GA -
broadleaf-advanced-inventory 3.0.0-GA -
broadleaf-common-modules-enterprise 4.0.0-GA -
broadleaf-jobs-events 3.0.0-GA -
broadleaf-i18n-enterprise 3.0.0-GA -
broadleaf-enterprise 4.0.0-GA -
broadleaf-account 3.0.0-GA -
broadleaf-enterprise-search 3.0.0-GA -
broadleaf-customer-segment 2.0.0-GA -
broadleaf-merchandising-group 2.0.0-GA -
broadleaf-api 3.0.0-GA -
broadleaf-oms 3.0.0-GA -
broadleaf-cart-rules 2.0.0-GA -
broadleaf-common-presentation 1.1.0-GA -
broadleaf-thymeleaf-presentation 2.0.0-GA -
broadleaf-product-type 2.0.0-GA -
broadleaf-catalog-access-policy 2.0.0-GA -
broadleaf-quote 2.0.0-GA -
broadleaf-marketplace 2.0.0-GA -
broadleaf-process 2.0.0-GA -
broadleaf-export 2.0.0-GA -
broadleaf-import 3.2.0-GA -
broadleaf-affiliate 2.0.0-GA -
broadleaf-contenttests 3.0.0-GA -
broadleaf-subscription 3.0.0-GA -
broadleaf-punchout2go 2.0.0-GA -
broadleaf-free-geo-ip 2.0.0-GA -
broadleaf-max-mind-geo 2.0.0-GA -

Major feats

  • Updated core 3rd-party dependency baselines
  • Upgraded base JDK from 7 to 8
    • Thus, the minimum system requirement for Broadleaf 6.0 is no longer Java 7 but Java 8
  • Upgraded Solr APIs to support Solr 7
    • While the APIs have been tested to support a Solr 5 server, it is advised to migrate to Solr 7 and do a full reindex
  • Added support for Java Servlet API 3.1.0
  • Dropped support for MSSQL

Dependency Updates

  • Removed
    • commons-digest
    • velocity
      • No longer used
    • commons-lang
      • Replaced by commons-lang3
    • YUICompressor for Javascript minification
      • Usage replaced by Google Closure Compiler
      • Still used for CSS minification
    • Thymeleaf 2 support
  • Updated
    • Java Servlet API to 3.1
    • Spring 4.3.17 -> 5.0.7
    • Spring Security 4.3.x -> 5.0.6
    • Spring Boot 1.5.12 -> 2.0.3
    • Hibernate 4.1.11 -> 5.2.17
    • Hibernate validator to 6.0.9
    • JPA to 2.1
    • Jackson to 2.9
    • commons-io 2.4 -> 2.6
    • commons-codec 1.4 -> 1.11
    • commons-dbcp 1.2.2 -> 2.2.0
      • Required changing groupId and artifactId from commons-dbcp:commons-dbcp to org.apache.commons:commons-dbcp2
    • commons-lang -> commons-lang3
    • esapi 2.1.0 -> 2.1.0.1
    • guava 12 -> 22
    • quartz-scheduler 2.2 -> 2.3

Solr 7 upgrade

Spring 5 changes

Hibernate 5 updates

Dialects

  • MySQL (changed)
    • Replace org.hibernate.dialect.MySQL5InnoDBDialect (now deprecated)
    • with org.hibernate.dialect.MySQL5Dialect and set hibernate.dialect.storage_engine=innodb as an environment variable or JVM system property instead
  • Postgres (changed)
    • Replace org.hibernate.dialect.PostgreSQLDialect (now deprecated)
    • with org.broadleafcommerce.common.dialect.BroadleafPostgreSQLDialect
  • HSQL (unchanged)
    • org.hibernate.dialect.HSQLDialect
  • Oracle (unchanged)
    • org.hibernate.dialect.Oracle10gDialect
  • MSSQL (unchanged)
    • org.hibernate.dialect.SQLServerDialect

Naming Strategies

Hibernate 5 introduced a change to their naming strategy contract:

Historically, Hibernate provided just a singular contract for applying a "naming strategy". Starting in 5.0, this has been split into 2 distinct contracts: * ImplicitNamingStrategy - is used whenever a table or column is not explicitly named to determine the name to use. * PhysicalNamingStrategy - is used to convert a "logical name" (either implicit or explicit) name of a table or column into a physical name (e.g. following corporate naming guidelines)

This affects Broadleaf insofar as the default ImplicitNamingStrategy has been changed in order to be compliant with JPA 2.0 standards. Where before a column without an explicitly labelled name (e.g., @Column instead of @Column(name = "COLUMN_NAME) might be named TABLE_NAME_FIELD_NAME, the new standard causes Hibernate to expect the name to be EntityName_FIELD_NAME. All cases in Broadleaf of implicit naming have been made explicit to prevent any need for schema migration changes on Broadleaf's account. However, clients will need to consider any custom and extended entities that may be using the implicit naming strategy.

There are 2 options for handling this change:

  1. (Easy Way) In the short term to make the migration easy, the legacy implicit naming strategy can be reintroduced by setting the following property for each persistence unit as with other Hibernate properties:
    • <persistenceUnit>.hibernate.implicit_naming_strategy=legacy-jpa
    • <persistenceUnit> could be blPU, blCMSStorage, blSecure, or any other persistence unit present
  2. (Involved Way) Eventually, it is recommded to move away from using a legacy feature of a 3rd party dependency since it may be removed in the next upgrade. To do so, replace all cases where implicit naming is relied upon for tables and columns by providing explicit names. Some examples:
    • @Table -> @Table(name = "EXISITNG_TABLE_NAME"
    • @Column -> @Column(name = "EXISTING_COLUMN_NAME)
    • @JoinTable ->
@JoinTable(name = "EXISTING_TABLE_NAME", 
           joinColumns = @JoinColumn(name = "EXISTING_COLUMN_NAME", referencedColumnName = "REFERENCED_COLUMN_NMAE"), 
           inverseJoinColumns = @JoinColumn(name = "EXISTING_COLUMN_NAME", referencedColumnName = "REFERENCED_COLUMN_NAME"))

Additionally, the physical naming strategy can be overridden, but this is not necessary since Hibernate defaults to matching the physical and implicit (logical) names. Yet, to override set <persistenceUnit>.hibernate.physical_naming_strategy to some.class.implementing.org.hibernate.boot.model.naming.PhysicalNamingStrategy. The default class is org.hibernate.boot.model.naming.PhysicalNamingStrategyStandardImpl

Notes

Scheduled Jobs Updates

Quartz Scheduler 2.2 suffered from a bug that prevented cron expressions with increments (e.g., 0 0/60 * * * ?) from being correctly validated. That was fixed in 2.3. However, that means that invalid increment values will now cause exceptions to be thrown when trying to run scheduled jobs. Please, correct any invalid cron expressions in BLC_SCHED_JOB.CRON_EXPRESSION. Primarily, make sure that values for seconds and minutes are < 60 and hours are < 23. For example previously, the following would not throw an exception: 0 0/60 * * * ?. However, it should now be changed to 0 0/59 * * * ?. See allowed values for each field below:

Field Allowed Values
Seconds 0-59
Minutes 0-59
Hours 0-23
Day of month 1-31
Month 1-12 or Jan-Dec
Day of week 1-7 or SUN-SAT
Year empty or 1970-2099

Framework changes

General changes

  • Removed:
    • Support for Thymeleaf 2
      • Remove the broadleaf-thymeleaf2-presentation dependency and replace it with broadlaef-thymeleaf3-presentation
      • Thymeleaf upgrade blog post -RuntimeEnvironmentPropertiesConfigurer
      • Instead, use org.springframework.core.env.Environment to access the current profile or @Profile
    • Support for having a salt source for passwords
      • No longer needed since Spring provides a salt for the encoders that need one
    • Support for older password encoders
      • BCrypt is our recommendation
  • Added
    • Out-of-box usage of commons-dbcp2 for creating data sources
      • Various changes in API
      • Change #setMaxActive to #setMaxTotal

Domain changes

  • MenuItem no longer has a foreign key relationship with Media
    • The foreign key is replaced by a string field to hold the Media's URL
    • Migration notes
  • ExternalId field added to Customer
    • Previously, this was optionally woven on by the Import module
    • To migrate, add a new string column, EXTERNAL_ID, to BLC_CUSTOMER
      • This is an optional field and is used to map the customer record to an external system.
  • If you are using the ProductType module version 1.1 or less, you will need to add a new column to the BLC_PRODUCT_ADD_ON_XREF table. The new column is ADD_ON_SKU_ID.
-- MySQL example
alter table BLC_PRODUCT_ADD_ON_XREF
add column `ADD_ON_SKU_ID` bigint(20) DEFAULT NULL;

Code Changes (Spring Boot)

The upgrade will require updates to configuration and application classes:

  • ApplicationSolrConfiguration
    • If configuring Solr clients using a configuration class, replace direct instantiations of solr client objects with builders:
      • new HttpSolrClient(url) -> new HttpSolrClient.Builder(primaryFulfillmentOrderSolrUrl).build()
  • CorePersistenceConfig
    • Change org.springframework.boot.autoconfigure.jdbc.DataSourceBuilder -> org.springframework.boot.jdbc.DataSourceBuilder
  • Api/Admin/SiteApplication
    • Change org.springframework.boot.web.support.SpringBootServletInitializer -> org.springframework.boot.web.servlet.support.SpringBootServletInitializer
    • Change uses of org.springframework.boot.context.embedded.tomcat.TomcatEmbeddedServletContainerFactory -> org.springframework.boot.web.embedded.tomcat.TomcatServletWebServerFactory

New Broadleaf Hibernate Dialect for PostgreSQL

What

Introduced new custom Hibernate dialect to better support PostgreSQL.

Why

The PostgreSQL jdbc driver does not implement createClob(), causing difficulty for Hibernate to correctly handle clobs for Postgres. Normally, a clob would be stored as a Postgres Large Object pointed to by an OID in the original column. However, because createClob() is not implemented, the string value is placed directly into the column meant for the OID. Hibernate's Postgres dialect does not recognize that the column value is not an OID; therefore, an exception is thrown because Hibernate tries to cast the string to a long.

Thus, the custom BroadleafPostgreSQLDialect treats all Clob types as if they contain a string instead of an long (OID).

How to use

Set <persistenceUnit>.hibernate.dialect to org.broadleafcommerce.common.dialect.BroadleafPostgreSQLDialect where <persistenceUnit> can be blPU, blCMSStorage, blSecure, etc.

Notes on Logging for the PostgreSQL Clob

Once using the custom BroadleafPostgresSQLDialect, clobs should be handled as expected. However, you may still see INFO entries in the application logs related to the lack of support for createClob().

INFO  o.h.e.j.e.i.LobCreatorBuilderImpl...
...
Caused by: java.sql.SQLFeatureNotSupportedException: Method org.postgresql.jdbc.PgConnection.createClob() is not yet implemented.

These are only INFO log entries and are harmless. The recommendation is to change the logging levels to WARN/ERROR.