Documentation Home
This version of the framework is no longer supported. View the latest documentation.

Broadleaf 3.1.0-GA

3.1.0-GA includes a ton of awesome features, bug fixes and enhancements. Here are the major feature highlights of this release.

Friendly REST exceptions

There is a new class to help build XML/JSON responses into exceptions that might occur in your REST APIs with BroadleafWebServicesExceptions. Usage of this class hs through a static invocation to build(). An example is in the addOfferCode method of CartEndpoint:

public OrderWrapper addOfferCode(HttpServletRequest request,
        String promoCode,
        boolean priceOrder) {
    // code removed

    OfferCode offerCode = offerService.lookupOfferCodeByCode(promoCode);

    if (offerCode == null) {
        throw BroadleafWebServicesException.build(Response.Status.NOT_FOUND.getStatusCode())
                .addMessage(BroadleafWebServicesException.PROMO_CODE_INVALID, promoCode);
    }

    // etc...

}

The exception builder takes in the HTTP status code (in this case a 404) and then also adds a not-found message. This exception is later parsed by the BroadleafRestExceptionMapper. This exception mapper should already be hooked up but if not, include it as a bean in your applicationContext-rest-api.xml:

    <bean class="org.broadleafcommerce.core.web.api.BroadleafRestExceptionMapper" scope="singleton"/>

Note: error messages are translated via Spring's message i18n property resolution. The above case also uses a parameterized message with the promo code that was not found

Site Maps

There is new functionality to configure a site map generator to scan through your existing Category, Product and Page domain and output a sitemap file for web crawlers. Documentation on how to set this up are in SEO. One additional configuration step is to add a new controller to respond to requests for a site map:

@Controller
public class SiteMapController extends BroadleafSiteMapController {
    @RequestMapping(value = { "/sitemap*.xml", "sitemap*.gz" })
    @ResponseBody
    public FileSystemResource retrieveSiteMapIndex(HttpServletRequest request, HttpServletResponse response)
            throws IOException {
        return super.retrieveSiteMapFile(request, response);
    }
}

You also want to notify crawlers via robots.txt about your site map. You can add this functionality with a robots controller:

@Controller
public class RobotsController extends BroadleafRobotsController {
    @RequestMapping(value = { "/robots.txt" })
    @ResponseBody
    public String getRobotsFile(HttpServletRequest request, HttpServletResponse response) {
        return super.getRobotsFile(request, response);
    }
}

Payment Domain Refactor

See the Payment section for more information on what this looks like and 3.0 to 3.1 Migration if you are upgrading from 3.0

Cart and Customer Cleanup Jobs

You can now configure a Quartz job to remove old IN_PROCESS Carts and non-registered users from your system. Below is an example configuration that will delete all IN_PROCESS Orders (carts) that are older than 30 days (2592000 seconds):

 <bean id="purgeCartConfig" class="org.springframework.beans.factory.config.MapFactoryBean">
    <property name="sourceMap">
        <map>
            <entry key="SECONDS_OLD" value="2592000"/>
            <entry key="STATUS" value="IN_PROCESS"/>
        </map>
    </property>
</bean>

<bean id="purgeCartJobDetail" class="org.springframework.scheduling.quartz.MethodInvokingJobDetailFactoryBean">
    <property name="targetObject" ref="blResourcePurgeService" />
    <property name="targetMethod" value="purgeCarts" />
    <property name="arguments">
        <list>
            <ref bean="purgeCartConfig"/>
        </list>
    </property>
</bean>

<bean id="purgeCartTrigger" class="org.springframework.scheduling.quartz.SimpleTriggerFactoryBean">
    <property name="jobDetail" ref="purgeCartJobDetail" />
    <property name="startDelay" value="30000" />
    <property name="repeatInterval" value="86400000" />
</bean>

Valid parameters in the purgeCartConfig map are:

  • SECONDS_OLD - number of seconds since the last update date of the cart
  • STATUS - comma-delimited status from OrderStatus. For instance, if you wanted to clean up all IN_PROCESS (carts) and NAMED (wishlists) orders:
   <entry key="STATUS" value="IN_PROCESS,NAMED" />
  • NAME - the name of NAMED Orders to delete. This is useful if your implementation uses specific names of wishlist or saved carts and they are not normally user-specified
  • IS_PREVIEW - "true" or "false" for the value of the IS_PREVIEW column on Order. This is mainly used in enterprise.

Anonymous Customers can also be cleaned up. While Broadleaf does not persist a new Customer on every single visit, new Customers are persisted when a user adds something to their cart. This is an example of a quarts job that cleans up all non-registered Customers that have not been updated in the last 30 days:

<bean id="purgeCustomerConfig" class="org.springframework.beans.factory.config.MapFactoryBean">
    <property name="sourceMap">
        <map>
            <entry key="SECONDS_OLD" value="2592000"/>
            <entry key="IS_REGISTERED" value="false"/>
        </map>
    </property>
</bean>

<bean id="purgeCustomerJobDetail" class="org.springframework.scheduling.quartz.MethodInvokingJobDetailFactoryBean">
    <property name="targetObject" ref="blResourcePurgeService" />
    <property name="targetMethod" value="purgeCustomers" />
    <property name="arguments">
        <list>
            <ref bean="purgeCustomerConfig"/>
        </list>
    </property>
</bean>

<bean id="purgeCustomerTrigger" class="org.springframework.scheduling.quartz.SimpleTriggerFactoryBean">
    <property name="jobDetail" ref="purgeCustomerJobDetail" />
    <property name="startDelay" value="30000" />
    <property name="repeatInterval" value="86400000" />
</bean>

Valid parameters in the purgeCustomerConfig map are:

  • SECONDS_OLD - number of seconds since the last update date of the Customer
  • IS_REGISTERED - "true" or "false" for the value of the registered field on Customer
  • IS_DEACTIVATED - true" or "false" for the value of the deactivated field on Customer
  • IS_PREVIEW - "true" or "false" for the value of the IS_PREVIEW column on Customer. This is used in enterprise.

Database-managed System Properties

Rather than managing system properties only via Runtime Environment Configuration, you can now manage properties in the database via the BLC_SYSTEM_PROPERTY table. If the property is not found in the database, then the fallback is to look for the property in property files configured according to Runtime Environment Configuration.

If you would like to take advantage of this functionality then you can remove an @Value annotation on a bean property and override the getter to invoke BLCSystemProperty like so:

protected boolean getSomeBeanProperty() {
    BLCSystemProperty.resolveBooleanSystemProperty("some.bean.property");
}

This is how we refactored the TranslationRequestProcessor to determine if translations should be enabled:

@Component("blTranslationRequestProcessor")
public class TranslationRequestProcessor extends AbstractBroadleafWebRequestProcessor {
    // ...

    protected boolean getTranslationEnabled() {
        return BLCSystemProperty.resolveBooleanSystemProperty("i18n.translation.enabled");
    }

    // ...
}

Thymeleaf 2.1

We have continued and enhanced our usage of Thymeleaf by updating to the latest GA version. To see what comes with Thymeleaf 2.1, see their What's new in Thymeleaf 2.1 page.

Friendly Permissions

We refactored admin permissions to make them more intuitive for adding to users and roles. The idea here is that if you want to give permissions to a user or role for a certain section of the admin, all you need to do is add either of the friendly permissions for that section ("View [section]" or "Maintain [section]"). We added a boolean value on Permission called isFriendly which indicates that this is a permission that contains child permissions maintained through BLC_ADMIN_PERMISSION_XREF.

Resolved GitHub Issues Reference

An at-a-glance view of the issues that were closed in this release:

Critical Bugs(3)

Major Bugs(22)

Minor Bugs(13)

Features(26)

Enhancements(53)

Total Resolved Issues: 119