10.2.3. Storing Process Events in a JMS queue for further processing

Process events are stored in the database synchronously and within the same transaction as actual process instance execution. That obviously takes some time especially in highly loaded systems and might have some impact on the database when both history log and runtime data are kept in the same database. To provide an alternative option for storing process events, a JMS based logger has been provided. It can be configured to submit messages to JMS queue instead of directly persisting them in the database. It can be configured to be transactional as well to avoid issues with inconsistent data in case of jBPM engine transaction is rolled back.

ConnectionFactory factory = …;
Queue queue = …;
StatefulKnowledgeSession ksession = …;
Map<String, Object> jmsProps = new HashMap<String, Object>();
jmsProps.put(“jbpm.audit.jms.transacted”, true);
jmsProps.put(“jbpm.audit.jms.connection.factory”, factory);
jmsProps.put(“jbpm.audit.jms.queue”, queue);
AbstractAuditLogger auditLogger = AuditLoggerFactory.newInstance(Type.JMS, ksession, jmsProps);
ksession.addProcessEventListener(auditLogger);

// invoke methods one your session here

This is just one of possible ways to configure JMS audit logger, see javadocs for AuditLoggerFactory for more details.
10.2.4. Variables auditing

Process and task variables are stored in audit tables by default although there are stored in simplest possible way - by creating string representation of the variable - variable.toString(). In many cases this is enough as even for custom classes used as variables users can implement custom toString() method that produces expected “view” of the variable.

Though this might not cover all needs, especially when there is a need for efficient queries by variables (both task and process). Let’s take as an example a Person object that has following structure:

public class Person implements Serializable {

private static final long serialVersionUID = -5172443495317321032L;
private String name;
private int age;

public Person(String name, int age) {
    this.name = name;
    this.age = age;
}

public String getName() {
    return name;
}

public void setName(String name) {
    this.name = name;
}

public int getAge() {
    return age;
}

public void setAge(int age) {
    this.age = age;
}

@Override
public String toString() {
    return "Person [name=" + name + ", age=" + age + "]";
}

}

while at first look this seems to be sufficient as the toString() methods provide human readable format it does not make it easy to be searched by. As searching through strings like "Person [name=“john”, age=“34”] to find people with age 34 would make data base query very inefficient.

To solve the problem variable audit has been based on VariableIndexers that are responsible for extracting relevant parts of the variable that will be stored in audit log.

/**

  • Variable indexer that allows to transform variable instance into other representation (usually string)

  • to be able to use it for queries.

  • @param type of the object that will represent indexed variable
    */
    public interface VariableIndexer {

    /**

    • Tests if given variable shall be indexed by this indexer
    • NOTE: only one indexer can be used for given variable
    • @param variable variable to be indexed
    • @return true if variable should be indexed with this indexer
      */
      boolean accept(Object variable);

    /**

    • Performs index/transform operation of the variable. Result of this operation can be
    • either single value or list of values to support complex type separation.
    • For example when variable is of type Person that has name, address phone indexer could
    • build three entries out of it to represent individual fields:
    • person = person.name
    • address = person.address.street
    • phone = person.phone
    • that will allow more advanced queries to be used to find relevant entries.
    • @param name name of the variable
    • @param variable actual variable value
    • @return
      */
      List index(String name, Object variable);
      }

By default (indexer that takes the toString()) will produce single audit entry for single variable, so it’s one to one relationship. But that’s not the only option: indexers (as can be seen in the interface) returns list of objects that are the outcome of single variable indexation.

To make our person queries more efficient we could build custom indexer that would take Person instance and index it into separate audit entries one representing name and the other representing age.

public class PersonTaskVariablesIndexer implements TaskVariableIndexer {

@Override
public boolean accept(Object variable) {
    if (variable instanceof Person) {
        return true;
    }
    return false;
}

@Override
public List<TaskVariable> index(String name, Object variable) {

    Person person = (Person) variable;
    List<TaskVariable> indexed = new ArrayList<TaskVariable>();

    TaskVariableImpl personNameVar = new TaskVariableImpl();
    personNameVar.setName("person.name");
    personNameVar.setValue(person.getName());

    indexed.add(personNameVar);

    TaskVariableImpl personAgeVar = new TaskVariableImpl();
    personAgeVar.setName("person.age");
    personAgeVar.setValue(person.getAge()+"");

    indexed.add(personAgeVar);

    return indexed;
}

}

That indexer will then be used to index Person class only and rest of variables will be indexed with default (toString()) indexer. Now when we want to find process instances or tasks that have person with age 34 we simple refer to it as

variable name: person.age

variable value: 34

There is not even need to use like based queries so data base can optimize the query and make it efficient even with big set of data.

Building and registering custom indexers

Indexers are supported for both process and task variables. though they are supported by different interfaces as they do produce different type of objects representing audit view of the variable. Following are the interfaces to be implemented to build custom indexers:

process variables: org.kie.internal.process.ProcessVariableIndexer

task variables: org.kie.internal.task.api.TaskVariableIndexer

Implementation is rather simple, just two methods to be implemented

accept - indicates what types are handled by given indexer. Note that only one indexer can index given variable, so the first that accepts it will perform the work

index - actually does the work to index variables depending on custom requirements

Once the implementation is done, it should be packaged as jar file and following file needs to be included:

for process variables: META-INF/services/org.kie.internal.process.ProcessVariableIndexer with list of FQCN that represent the process variable indexers (single class name per line in that file)

for task variables: META-INF/services/org.kie.internal.task.api.TaskVariableIndexer with list of FQCN that represent the task variable indexers (single class name per line in that file)

Indexers are discovered by ServiceLoader mechanism and thus the META-INF/services files need. All found indexers will be examined whenever process or task variable is about to be indexed.

Only the default (toString() based) indexer is not discovered but added explicitly as last indexer to allow custom ones to take the precedence over it.

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值