Documentation Home

Customizing Broadleaf Beans

Overrides

Broadleaf comes with hundreds of Spring components, all of which can be overridden or customized in one way or another. A simple but common example is to override CustomerService and change which implementation that gets created depending on something about the request.

If we look for implementations of the CustomerService interface we see CustomerServiceImpl. This is annotated with @Service("blCustomerService") (as almost all Broadleaf beans start with bl), which means that we need to create an override for the blCustomerService bean. We start with creating a subclass of CustomerServiceImpl:

package com.mycompany;

public class MyCustomerService extends CustomerServiceImpl {

    @Override
    public Customer createCustomer() {
        if (RequestContextHolder.getRequestAttributes().getAttribute("someSessionAttribute", SCOPE_SESSION)) {
            MyCustomer customer = new MyCustomer();
            customer.setId(findNextCustomerId());
        }
    }
}

This assumes that you have already added MyCustomer as an entity outlined in Creating a New Entity

@Component/@Service/@Repository are intentionally left off of this class to exclude it from regular component scanning

Java Configuration

Create an @Configuration class within the package org.broadleafoverrides.config that contains an @Bean method that returns your override. The method name must be the exact same as the bean name:

package org.broadleafoverrides.config;

@Configuration
public class BroadleafOverrides {

    @Bean
    public CustomerService blCustomerService() {
        return new MyCustomerService();
    }
}

XML

One way to guarantee your override is to add an @ImportResource to an XML file that contains the following:

<beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xmlns:context="http://www.springframework.org/schema/context"
    xmlns:aop="http://www.springframework.org/schema/aop"
    xmlns:util="http://www.springframework.org/schema/util"
    xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
           http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd">

    <bean id="blCustomerService" class="com.mycompany.MyCustomerService />

</beans>

Then we create a special @Configuration clas

By looking through the INFO-level logging on org.springframework, on startup you should see the following log message:

2017-06-14 10:55:58.287  INFO 10427 --- [ost-startStop-1] o.s.b.f.s.DefaultListableBeanFactory     : Overriding bean definition for bean 'blCustomerService' with a different definition: replacing [Generic bean: class [org.broadleafcommerce.profile.core.service.CustomerServiceImpl]; scope=singleton; abstract=false; lazyInit=false; autowireMode=0; dependencyCheck=0; autowireCandidate=true; primary=false; factoryBeanName=null; factoryMethodName=null; initMethodName=null; destroyMethodName=null; defined in URL [jar:file://apache-tomcat-7.0.78/webapps/site/WEB-INF/lib/broadleaf-profile-5.2.0-SNAPSHOT.jar!/org/broadleafcommerce/profile/core/service/CustomerServiceImpl.java.class]] with [Root bean: class [null]; scope=; abstract=false; lazyInit=false; autowireMode=3; dependencyCheck=0; autowireCandidate=true; primary=false; factoryBeanName=broadleafOverrides; factoryMethodName=blCustomerService; initMethodName=null; destroyMethodName=(inferred); defined in com.mycompany.MyCustomerService]]

This log message will be slightly different depending on if you overwrote the bean with XML or Java @Configuration

Java @Configuration package scanning

In order for bean overrides to work, Broadleaf scans various packages looking for @Configuration classes in different contexts, depending on which @EnableBroadleaf... annotation you have active. Doing a search in your project indicates which annotations you have active.

Annotation Used Bean Override Packages Scanned Used When...
@EnableBroadleafSiteAutoConfiguration org.broadleafoverrides.config, org.broadleafoverrides.site.config There is a single ApplicationContext, only in the site project. This is the default for fresh Broadleaf 5.2+ projects
@EnableBroadleafSiteRootAutoConfiguration org.broadleafoverrides.config, org.broadleafoverrides.site.config There are multiple ApplicationContexts and the override is only for beans in the root (the majority of the Broadleaf beans) only in the site project. Default for projects upgraded to Broadleaf 5.2
@EnableBroadleafSiteServletAutoConfiguration org.broadleafoverrides.servlet.config, org.broadleafoverrides.site.servlet.config There are multiple ApplicationContexts and the override is only for beans in the servlet only in the site project. Default for projects upgraded to Broadleaf 5.2
@EnableBroadleafAdminAutoConfiguration org.broadleafoverrides.config, org.broadleafoverrides.admin.config There is a single ApplicationContext, only in the admin project. This is the default for fresh Broadleaf 5.2+ projects
@EnableBroadleafAdminRootAutoConfiguration org.broadleafoverrides.config, org.broadleafoverrides.admin.config There are multiple ApplicationContexts and the override is only for beans in the root (the majority of the Broadleaf beans) only in the admin project. Default for projects upgraded to Broadleaf 5.2
@EnableBroadleafAdminServletAutoConfiguration org.broadleafoverrides.servlet.config, org.broadleafoverrides.admin.servlet.config There are multiple ApplicationContexts and the override is only for beans in the servlet only in the admin project. Default for projects upgraded to Broadleaf 5.2
@EnableBroadleafAutoConfiguration org.broadleafoverrides.config Not used in Broadleaf 5.2, added for completeness
@EnableBroadleafRootAutoConfiguration org.broadleafoverrides.config Not used in Broadleaf 5.2, added for completeness
@EnableBroadleafServletAutoConfiguration org.broadleafoverrides.servlet.config Not used in Broadleaf 5.2, added for completeness

Spring's BeanFactoryPostProcessor BeanDefinitionPostProcessor and BeanPostProcessor interfaces

There might be instances where you do not want to override the Broadleaf beans but instead need to customize properties or members of a Broadleaf bean. Spring has some great out of the box abilities to further refine and customize beans within the ApplicationContext:

Spring Interface Use When...
BeanFactoryPostProcessor You want to change a bean definition before any beans are instantiated
BeanDefinitionRegistryPostProcessor You need to modify a bean definition that a BeanFactoryPostProcessor depends on, or add additional BeanFactoryPostProcessors
BeanPostProcessor You want the original bean definition to be active and instantiate the bean but you want to customize the actual bean instance further (like change properties, modify members, etc)