Extend Expressional Inference Rule Engine - BloomReach Experience - Open Source CMS

This article covers a Hippo CMS version 12. There's an updated version available that covers our most recent release.

30-11-2017

Extend Expressional Inference Rule Engine

BloomReach offers Enterprise support for this feature to BloomReach Experience customers. The release cycle of this feature may differ from our core product release cycle. 

Introduction

Expressional Inference Rule Engine provides a sandbox-based expression execution environment (powered by Apache Commons JEXLTM) for security reasons. So, it allows property/operation access only on the specific registered ("white-listed") objects and function namespaces.

You can register any extra objects and function namespaces to extend Expressional Inference Rule Engine for your custom integration needs (e.g., custom CRM access objects or function namespaces).

Add Custom Attributes to Built-In Root Object

In order to add custom attribute objects to the built-in root object ($), you should do the following:

  1. Add a Spring bean assembly XML file into site/src/main/resources/META-INF/hst-assembly/overrides/addon/com/onehippo/cms7/inference/engine/ folder. e.g, my-custom-extensions.xml under the folder.

  2. Register all the white-listed object class names (FQCNs) in the Spring bean assembly XML file.

  3. Register extra attribute object beans in the Spring bean assembly XML file.

In order to register all the white-listed object class names (FQCNs), add an org.springframework.beans.factory.config.ListFactoryBean bean named inferenceEngineWhiteSet containing all the white-listed class names (FQCNs).

In order to register all the extra attribute objects, add org.springframework.beans.factory.config.MapFactoryBean bean named inferenceEngineGenericBuiltinModelExtraAttributes containing all the extra attribute name and object pairs.

See the following example containing both:

<?xml version="1.0" encoding="UTF-8"?>
<!--
  Copyright 2017 Hippo B.V. (http://www.onehippo.com)
-->
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.1.xsd>

  <!--
    For security reason, you must explicitly add any custom class types here to use in expressions.
  -->
  <bean id="inferenceEngineWhiteSet"
        class="org.springframework.beans.factory.config.ListFactoryBean">
    <property name="sourceList">
      <list>
        <value>com.onehippo.cms7.inference.engine.demo.integration.FooMarketingAccount</value>
        <value>com.onehippo.cms7.inference.engine.demo.integration.FooMarketingConnector</value>
      </list>
    </property>
  </bean>

  <!--
    You can add any custom attributes as name vs. object pairs below.
    You can access an attribute like '$.getAttribute("fooMarketingConnector").getAccount();', for instance.
  -->
  <bean id="inferenceEngineGenericBuiltinModelExtraAttributes"
        class="org.springframework.beans.factory.config.MapFactoryBean">
    <property name="sourceMap">
      <map>
        <entry key="fooMarketingConnector">
          <ref bean="fooMarketingConnector" />
        </entry>
      </map>
    </property>
  </bean>

  <!-- SNIP -->

</beans>

You can access your custom attributes through the built-in root object ($) in expressions like the following example:

var fooMarketingConnector = $.getAttribute("fooMarketingConnector");
var account = fooMarketingConnector.getAcount();

Add Custom Function Namespaces

You can also add custom function namespaces. In order to add custom function namespaces, you should do the following as well:

  1. Add a Spring bean assembly XML file into site/src/main/resources/META-INF/hst-assembly/overrides/addon/com/onehippo/cms7/inference/engine/ folder. e.g, my-custom-extensions.xml under the folder.

  2. Register all the white-listed object class names (FQCNs) in the Spring bean assembly XML file.

  3. Register extra attribute object beans in the Spring bean assembly XML file.

In order to register all the white-listed object class names (FQCNs) of your custom function classes, add all the class names (FQCNs) into the org.springframework.beans.factory.config.ListFactoryBean bean named "inferenceEngineWhiteSet" like you do for the custom attributes. Please note that you should keep only one inferenceEngineWhiteSet bean in your custom Spring bean assembly XML files. Please combine all the whilte-listed class names into the ListFactoryBean bean.

In order to register all the extra attribute objects, add org.springframework.beans.factory.config.MapFactoryBean bean named inferenceEngineNamespaces containing all the extra function namespace name and function namespace object like the following:

<?xml version="1.0" encoding="UTF-8"?>
<!--
  Copyright 2017 Hippo B.V. (http://www.onehippo.com)
-->
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.1.xsd>

  <!--
    For security reason, you must explicitly add any custom class types here to use in expressions.
  -->
  <bean id="inferenceEngineWhiteSet"
        class="org.springframework.beans.factory.config.ListFactoryBean">
    <property name="sourceList">
      <list>
        <!-- SNIP -->
        <!-- Note: you need to register your function namespace class name to the white list as well! -->
        <value>com.example.util.MyMarketingUtils</value>
      </list>
    </property>
  </bean>

  <!-- SNIP --> 

  <!--
    You can add any custom function namespaces as name vs. object pairs below.
    You can access an attribute like 'mymarketing:getAccountInfo("foo");', for instance.
  -->
  <bean id="inferenceEngineNamespaces"
        class="org.springframework.beans.factory.config.MapFactoryBean">
    <property name="sourceMap">
      <map>
        <entry key="mymarketing">
          <ref bean="myMarketingUtils" />
        </entry>
      </map>
    </property>
  </bean>

  <!-- SNIP -->

</beans>

You can access your custom function namespaces through the standard JEXL expressions like the following example:

var accountInfo = mymarketing:getAccountInfo("foo");

 

Did you find this page helpful?
How could this documentation serve you better?
On this page
    Did you find this page helpful?
    How could this documentation serve you better?