Reference‎ > ‎

Dynamic logic

ABL supports the concept of dynamic logic reloading. This optional feature enables you to change the logic classes at runtime, while your application is running, and have those changes take effect immediately, without having to restart the application.

This feature is provided through implementations of the LogicClassManager interface. ABL provides three implementations of this interface, but you can also provide your own, either by extending an existing implementation, or by creating one from scratch.

Dynamic logic is enabled by configuring it in ABLConfig.properties. Let's look at an example:

logicClassManager1=file
logicClassManager1_directory=/home/jdoe/projects/Foo/classes

logicClassManager2=jar
logicClassManager2_jar_path=/home/jdoe/projects/Bar/classes.jar

logicClassManager3=database
logicClassManager3_project_name=Sample
logicClassManager3_check_min_interval=600
logicClassManager3_persistence_unit=LogicDB

Here we see three dynamic logic managers. They are ordered (1,2,3) and behave like a classpath: each is asked in turn if it has the logic for a given persistent entity. When one does have the logic, the search ends there.

Each standard logic manager is described in its own section below.

The file logic manager


The first dynamic logic manager is file, which is shorthand for com.autobizlogic.abl.logic.dynamic.TimeStampClassManager. The line after that provides the required configuration parameter, in this case the directory in which the logic class files can be found. This logic manager will check the last modified timestamp on each class file, and reload it if it changes.

Note that there may be a slight performance implication, depending on the number of logic classes in use, since the class files' timestamps will have to be checked frequently.

The jar logic manager

The second dynamic logic manager is jar, which is shorthand for com.autobizlogic.abl.logic.dynamic.JarClassManager. The line after that points to a jar file, which contains logic classes. This logic manager will check the last modified timestamp of the jar file, and reload the logic classes if it changes.

The performance implications are negligible in this configuration (other than, obviously, the cost of reloading the logic classes when the jar file is updated).

The database logic manager

The third dynamic logic manager is database, which is shorthand for com.autobizlogic.abl.logic.dynamic.DatabaseClassManager.
It enables you to store the logic classes in a relational database (which may or may not be the same database as that used by your application). This is particularly useful in a distributed scenario (cluster, cloud, etc...), when you may have more than one instance of the ABL engine, and you need to update the logic on all instances. Obviously this can be more convenient than copying a jar file to multiple servers.

An additional advantage of this strategy is that you can optionally delay the activation of your new logic until a given point in the future.

Logic classes are deployed to a database as a jar, which is stored in the database as a blob. These blobs are organized in Projects, which are identified by their name. Every time you deploy a new version of the logic classes, you assign it to a Project, and you can optionally specify when these logic classes should take effect.

 This logic manager accepts the following configuration parameters:

 Parameter name
 Value
 project_name The name of the Project (in the database) containing the desired logic. This is required.
 check_min_interval The minimum amount of time between checks of whether the logic jar has been updated in the database, in seconds. This is optional, the default is 600 (10 minutes).
This value should typically not be set too low, as that could lead to too many database queries.
 persistence_unit If the logic database is to be accessed via JPA, then this parameter specifies which persistence unit is to be used. Required if using JPA for the logic database.
 hibernate_cfg If the logic database is to be accessed directly via Hibernate, then this parameter specifies a Hibernate configuration file pointing to that database. Required if using direct Hibernate for the logic database.

A sample JPA persistence.xml file might look like this:

<persistence xmlns="http://java.sun.com/xml/ns/persistence"
             xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
             xsi:schemaLocation="http://java.sun.com/xml/ns/persistence
                        http://java.sun.com/xml/ns/persistence/persistence_1_0.xsd"

             version="1.0">
            
        <!-- Persistent unit for the application -->
     <persistence-unit name="TestDB" transaction-type="RESOURCE_LOCAL">
        <class>com.sample.data.Customer</class>
        <class>com.sample.data.PurchaseOrder</class>
        <!-- Etc.. etc... -->
    </persistence-unit>
   
    <!-- Persistence unit for the logic classes -->
    <persistence-unit name="LogicDB" transaction-type="RESOURCE_LOCAL">
        <provider>org.hibernate.ejb.HibernatePersistence</provider>
       
        <class>com.autobizlogic.abl.logic.dynamic.database.Project</class>
        <class>com.autobizlogic.abl.logic.dynamic.database.LogicFile</class>
        <class>com.autobizlogic.abl.logic.dynamic.database.LogicFileLog</class>
       
        <properties>
            <!-- You need the following few properties if you don't use a data source -->
            <property name="hibernate.connection.driver_class" value="org.hsqldb.jdbc.JDBCDriver"/>
            <property name="hibernate.connection.username" value="SA"/>
            <property name="hibernate.default_catalog" value="PUBLIC"/>
            <property name="hibernate.connection.url" value="jdbc:hsqldb:file:/Users/JaneDoe/LogicDb"/>
            <property name="hibernate.archive.autodetection" value="class" />
            <property name="hibernate.current_session_context_class" value="thread" />
            <property name="hibernate.dialect" value="org.hibernate.dialect.HSQLDialect" />
            <property name="hibernate.bytecode.use_reflection_optimizer" value="true" />           
        </properties>
       
    </persistence-unit>
</persistence>


Note that there are two persistence units shown here: one for the application, and one for the logic classes. The first one is abbreviated, since it's not really relevant here. The second one is only a sample, and you can use all the standard configuration options: data sources, JTA, etc... Also note that the three classes (Project, LogicFile and LogicFileLog) must be mentioned in the persistence unit

If you wanted to access the logic database without JPA, using straight Hibernate, your configuration file might look like:

<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE hibernate-configuration PUBLIC
"-//Hibernate/Hibernate Configuration DTD 3.0//EN"
"http://www.hibernate.org/dtd/hibernate-configuration-3.0.dtd">
<hibernate-configuration>
    <session-factory>
        <property name="hibernate.connection.driver_class">org.hsqldb.jdbc.JDBCDriver</property>
        <property name="hibernate.connection.url">jdbc:hsqldb:file:/Users/JaneDoe/LogicDb</property>
        <property name="hibernate.connection.username">SA</property>
        <property name="hibernate.connection.password">supersecret</property>
        <property name="hibernate.default_catalog">LOGIC</property>
        <property name="hibernate.dialect">org.hibernate.dialect.HSQLDialect</property>
        <property name="hibernate.current_session_context_class">thread</property>
        <property name="hibernate.hbm2ddl.auto">update</property>
    </session-factory>
</hibernate-configuration>

This is only an example, obviously. You can set up this file in any way that works for you. You can use the hibernate.hbm2ddl.auto option to automatically create the required tables the first time, or you can create them by hand using the script that ships with the product (abl/doc/DynamicLogicSchema.sql).
Note that this configuration file does not reference any persistent objects. That's because the relevant objects are configured automatically at runtime.

This all begs the question: how does one load the logic classes into this database?

Logic deployer

The ABL engine jar contains a command-line utility, which you can use to deploy a jar of logic classes to a database. It can be invoked as follows:

java com.autobizlogic.abl.logic.dynamic.Deployer <hibernate-config-file> <project-name> <jar-file> [<effective-date>]

for instance:

java com.autobizlogic.abl.logic.dynamic.Deployer /Users/JaneDoe/projects/DynamicLogic.cfg.xml "Test project" /Users/JaneDoe/projects/Logic.jar 2012-01-19-23:59

  • The first parameter is the name of a Hibernate configuration file pointing to the desired database.
  • The second parameter is the name of the project. The same name should be used in the ABLConfig.properties file as the value for the project_name parameter. Note that the same database can contain multiple projects, which allows you to use this database for any number of different applications. If the given project does not exist, it will be created.
  • The third parameter is the name of the jar file which contains the logic classes.
  • The fourth parameter is optional. If specified, it should be in the format YYYY-MM-DD-hh:mm and will specify the point in time at which the new logic classes should take effect. If not specified, the default is now.
Note that this deployment can also be done using the API. See the JavaDoc documentation for the Deployer class.

Implementing your own logic manager class

If these three logic managers do not fulfill your needs, or if you'd like to customize them, you can subclass them, or even create a brand new one from scratch. All that is required is that it implement the com.autobizlogic.abl.logic.dynamic.LogicClassManager interface. We recommend that you look at one of the standard implementations' source code to better understand what is expected of this class.

Once you do have such a class, you can use it by specifying it in your ABLConfig.properties, for instance:

# Use our custom logic manager
logicClassManager1=com.acme.logic.MyLogicManager

logicClassManager1_first_parameter=something
logicClassManager1_second_parameter=something else


The first line is obviously the full name of your class, which implements the com.autobizlogic.abl.logic.dynamic.LogicClassManager interface. The other lines will be provided to your class's constructor on instantiation as a Map<String, String>, which, in this particular example, would contain two values:

 first_parameter something
 second_parameter something else

See the Javadoc documentation for the LogicClassManager interface for further details.

Server Considerations

In some environments, such as Tomcat, the server may be restarted if you change any classes in the app. This may cause problems with database connections if the application does not properly clean up on shutdown.
To avoid this issue, you can disable app reloading in Tomcat as shown below:

This will prevent Tomcat from restarting the server when you make changes to your classes. Your logic classes, however, will of course be reloaded when they change.

Servers other than Tomcat may use a different convention, obviously -- consult their documentation for details.

Comments