www.espertech.comDocumentation

Chapter 17. Configuration

17.1. Overview
17.2. Programmatic Configuration
17.3. Configuration via XML File
17.4. Configuration Common
17.4.1. Annotation Class and Package Imports
17.4.2. Class and Package Imports
17.4.3. Events Represented by Classes
17.4.4. Events Represented by java.util.Map
17.4.5. Events Represented by Object[] (Object-array)
17.4.6. Events Represented by JSON
17.4.7. Events Represented by Avro GenericData.Record
17.4.8. Events Represented by org.w3c.dom.Node
17.4.9. Event Type Defaults
17.4.10. Event Type Import Package (Event Type Auto-Name)
17.4.11. From-Clause Method Invocation
17.4.12. Relational Database Access
17.4.13. Common Settings Related to Logging
17.4.14. Common Settings Related to Time Source
17.4.15. Variables
17.4.16. Variant Stream
17.5. Configuration Compiler
17.5.1. Compiler Settings Related to Byte Code Generation
17.5.2. Compiler Settings Related to View Resources
17.5.3. Compiler Settings Related to Logging
17.5.4. Compiler Settings Related to Stream Selection
17.5.5. Compiler Settings Related to Language and Locale
17.5.6. Compiler Settings Related to Expression Evaluation
17.5.7. Compiler Settings Related to Scripts
17.5.8. Compiler Settings Related to Execution of Statements
17.5.9. Compiler Settings Related to Serializers and Deserializers
17.6. Configuration Runtime
17.6.1. Runtime Settings Related to Concurrency and Threading
17.6.2. Runtime Settings Related to Logging
17.6.3. Runtime Settings Related to Variables
17.6.4. Runtime Settings Related to Patterns
17.6.5. Runtime Settings Related to Match-Recognize
17.6.6. Runtime Settings Related to Time Source
17.6.7. Runtime Settings Related to JMX Metrics
17.6.8. Runtime Settings Related to Metrics Reporting
17.6.9. Runtime Settings Related to Expression Evaluation
17.6.10. Runtime Settings Related to Execution of Statements
17.6.11. Runtime Settings Related to Exception Handling
17.6.12. Runtime Settings Related to Condition Handling
17.7. Passing Services or Transient Objects
17.7.1. Service Example
17.7.2. Class-for-Name
17.7.3. Class Loader
17.8. Type Names
17.9. Logging Configuration
17.9.1. Log4j Logging Configuration

Compile-time and runtime configuration is entirely optional. The compiler and runtime work out-of-the-box without configuration.

All configuration lives in the Configuration class (com.espertech.esper.common.client.configuration.Configuration).

The configuration class has configure methods that can read configuration XML and that add the information contained in the XML to the configuration. You can read multiple XML sources additively.

A configuration has three sections:

  • The common section with configuration that both the compiler and the runtime may use, represented by the ConfigurationCommon class.

  • The compiler section, which provides configuration for use only by the compiler, represented by the ConfigurationCompiler class.

  • The runtime section, which provides configuration for use only by the runtime, represented by the ConfigurationRuntime class.

Configuration is an initialization-time object. The compiler does not retain any association back to configuration. The runtime makes a deep copy of the configuration object available (see getConfigurationDeepCopy on EPRuntime) but the configuration object cannot be changed once provided to the runtime.

You may obtain a Configuration instance by instantiating it directly and adding or setting values on it.

The following example code adds a preconfigured event type and adds an import to the common section of the configuration.

Configuration configuration = new Configuration();
configuration.getCommon().addEventType("PriceLimit", PriceLimit.class.getName());
configuration.getCommon().addImport("org.mycompany.mypackage.MyUtility");

The above example adds a preconfigured event type. For adding an event type at runtime please use create schema.

In addition to programmatic configuration, or as an alternative approach, you may specify configuration items in XML files.

The default name for the XML configuration file is esper.cfg.xml. The configuration class reads this file from the root of the CLASSPATH as an application resource via the configure method.

Configuration configuration = new Configuration();		
configuration.configure();

The Configuration class can read the XML configuration file from other sources as well. The configure method accepts URL, File and String filename parameters.

Configuration configuration = new Configuration();		
configuration.configure("myconfigfile.esper.cfg.xml");

The schema for the configuration file can be found in the etc folder and is named esper-configuration-majorversion-0.xsd. The schema is available online at http://www.espertech.com/schema/esper/esper-configuration-majorversion-0.xsd so that a tool can fetch it automatically. The namespace is http://www.espertech.com/schema/esper.

You can use the XML schema file to validate that your XML configuration file is valid.

Here is an example configuration file.

<?xml version="1.0" encoding="UTF-8"?>
<esper-configuration xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xmlns="http://www.espertech.com/schema/esper"
    xsi:schemaLocation="
http://www.espertech.com/schema/esper
http://www.espertech.com/schema/esper/esper-configuration-8-0.xsd">
  <common>
    <event-type name="PriceLimit" class="com.espertech.esper.example.stockticker.event.PriceLimit"/>
    <auto-import import-name="org.mycompany.mypackage.MyUtility"/>
  </common>
</esper-configuration>

The common section of the configuration applies to the compiler and also applies to the runtime.

EPL allows invocations of static Java library functions in expressions, as outlined in Section 10.1, “Single-Row Function Reference”. This configuration item can be set to allow a partial rather than a fully qualified class name in such invocations. The imports work in the same way as in Java files, so both packages and classes can be imported.

select Math.max(priceOne, PriceTwo)
// via configuration equivalent to
select java.lang.Math.max(priceOne, priceTwo)

EPL auto-imports the following Java library packages. Any additional imports that are specified in configuration files or through the API are added to the configuration in addition to the imports below.

  • java.lang.*

  • java.math.*

  • java.text.*

  • java.util.*

In a XML configuration file the auto-import configuration may look as below:

<esper-configuration xmlns="http://www.espertech.com/schema/esper">
  <common>
    <auto-import import-name="com.mycompany.mypackage.*"/>
    <auto-import import-name="com.mycompany.myapp.MyUtilityClass"/>  
  </common>
</esper-configuration>

Here is an example of providing imports via the API:

Configuration config = new Configuration();
config.getCommon().addImport("com.mycompany.mypackage.*");	// package import
config.getCommon().addImport("com.mycompany.mypackage.MyLib");   // class import

This section is relevant if you want to use regular classes to represent events.

The runtime can process event objects via the sendEventBean(Object event, String eventTypeName) method on the EPEventService interface.

You can use this setting herein when method and member variable names in your Java class do not adhere to the JavaBean convention - any public methods and public member variables can be exposed as event properties via the below configuration.

A Java class can optionally be configured with an accessor style attribute. This attribute instructs the compiler how it should expose methods and fields for use as event properties in statements.


For NEsper .NET accessor styles are NATIVE, PUBLIC and EXPLICIT.

Using the public setting for the accessor-style attribute instructs the compiler to expose an event property for each public method and public member variable of a Java class. The compiler assigns event property names of the same name as the name of the method or member variable in the Java class.

For example, assuming the class MyLegacyEvent exposes a method named readValue and a member variable named myField, you can then use properties as shown.

select readValue, myField from MyLegacyEvent

Using the explicit setting for the accessor-style attribute requires that event properties are declared via configuration. This is outlined in the next chapter.

When configuring a compiler or runtime from a XML configuration file, the XML snippet below demonstrates the use of the legacy-type element and the accessor-style attribute.

<esper-configuration xmlns="http://www.espertech.com/schema/esper">
  <common>
    <event-type name="MyLegacyEvent" class="com.mycompany.mypackage.MyLegacyEventClass">
      <legacy-type accessor-style="public"/>
    </event-type>
  </common>
</esper-configuration>

When configuring an compiler or runtime via Configuration API, the sample code below shows how to set the accessor style.

Configuration configuration = new Configuration();
ConfigurationCommonEventTypeBean legacyDef = new ConfigurationCommonEventTypeBean();
legacyDef.setAccessorStyle(AccessorStyle.PUBLIC);
configuration.getCommon().addEventType("MyLegacyEvent", MyLegacyEventClass.class.getName(), legacyDef);

Sometimes it may be convenient to use event property names in pattern and statements that are backed up by a given public method or member variable (field) in a Java class. And it can be useful to declare multiple event properties that each map to the same method or member variable.

We can configure properties of events via method-property and field-property elements, as the next example shows.

<esper-configuration xmlns="http://www.espertech.com/schema/esper">
  <common>
      <event-type name="StockTick" class="com.espertech.esper.example.stockticker.event.StockTickEvent">
        <legacy-type accessor-style="javabean" code-generation="enabled">
          <method-property name="price" accessor-method="getCurrentPrice" />
          <field-property name="volume" accessor-field="volumeField" />
       </legacy-type>
    </event-type>
  </common>
</esper-configuration>

The XML configuration snippet above declared an event property named price backed by a getter-method named getCurrentPrice, and a second event property named volume that is backed by a public member variable named volumeField. Thus the price and volume properties can be used in a statement:

select avg(price * volume) from StockTick

As with all configuration options, the API can also be used:

Configuration configuration = new Configuration();
ConfigurationCommonEventTypeBean legacyDef = new ConfigurationCommonEventTypeBean();
legacyDef.addMethodProperty("price", "getCurrentPrice");
legacyDef.addFieldProperty("volume", "volumeField");
configuration.getCommon().addEventType("StockTick", StockTickEvent.class.getName(), legacyDef);

The insert into clause and directly instantiate and populate your event object. By default the runtime invokes the default constructor to instantiate an event object. To change this behavior, you may configure a factory method. The factory method is a method name or a class name plus a method name (in the format class.method) that returns an instance of the class.

The update clause can change event properties on an event object. For the purpose of maintaining consistency, the runtime may have to copy your event object via serialization (implement the java.io.Serializable interface). If instead you do not want any copy operations to occur, or your application needs to control the copy operation, you may configure a copy method. The copy method is the name of a method on the event object that copies the event object.

The sample below shows this option in XML configuration, however the setting can also be changed via ConfigurationCommonEventTypeBean:

<esper-configuration xmlns="http://www.espertech.com/schema/esper">
  <common>
    <event-type name="MyLegacyEvent" class="com.mycompany.package.MyLegacyEventClass">
      <legacy-type factory-method="com.mycompany.myapp.MySampleEventFactory.createMyLegacyTypeEvent" copy-method="myCopyMethod"/>
    </event-type>
  </common>
</esper-configuration>

The copy method should be a public method that takes no parameters and returns a new event object (it may not return this). The copy method may not be a static method and may not take parameters.

The Beacon data flow operator in connection with the Sun JVM can use sun.reflect.ReflectionFactory if the class has no default no-argument constructor.

The runtime can process java.util.Map events via the sendEventMap(Map map, String eventTypeName) method on the EPEventService interface. Entries in the Map represent event properties. Please see the Appendix E, Event Representation: java.util.Map Events section for details on how to use Map events with the runtime.

You can provide an event type name for Map events.

The below snippet of XML configuration configures an event type named MyMapEvent.

<esper-configuration xmlns="http://www.espertech.com/schema/esper">
  <common>
    <event-type name="MyMapEvent">
      <java-util-map>
        <map-property name="carId" class="int"/>
        <map-property name="carType" class="string"/>
        <map-property name="assembly" class="com.mycompany.Assembly"/>    
      </java-util-map>
    </event-type>
  </common>
</esper-configuration>

For NEsper .NET use util-map instead of java-util-map.

This configuration defines the carId property of MyMapEvent events to be of type int, and the carType property to be of type java.util.String. The assembly property of the Map event will contain instances of com.mycompany.Assembly for the runtime to query.

The valid types for the class attribute are listed in Section 17.8, “Type Names”. In addition, any fully-qualified Java class name that can be resolved via Class.forName is allowed.

You can also use the configuration API to configure Map event types, as the short code snippet below demonstrates:

Map<String, Object> properties = new LinkedHashMap<String, Object>();
properties.put("carId", "int");
properties.put("carType", "string");
properties.put("assembly", Assembly.class.getName());

Configuration configuration = new Configuration();
configuration.getCommon().addEventType("MyMapEvent", properties);

A Map event type may also become a subtype of one or more supertypes that must also be Map event types. The java-util-map element provides the optional attribute supertype-names that accepts a comma-separated list of names of Map event types that are supertypes to the type:

<esper-configuration xmlns="http://www.espertech.com/schema/esper">
  <common>
    <event-type name="AccountUpdate">
      <java-util-map supertype-names="BaseUpdate, AccountEvent">
      </java-util-map>
    </event-type>
  </common>
</esper-configuration>

A Map event type may declare a start and end timestamp property name. The XML shown next instructs the compiler that the startts property carries the event start timestamp and the endts property carries the event end timestamp:

<esper-configuration xmlns="http://www.espertech.com/schema/esper">
  <common>
    <event-type name="AccountUpdate">
      <java-util-map start-timestamp-property-name="startts" end-timestamp-property-name="endts">
      </java-util-map>
    </event-type>
  </common>
</esper-configuration>

For adding a type at runtime please use create map schema.

The runtime can process Object-array (Object[]) events via the sendEventObjectArray(Object[] array, String eventTypeName) method on the EPEventService interface. Elements in the Object array represent event properties. Please see the Appendix F, Event Representation: Object-Array (Object[]) Events section for details on how to use Object[] events with the runtime.

The below snippet of XML configuration configures an event type named MyObjectArrayEvent.

<esper-configuration xmlns="http://www.espertech.com/schema/esper">
  <common>
    <event-type name="MyObjectArrayEvent">
      <objectarray>
        <objectarray-property name="carId" class="int"/>
        <objectarray-property name="carType" class="string"/>
        <objectarray-property name="assembly" class="com.mycompany.Assembly"/>    
      </objectarray>
    </event-type>
  </common>
</esper-configuration>

This configuration defines the carId property of MyObjectArrayEvent events to be of type int and in the object array first element ([0]). The carType property to be of type java.util.String is expected in the second array element ([1]) . The assembly property of the object array event will contain instances of com.mycompany.Assembly for the runtime to query in element two ([2]).

Note that the runtime does not verify the length and property values of object array events when your application sends object-array events into the runtime. For the example above, the proper object array would look as follows: new Object[] {carId, carType, assembly}.

The valid types for the class attribute are listed in Section 17.8, “Type Names”. In addition, any fully-qualified Java class name that can be resolved via Class.forName is allowed.

You can also use the configuration API to configure Object[] event types, as the short code snippet below demonstrates:

String[] propertyNames = {"carId", "carType", "assembly"};
Object[] propertyTypes = {int.class, String.class, Assembly.class};

Configuration configuration = new Configuration();
configuration.getCommon().addEventType("MyObjectArrayEvent", propertyNames, propertyTypes);

An Object-array event type may also become a subtype of one supertype that must also be an Object-array event type. The objectarray element provides the optional attribute supertype-names that accepts a single name of an Object-array event type that is the supertype to the type:

<esper-configuration xmlns="http://www.espertech.com/schema/esper">
  <common>
    <event-type name="AccountUpdate">
      <objectarray supertype-names="BaseUpdate">
      </objectarray>
    </event-type>
  </common>
</esper-configuration>

An Object-array event type may declare a start and end timestamp property name. The XML shown next instructs the compiler that the startts property carries the event start timestamp and the endts property carries the event end timestamp:

<esper-configuration xmlns="http://www.espertech.com/schema/esper">
  <common>
    <event-type name="AccountUpdate">
      <objectarray start-timestamp-property-name="startts" end-timestamp-property-name="endts"/>
    </event-type>
  </common>
</esper-configuration>

For adding a type at runtime please use create objectarray schema.

The runtime can process Avro GenericData.Record events via the sendEventAvro(GenericData.Record event, String eventTypeName) method on the EPEventService interface. Please see the Appendix H, Event Representation: Avro Events (org.apache.avro.generic.GenericData.Record) section for details on how to use Avro events with the compiler and runtime.

The below snippet of XML configuration configures an event type named MyAvroEvent.

<esper-configuration xmlns="http://www.espertech.com/schema/esper">
  <common>
    <event-type name="MyAvroEvent">
      <avro schema-text='{"type":"record","name":"MyAvroEvent","fields":[{"name":"carId","type":"int"},{"name":"carType","type":{"type":"string","avro.java.string":"String"}}]}'/>
    </event-type>  
  </common>
</esper-configuration>

The sample Avro schema above in pretty-print is:

{
  "type" : "record",
  "name" : "MyAvroEvent",
  "fields" : [ {
    "name" : "carId",
    "type" : "int"
  }, {
    "name" : "carType",
    "type" : {
      "type" : "string",
      "avro.java.string" : "String"
    }
  } ]
}

This schema defines:

  1. A carId property of type int.

  2. A carType property of type string. Note:Wse the Avro-provided avro.java.string property to ensure is is a java.lang.String instance and not a java.lang.CharSequence) instance.

Note that the runtime does not verify that Avro events are valid or that they actually match the schema provided for the Avro event type.

You can also use the configuration API to configure Avro event types, as the short code snippet below demonstrates:

Configuration configuration = new Configuration();
ConfigurationCommonEventTypeAvro avroType = new ConfigurationCommonEventTypeAvro();
avroType.setAvroSchema(schema);
configuration.getCommon().addEventTypeAvro("MyAvroType", avroType);

For adding a type at runtime please use create avro schema.

An Avro event type may also become a subtype of one supertype that must also be an Avro event type. The avro element provides the optional attribute supertype-names that accepts a single name of an Avro event type that is the supertype to the type:

<esper-configuration xmlns="http://www.espertech.com/schema/esper">
  <common>
    <event-type name="MyAvroEvent">
      <avro supertype-names="BaseUpdate"/>
    </event-type>  
  </common>
</esper-configuration>

An Avro event type may declare a start and end timestamp property name. The XML shown next instructs the compiler that the startts property carries the event start timestamp and the endts property carries the event end timestamp:

<esper-configuration xmlns="http://www.espertech.com/schema/esper">
  <common>
    <event-type name="MyAvroEvent">
      <avro start-timestamp-property-name="startts" end-timestamp-property-name="endts"/>
    </event-type>  
  </common>
</esper-configuration>

Via this configuration item, or using create xml schema, the runtime can natively process org.w3c.dom.Node instances, i.e. XML document object model (DOM) nodes. Please see the Appendix I, Event Representation: org.w3c.dom.Node XML Events section for details on how to use Node events with the compiler and runtime.

EPL allows configuring XPath expressions as event properties. You can specify arbitrary XPath functions or expressions and provide a property name by which their result values will be available for use in expressions. Use the @XMLSchemaField annotation with create xml schema.

For XML documents that follow a XML schema, the compiler and runtime can load and interrogate your schema and validate event property names and types against the schema information.

Nested, mapped and indexed event properties are also supported in expressions against org.w3c.dom.Node events. Thus XML trees can conveniently be interrogated using the existing event property syntax for querying JavaBean objects, JavaBean object graphs or java.util.Map events.

In the simplest form, the compiler only requires a configuration entry containing the root element name and the event type name in order to process org.w3c.dom.Node events:

<esper-configuration xmlns="http://www.espertech.com/schema/esper">
  <common>
    <event-type name="MyXMLNodeEvent">
      <xml-dom root-element-name="myevent" />
    </event-type>
  </common>
</esper-configuration>

You can also use the configuration API to configure XML event types, as the short example below demonstrates. In fact, all configuration options available through XML configuration can also be provided via setter methods on the ConfigurationEventTypeXMLDOM class.

Configuration configuration = new Configuration();
ConfigurationCommonEventTypeXMLDOM desc = new ConfigurationCommonEventTypeXMLDOM();
desc.setRootElementName("myevent");
desc.addXPathProperty("name1", "/element/@attribute", XPathConstants.STRING);
desc.addXPathProperty("name2", "/element/subelement", XPathConstants.NUMBER);
configuration.getCommon().addEventType("MyXMLNodeEvent", desc);

The equivalent to above configuration is declaring the schema via create xml schema:

@XMLSchema(rootElementName='myevent')
@XMLSchemaField(name='name1', xpath='/element/@attribute', type='string')
@XMLSchemaField(name='name2', xpath='/element/subelement', type='number')
create xml schema MyXMLNodeEvent()

The next example presents configuration options in a sample configuration entry.

<esper-configuration xmlns="http://www.espertech.com/schema/esper">
  <common>
    <event-type name="AutoIdRFIDEvent">
      <xml-dom root-element-name="Sensor" schema-resource="data/AutoIdPmlCore.xsd" 
         default-namespace="urn:autoid:specification:interchange:PMLCore:xml:schema:1">
        <namespace-prefix prefix="pmlcore" 
           namespace="urn:autoid:specification:interchange:PMLCore:xml:schema:1"/>
        <xpath-property property-name="countTags" 
           xpath="count(/pmlcore:Sensor/pmlcore:Observation/pmlcore:Tag)" type="number"/>
      </xml-dom>
    </event-type>
  </common>
</esper-configuration>

The equivalent to above configuration is declaring the schema via create xml schema:

@XMLSchema(rootElementName='Sensor' schemaResource='data/AutoIdPmlCore.xsd', 
  defaultNamespace='urn:autoid:specification:interchange:PMLCore:xml:schema:1')
@XMLSchemaNamespacePrefix(prefix='pmlcore', namespace='urn:autoid:specification:interchange:PMLCore:xml:schema:1')" +
@XMLSchemaField(name='countTags', xpath='count(/pmlcore:Sensor/pmlcore:Observation/pmlcore:Tag)', type='number')
create xml schema AutoIdRFIDEvent()

This example configures an event property named countTags whose value is computed by an XPath expression. The namespace prefixes and default namespace are for use with XPath expressions and must also be made known to the compiler and runtime in order for the compiler/runtime to compile XPath expressions. Via the schema-resource attribute you can instruct the compiler/runtime to load a schema file. You may also use schema-text instead to provide the actual text of the schema.

The xpath-property element adds explicitly-names event properties to the event type that are computed via an XPath expression. In order for the XPath expression to compile, be sure to specify the default-namespace attribute and use the namespace-prefix to declare namespace prefixes.

XPath expression properties are strongly typed. The type attribute allows the following values. These values correspond to those declared by javax.xml.xpath.XPathConstants.

In case you need your XPath expression to return a type other than the types listed above, an optional cast-to type can be specified. If specified, the operation firsts obtains the result of the XPath expression as the defined type (number, string, boolean) and then casts or parses the returned type to the specified cast-to-type. At runtime, a warning message is logged if the XPath expression returns a result object that cannot be casted or parsed.

The next line shows how to return a long-type property for an XPath expression that returns a string:

desc.addXPathProperty("name", "/element/sub", XPathConstants.STRING, "long");

For use with create xml schema it is:

@XMLSchemaField(name='name', xpath='/element/sub', type='string', castToType='long')

The equivalent configuration XML is:

<xpath-property property-name="name"  xpath="/element/sub" type="string" cast="long"/>

See Section 17.8, “Type Names” for a list of cast-to type names.

This setting indicates that when properties are compiled to XPath expressions that the compilation should generate an absolute XPath expression or a deep (find element) XPath expression.

For example, consider the following statement against an event type that is represented by a XML DOM document, assuming the event type GetQuote has been configured with the compiler as a XML DOM event type:

select request, request.symbol from GetQuote

By default, the compiler compiles the "request" property name to an XPath expression "/GetQuote/request". It compiles the nested property named "request.symbol" to an XPath expression "/GetQuote/request/symbol", wherein the root element node is "GetQuote".

By setting absolute property resolution to false, the compiler compiles the "request" property name to an XPath expression "//request". It compiles the nested property named "request.symbol" to an XPath expression "//request/symbol". This enables these elements to be located anywhere in the XML document.

The setting is available in XML via the attribute resolve-properties-absolute.

The configuration API provides the above settings as shown here in a sample code:

Configuration configuration = new Configuration();
ConfigurationCommonEventTypeXMLDOM desc = new ConfigurationCommonEventTypeXMLDOM();
desc.setRootElementName("GetQuote");
desc.setDefaultNamespace("http://services.samples/xsd");
desc.setRootElementNamespace("http://services.samples/xsd");
desc.addNamespacePrefix("m0", "http://services.samples/xsd");
desc.setXPathResolvePropertiesAbsolute(false);
configuration.getCommon().addEventType("GetQuote", desc);

The equivalent to above configuration is declaring the schema via create xml schema is:

@XMLSchema(rootElementName = 'GetQuote', defaultNamespace='http://services.samples/xsd',
  rootElementNamespace='http://services.samples/xsd', xpathResolvePropertiesAbsolute=false)
@XMLSchemaNamespacePrefix(prefix='m0', namespace='http://services.samples/xsd')
create xml schema GetQuote()

This configuration controls compiler settings in respect to Avro.

The enable-avro setting is boolean-typed and is false by default. It controls whether Avro is enabled or disabled. If disabled the compiler and runtime disallow registering Avro event types or using an Avro event representation.

The enable-native-string setting is boolean-typed and is true by default. It controls whether for String-type values, when the compiler generates an Avro schema, such field schema adds the property avro.java.string of value String.

The enable-schema-default-nonnull setting is boolean-typed and is true by default. It controls whether the compiler assembles non-null Avro schemas (true) or nullable (union) Avro schemas (false).

The objectvalue-typewidener-factory-class setting is a fully-qualified class name of the class implementing the com.espertech.esper.common.client.hook.type.ObjectValueTypeWidenerFactory interface and is null by default. If specified the factory can provide a type widener for widening, coercing or transforming any object value to a Avro field value.

The type-representation-mapper-class setting is a fully-qualified class name of the class implementing the com.espertech.esper.common.client.hook.type.TypeRepresentationMapper interface and is null by default. If specified the implementation can provide for a given class the Avro schema for the field.

The XML snippet below is an example of Avro settings that configures the same as the default values:

<esper-configuration xmlns="http://www.espertech.com/schema/esper">
  <common>
    <event-meta>
      <avro-settings enable-avro="false" enable-native-string="true" enable-schema-default-nonnull="true"
          objectvalue-typewidener-factory-class=""
          type-representation-mapper-class=""/>
    </event-meta>
  </common>
</esper-configuration>

The code snippet shown next sets the default event representation to Object-array in the configuration object:

Configuration configuration = new Configuration();
configuration.getCommon().getEventMeta().getAvroSettings().setEnableAvro(false);
configuration.getCommon().getEventMeta().getAvroSettings().setEnableNativeString(true);
configuration.getCommon().getEventMeta().getAvroSettings().setEnableSchemaDefaultNonNull(true);
configuration.getCommon().getEventMeta().getAvroSettings().setObjectValueTypeWidenerFactoryClass(null);
configuration.getCommon().getEventMeta().getAvroSettings().setTypeRepresentationMapperClass(null);

This configuration controls compiler and runtime settings in respect to XML XSD Schemas. More information can be found at Section I.2.1, “Getting Started”.

The enable-xmlxsd setting is boolean-typed and is false by default. It controls whether XML XSD schemas using Apache Xerces 2 is enabled or disabled. If disabled the compiler and runtime disallow registering XML XSD schema event types.

The XML snippet below is an example of the settings that configures the same as the default values:

<esper-configuration xmlns="http://www.espertech.com/schema/esper">
  <common>
    <event-meta enable-xmlxsd="false"\>
  </common>
</esper-configuration>

The code snippet shown next sets the default event representation to Object-array in the configuration object:

Configuration configuration = new Configuration();
configuration.getCommon().getEventMeta().setEnableXMLXSD(true);

This allows to control case sensitivity or accessor style for all event classes as a default. The two settings are found under class-property-resolution under event-meta in the XML common configuration.

To control the case sensitivity as discussed in Section 17.4.3.4, “Case Sensitivity and Property Names”, add the style attribute in the XML configuration to set a default case sensitivity applicable to all event classes unless specifically overridden by class-specific configuration. The default case sensitivity is case_sensitive (case sensitivity turned on).

To control the accessor style as discussed in Section 17.4.3.2, “Non-JavaBean and Legacy Java Event Classes”, add the accessor-style attribute in the XML configuration to set a default accessor style applicable to all event classes unless specifically overridden by class-specific configuration. The default accessor style is javabean JavaBean accessor style.

The next code snippet shows how to control this feature via the API:

Configuration config = new Configuration();
config.getCommon().getEventMeta().setClassPropertyResolutionStyle(
    PropertyResolutionStyle.CASE_INSENSITIVE);
config.getCommon().getEventMeta().setDefaultAccessorStyle(
    AccessorStyle.PUBLIC);

Method invocations are allowed in the from clause in EPL, such that your application may join event streams to the data returned by a web service, or to data read from a distributed cache or object-oriented database, or obtain data by other means. A local cache may be placed in front of such method invocations through the configuration settings described herein.

The LRU cache is described in detail in Section 17.4.12.6.1, “LRU Cache”. The expiry-time cache documentation can be found in Section 17.4.12.6.2, “Expiry-Time Cache”

The next XML snippet is a sample cache configuration that applies to methods provided by the classes 'MyFromClauseLookupLib' and 'MyFromClauseWebServiceLib'. The XML and API configuration understand both the fully-qualified Java class name, as well as the simple class name:

<esper-configuration xmlns="http://www.espertech.com/schema/esper">
  <common>
    <method-reference class-name="com.mycompany.MyFromClauseLookupLib">
      <expiry-time-cache max-age-seconds="10" purge-interval-seconds="10" ref-type="weak"/>
    </method-reference> 	
    <method-reference class-name="MyFromClauseWebServiceLib">
      <lru-cache size="1000"/>
    </method-reference>
  </common>
</esper-configuration>

For NEsper .NET also see Section J.17, “.NET Configurations - Relational Database Access”.

EPL has the capability to join event streams against historical data sources, such as a relational database. This section describes the configuration entries that the compiler or runtime require to access data stored in your database. Please see Section 5.13, “Accessing Relational Data via SQL” for information on the use of EPL queries that include historical data sources.

EPL queries that poll data from a relational database specify the name of the database as part of the statement. The compiler and runtime use the configuration information described here to resolve the database name in the statement to database settings. The required and optional database settings are summarized below.

  • Database connections can be obtained via JDBC javax.xml.DataSource, via java.sql.DriverManager and via data source factory. Either one of these methods to obtain database connections is a required configuration.

  • Optionally, JDBC connection-level settings such as auto-commit, transaction isolation level, read-only and the catalog name can be defined.

  • Optionally, a connection lifecycle can be set to indicate to the runtime whether the runtime must retain connections or must obtain a new connection for each lookup and close the connection when the lookup is done (pooled).

  • Optionally, define a cache policy to allow the runtime to retrieve data from a query cache, reducing the number of query executions.

Some of the settings can have important performance implications that need to be carefully considered in relationship to your database software, JDBC driver and runtime environment. This section attempts to outline such implications where appropriate.

The sample XML configuration file in the "etc" folder can be used as a template for configuring database settings. All settings are also available by means of the configuration API through the classes Configuration and ConfigurationDBRef.

This configuration causes the compiler or runtime to obtain a database connection from a javax.sql.DataSource available from your JNDI provider.

The setting is most useful when running within an application server or when a JNDI directory is otherwise present in your Java VM. If your application environment does not provide an available DataSource, the next section outlines how to use Apache DBCP as a DataSource implementation with connection pooling options and outlines how to use a custom factory for DataSource implementations.

If your DataSource provides connections out of a connection pool, your configuration should set the collection lifecycle setting to pooled.

The snippet of XML below configures a database named mydb1 to obtain connections via a javax.sql.DataSource. The datasource-connection element instructs the runtime to obtain new connections to the database mydb1 by performing a lookup via javax.naming.InitialContext for the given object lookup name. Optional environment properties for the InitialContext are also shown in the example.

<esper-configuration xmlns="http://www.espertech.com/schema/esper">
  <common>
    <database-reference name="mydb1">
      <datasource-connection context-lookup-name="java:comp/env/jdbc/mydb">
        <env-property name="java.naming.factory.initial" value ="com.myclass.CtxFactory"/>
        <env-property name="java.naming.provider.url" value ="iiop://localhost:1050"/>
      </datasource-connection>
    </database-reference>
  </common>
</esper-configuration>

To help you better understand how the runtime uses this information to obtain connections, please look at the logic below.

if (envProperties.size() > 0) {
  initialContext = new InitialContext(envProperties);
}
else {
  initialContext = new InitialContext();
}
DataSource dataSource = (DataSource) initialContext.lookup(lookupName);
Connection connection = dataSource.getConnection();

In order to plug-in your own implementation of the DataSource interface, your application may use an existing JNDI provider as provided by an application server if running in a J2EE environment.

In case your application does not have an existing JNDI implementation to register a DataSource to provide connections, you may set the java.naming.factory.initial property in the configuration to point to your application's own implementation of the javax.naming.spi.InitialContextFactory interface that can return your application DataSource though the javax.naming.Context provided by the factory implementation. Please see Java Naming and Directory Interface (JNDI) API documentation for further information.

This section describes how to use Apache Commons Database Connection Pooling (Apache DBCP). It explains how to provide a custom application-specific DataSource factory if not using Apache DBCP.

If your DataSource provides connections out of a connection pool, your configuration should set the collection lifecycle setting to pooled.

Apache DBCP provides comprehensive means to test for dead connections or grow and shrik a connection pool. Configuration properties for Apache DBCP can be found at Apache DBCP configuration. The listed properties are passed to Apache DBCP via the properties list provided as part of the configuration.

The snippet of XML below is an example that configures a database named mydb3 to obtain connections via the pooling DataSource provided by Apache DBCP BasicDataSourceFactory.

The listed properties are passed to DBCP to instruct DBCP how to manage the connection pool. The settings below initialize the connection pool to 2 connections and provide the validation query select 1 from dual for DBCP to validate a connection before providing a connection from the pool:

<esper-configuration xmlns="http://www.espertech.com/schema/esper">
  <common>
    <database-reference name="mydb3">
      <!-- For a complete list of properties see Apache DBCP. -->
      <!-- NOTE: "dbcp2" applies to api-2.0 of DBCP, use "dbcp" otherwise. -->
      <datasourcefactory-connection class-name="org.apache.commons.dbcp2.BasicDataSourceFactory">	
        <env-property name="username" value ="myusername"/>
        <env-property name="password" value ="mypassword"/>
        <env-property name="driverClassName" value ="com.mysql.jdbc.Driver"/>
        <env-property name="url" value ="jdbc:mysql://localhost/test"/>
        <env-property name="initialSize" value ="2"/>
        <env-property name="validationQuery" value ="select 1 from dual"/>
      </datasourcefactory-connection>
      <connection-lifecycle value="pooled"/>
    </database-reference>
  </common>
</esper-configuration>

The same configuration options provided through the API:

Properties props = new Properties();
props.put("username", "myusername");
props.put("password", "mypassword");
props.put("driverClassName", "com.mysql.jdbc.Driver");
props.put("url", "jdbc:mysql://localhost/test");
props.put("initialSize", 2);
props.put("validationQuery", "select 1 from dual");

ConfigurationCommonDBRef configDB = new ConfigurationCommonDBRef();
// BasicDataSourceFactory is an Apache DBCP import
configDB.setDataSourceFactory(props, BasicDataSourceFactory.class.getName());
configDB.setConnectionLifecycleEnum(ConfigurationCommonDBRef.ConnectionLifecycleEnum.POOLED);

Configuration configuration = new Configuration();;
configuration.getCommon().addDatabaseReference("mydb3", configDB);

Apache Commons DBCP is a separate download and not provided as part of the distribution. The Apache Commons DBCP jar file requires the Apache Commons Pool jar file.

Your application can provide its own factory implementation for DataSource instances: Set the class name to the name of the application class that provides a public static method named createDataSource which takes a single Properties object as parameter and returns a DataSource implementation. For example:

configDB.setDataSourceFactory(props, MyOwnDataSourceFactory.class.getName());
...
class MyOwnDataSourceFactory {
  public static DataSource createDataSource(Properties properties) {
    return new MyDataSourceImpl(properties);
  }
}

Cache settings can dramatically reduce the number of database queries that the runtime executes for statements. If no cache setting is specified, the runtime does not cache query results and executes a separate database query for every event.

Caches store the results of database queries and make these results available to subsequent queries using the exact same query parameters as the query for which the result was stored. If your query returns one or more rows, the cache keep the result rows of the query keyed to the parameters of the query. If your query returns no rows, the cache also keeps the empty result. Query results are held by a cache until the cache entry is evicted. The strategies available for evicting cached query results are listed next.

The expiry time cache is configured by a maximum age in seconds, a purge interval and an optional reference type. The cache discards (on the get operation) any query results that are older then the maximum age so that stale data is not used. If the cache is not empty, then every purge interval number of seconds the runtime purges any expired entries from the cache.

The XML configuration entry for an expiry-time cache is as follows. The example configures an expiry time cache in which prior query results are valid for 60 seconds and which the runtime inspects every 2 minutes to remove query results older then 60 seconds.

<esper-configuration xmlns="http://www.espertech.com/schema/esper">
  <common>
    <database-reference name="mydb">
    <!-- ... configure data source or driver manager settings... -->
        <expiry-time-cache max-age-seconds="60" purge-interval-seconds="120" />
    </database-reference>
  </common>
</esper-configuration>

By default, the expiry-time cache is backed by a java.util.WeakHashMap and thus relies on weak references. That means that cached SQL results can be freed during garbage collection.

Via XML or using the configuration API the type of reference can be configured to not allow entries to be garbage collected, by setting the ref-type property to hard:

<esper-configuration xmlns="http://www.espertech.com/schema/esper">
  <common>
    <database-reference name="mydb">
    <!-- ... configure data source or driver manager settings... -->
        <expiry-time-cache max-age-seconds="60" purge-interval-seconds="120" ref-type="hard"/>
    </database-reference>
  </common>
</esper-configuration>

The last setting for the cache reference type is soft: This strategy allows the garbage collection of cache entries only when all other weak references have been collected.

A variant stream is a predefined stream into which events of multiple disparate event types can be inserted, and which can be selected from in patterns and the from clause.

The name of the variant stream and, optionally, the type of events that the stream may accept, are part of the stream definition. By default, the variant stream accepts only the predefined event types. The compiler validates your insert into clause which inserts into the variant stream against the predefined types.

A variant stream can be set to accept any type of event, in which case all properties of the variant stream are effectively dynamic properties. Set the type variance flag to ANY to indicate the variant stream accepts any type of event.

The following XML configuration defines a variant stream by name OrderStream that carries only PartsOrder and ServiceOrder events:

<esper-configuration xmlns="http://www.espertech.com/schema/esper">
  <common>
    <variant-stream name="OrderStream">
      <variant-event-type name="PartsOrder"/>
      <variant-event-type name="ServiceOrder"/>
    </variant-stream>
  </common>
</esper-configuration>

This code snippet sets up a variant stream by name OutgoingEvent:

Configuration config = new Configuration();
ConfigurationCommonVariantStream variant = new ConfigurationCommonVariantStream();
variant.setTypeVariance(ConfigurationCommonVariantStream.TypeVariance.ANY);
config.getCommon().addVariantStream("OutgoingEvent", variant);

If specifying variant event type names, make sure such names have been configured for JavaBean, Map or XML events.

The setting include-debugsymbols is false by default. It controls whether the compiler generates debug symbols as part of the binary class.

The setting include-comments is false by default. It controls whether the compiler generates code that contains additional information to help tracing back generated code to the code that generated it.

The setting attach-epl is true by default. It controls whether the compiler adds the statement text of the statement to statement properties.

The setting attach-module-epl is false by default. It controls whether the compiler adds the EPL module text of the module to module properties.

The setting allow-subscriber is false by default. It controls whether the compiler adds code for handling subscribers. If this flag is false the setSubscriber method on the EPStatement class throws an exception.

The setting allow-inlined-class is true by default. It controls whether the compiler allows inlined-classes. If this flag is false the compiler throws an exception upon encountering an inlined-class.

The setting threadpool-compiler-num-threads sets the number of threads for compiling a statement to byte code and is eight (8) by default. Setting this value to zero disables multi-threading for compilation. When the number of threads is greater zero the calling thread generates classes for statements and the thread pool compiles statement classes to byte code. This setting improves compilation performance only when a module has multiple statements as the unit of parallelization is the statement. The setting threadpool-compiler-capacity defines the number of permits (capacity of the queue) for compiling statements to byte code and is unbound by default. Use null to represent unbound. The minimum value for capacity is one.

The setting max-methods-per-class sets the maximum number of methods in a class or inner class. This value defaults to 1024 (1k). This setting exists as the JVM limits the constant pool for each class to 64k. Among other things the JVM class constant pool contains method information. Therefore, for large EPL expressions, the compiler attempts to not exceed this JVM limit. Upon finding a class that exceeds the configured maximum number of methods the compiler moves methods into an additional class or multiple additional classes. The minimum value for this setting is 100. If this value is too large you may see a compilation message such as Constant pool for class has grown past JVM limit of 0xFFFF. Note that there can be other reasons for this message. Please see Section 15.19, “Limitations”.

The sample code below sets the same values as the default values:

Configuration configuration = new Configuration();
ConfigurationCompilerByteCode byteCode = configuration.getCompiler().getByteCode();
byteCode.setIncludeDebugSymbols(false);
byteCode.setIncludeComments(false);
byteCode.setAttachEPL(true);
byteCode.setAttachModuleEPL(false);
byteCode.setAllowSubscriber(false);
byteCode.setAllowInlinedClass(false);
byteCode.setInstrumented(false);
byteCode.setThreadPoolCompilerNumThreads(8);
byteCode.setThreadPoolCompilerCapacity(null);
byteCode.setMaxMethodsPerClass(16*1024);

The sample XML configuration below also sets default values:

<esper-configuration xmlns="http://www.espertech.com/schema/esper">
  <compiler>
    <bytecode 
      include-comments="false" 
      include-debugsymbols="false"
      attach-epl="true" 
      attach-module-epl="false" 
      instrumented="false" 
      allow-subscriber="false"
      allow-inlined-class="true"
      threadpool-compiler-num-threads="8"
      max-methods-per-class="16384"/>
  </compiler>
</esper-configuration>

Access modifiers default to private and are listed here. You may also use the @private, @protected and @public annotations or the CompilerOptions object to set access modifiers.


The setting bus-modifier-event-type is set to nonbus by default. This means that any of the sendEventType method of EPEventService cannot be used to process events of that event type. Set this value to bus to indicate that the respective sendEventType method of EPEventService can process events of event types declared by the module (sendEventType throws an exception if it does not find a visible event type). You may also use the @buseventtype annotation or the CompilerOptions object to set bus event type visibility.

The sample code below sets the same values as the default values:

Configuration configuration = new Configuration();
ConfigurationCompilerByteCode byteCode = configuration.getCompiler().getByteCode();
byteCode.setAccessModifierContext(NameAccessModifier.PRIVATE);
byteCode.setAccessModifierEventType(NameAccessModifier.PRIVATE);
byteCode.setAccessModifierNamedWindow(NameAccessModifier.PRIVATE);
byteCode.setAccessModifierScript(NameAccessModifier.PRIVATE);
byteCode.setAccessModifierTable(NameAccessModifier.PRIVATE);
byteCode.setAccessModifierVariable(NameAccessModifier.PRIVATE);
byteCode.setBusModifierEventType(EventTypeBusModifier.NONBUS);

The sample XML configuration below also sets default values:

<esper-configuration xmlns="http://www.espertech.com/schema/esper">
  <compiler>
    <bytecode 
      access-modifier-context="private" 
      access-modifier-event-type="private" 
      access-modifier-expression="private" 
      access-modifier-named-window="private" 
	  access-modifier-script="private" 
	  access-modifier-table="private" 
	  access-modifier-variable="private" 
	  bus-modifier-event-type="nonbus"
	  />
  </compiler>
</esper-configuration>

By default the compiler returns double-typed values for divisions regardless of operand types. Division by zero returns positive or negative double infinity.

To have compiler use Java-standard integer division instead, use this setting as described here. In Java integer division, when dividing integer types, the result is an integer type. This means that if you divide an integer unevenly by another integer, it returns the whole number part of the result, does not perform any rounding and the fraction part is dropped. If Java-standard integer division is enabled, when dividing an integer numerator by an integer denominator, the result is an integer number. Thus the expression 1 / 4 results in an integer zero. Your EPL must then convert at least one of the numbers to a double value before the division, for example by specifying 1.0 / 4 or by using cast(myint, double).

When using Java integer division, division by zero for integer-typed operands always returns null. However division by zero for double-type operands still returns positive or negative double infinity. To also return null upon division by zero for double-type operands, set the flag to true as below (default is false).

The XML configuration is as follows:

<esper-configuration xmlns="http://www.espertech.com/schema/esper">
  <compiler>
    <expression integer-division="false" division-by-zero-is-null="false"/>
  </compiler>
</esper-configuration>

The API to change the setting:

Configuration config = new Configuration();
config.getCompiler().getExpression().setIntegerDivision(true);
config.getCompiler().getExpression().setDivisionByZeroReturnsNull(true);

The compiler analyzes filter expressions and determines whether the OR logical operator occurs with the filter expression(s). This setting is only relevant to those filter expression that have OR. Please see Section 15.18, “Compiler Filter Expression Analysis” for more information.

In the default configuration the setting is 16, which means that the filter expression analyzer can at most create 16 path expressions from a given filter expression. If the number of path expressions is over 16, the expression will instead be evaluated as non-path and not be subject to to be entered into filter indexes.

On the level of a statement, this setting can be controlled by providing a hint. For example:

// The compiler optimizes the filter expression to become:
//   "a=1, c=1" or "b=1, c=1" or "a=1, d=1" or "b=1, d=1".
//   This enables filter index sharing between filter expressions.
select * from Event((a=1 or b=1) and (c=1 or d=1))
// The compiler does not optimize filter expressions
@Hint('MAX_FILTER_WIDTH=0') select * from Event((a=1 or b=1) and (c=1 or d=1))

The XML configuration to set a new value is:

<esper-configuration xmlns="http://www.espertech.com/schema/esper">
  <compiler>
    <execution filter-service-max-filter-width="100"/>
  </compiler>
</esper-configuration>

The API to change the setting:

Configuration config = new Configuration();
config.getCompiler().getExecution().
    setFilterServiceMaxFilterWidth(16);

The compiler analyzes filter expressions and determines whether to use filter indexes. Please see Section 15.18, “Compiler Filter Expression Analysis” for more information.

By default the compiler performs advanced planning. The default setting is ConfigurationCompilerExecution.FilterIndexPlanning.ADVANCED.

This setting is an enumeration value that can be set to none, basic or advanced (the default).

By setting none the compiler simply builds a single non-reusable boolean composite expression for any filter expressions.

By setting basic the compiler analyzes filter expressions and builds basic triplets. The EPL can specify filter index planning hints to enable those advanced planning features that your application needs.

By setting advanced (the default) the compiler analyzes filter expressions fully. In this case the filter index planning hints are not considered by the compiler.

The XML configuration example is:

<esper-configuration xmlns="http://www.espertech.com/schema/esper">
  <compiler>
    <execution filter-index-planning="advanced"/>
  </compiler>
</esper-configuration>

The API example to change the setting is:

Configuration config = new Configuration();
config.getCompiler().getExecution().setFilterIndexPlanning(
    ConfigurationCompilerExecution.FilterIndexPlanning.ADVANCED);

In multithreaded environments, this setting controls whether dispatches of statement result events to listeners preserve the ordering in which a statement processes events. By default the runtime guarantees that it delivers a statement's result events to statement listeners in the order in which the result is generated. This behavior can be turned off via configuration as below. This behavior applies to stateful statements and not to stateless statements as stateless statements execute lock-free.

The next code snippet shows how to control this feature:

Configuration config = new Configuration();
config.getRuntime().getThreading().setListenerDispatchPreserveOrder(false);

And the XML configuration file can also control this feature by adding the following elements:

<esper-configuration xmlns="http://www.espertech.com/schema/esper">
  <runtime>
    <threading>
      <listener-dispatch preserve-order="true" timeout-msec="1000" locking="spin"/>
    </threading>
  </runtime>
</esper-configuration>

As discussed, by default the runtime can temporarily block another processing thread when delivering result events to listeners in order to preserve the order in which results are delivered to a given statement. The maximum time the runtime blocks a thread can also be configured, and by default is set to 1 second.

As such delivery locks are typically held for a very short amount of time, the default blocking technique employs a spin lock (There are two techniques for implementing blocking; having the operating system suspend the thread until it is awakened later or using spin locks). While spin locks are CPU-intensive and appear inefficient, a spin lock can be more efficient than suspending the thread and subsequently waking it up, especially if the lock in question is held for a very short time. That is because there is significant overhead to suspending and rescheduling a thread.

The locking technique can be changed to use a blocking strategy that suspends the thread, by means of setting the locking property to 'suspend'.

In multithreaded environments, this setting controls whether statements producing events for other statements via insert-into preserve the order of delivery within the producing and consuming statements, allowing statements that consume other statement's events to behave deterministic in multithreaded applications, if the consuming statement requires such determinism. By default, the runtime makes this guarantee (the setting is on). This behavior applies to stateful statements and not to stateless statements as stateless statements execute lock-free.

Take, for example, an application where a single statement (S1) inserts events into a stream that another statement (S2) further evaluates. A multithreaded application may have multiple threads processing events into statement S1. As statement S1 produces events for consumption by statement S2, such results may need to be delivered in the exact order produced as the consuming statement may rely on the order received. For example, if the first statement counts the number of events, the second statement may employ a pattern that inspects counts and thus expect the counts posted by statement S1 to continuously increase by 1 even though multiple threads process events.

The runtime may need to block a thread such that order of delivery is maintained, and statements that require order (such as pattern detection, previous and prior functions) receive a deterministic order of events. The settings available control the blocking technique and parameters. As described in the section immediately prior, the default blocking technique employs spin locks per statement inserting events for consumption, as the locks in questions are typically held a very short time. The 'suspend' blocking technique can be configured and a timeout value can also defined.

The XML configuration file may change settings via the following elements:

<esper-configuration xmlns="http://www.espertech.com/schema/esper">
  <runtime>
    <threading>
      <insert-into-dispatch preserve-order="true" timeout-msec="100" locking="spin"/>
    </threading>
  </runtime>
</esper-configuration>

In multithreaded environments, this setting controls whether named windows producing insert and remove streams for other statements that consume the named window by means of from-clause preserve the order of delivery within the producing named window and the consuming statements, allowing statements that consume named window's insert and remove stream events to behave deterministic in multithreaded applications, if the consuming statement requires such determinism. By default, the runtime makes this guarantee (the setting is on) with spin locking and Long.MAX_VALUE as millisecond timeout.

Take, for example, an application where a named window (W1) produces inserts and remove stream events that a statement (S1) consumes. A multithreaded application may have multiple threads producing insert and remove stream events for consumption by statement S1. Such results may need to be delivered in the exact order produced by the named window as the consuming statement may rely on the order received.

The runtime may need to block a thread such that order of delivery is maintained, and statements that require order receive a deterministic order of events. The settings available control the blocking technique and parameters. As described in the section immediately prior, the default blocking technique employs spin locks per named window producing insert and removed stream events for consumption, as the locks in questions are typically held a very short time. The 'suspend' blocking technique can be configured and a timeout value can also defined.

The XML configuration file may change settings via the following elements:

<esper-configuration xmlns="http://www.espertech.com/schema/esper">
  <runtime>
    <threading>
      <named-window-consumer-dispatch preserve-order="true" locking="spin"/>
    </threading>
  </runtime>
</esper-configuration>

The settings described herein are for enabling advanced threading options for inbound, outbound, timer and route executions.

Take the next snippet of XML configuration as an example. It configures all threading options to 2 threads, which may not be suitable to your application, however demonstrates the configuration:

<esper-configuration xmlns="http://www.espertech.com/schema/esper">
  <runtime>
    <threading>
      <threadpool-inbound enabled="true" num-threads="2"/>
      <threadpool-outbound enabled="true" num-threads="2" capacity="1000"/>
      <threadpool-timerexec enabled="true" num-threads="2"/>
      <threadpool-routeexec enabled="true" num-threads="2"/>
    </threading>
  </runtime>
</esper-configuration>

By default, queues are unbound and backed by java.util.concurrent.LinkedBlockingQueue. The optional capacity attribute can be set to instruct the threading option to configure a capacity-bound queue with a sender-wait (blocking put) policy, backed ArrayBlockingQueue.

This example uses the API for configuring inbound threading :

Configuration config = new Configuration();
config.getRuntime().getThreading().setThreadPoolInbound(true);
config.getRuntime().getThreading().setThreadPoolInboundNumThreads(2);

With a bounded work queue, the queue size and pool size should be tuned together. A large queue coupled with a small pool can help reduce memory usage, CPU usage, and context switching, at the cost of potentially constraining throughput.

By default, the runtime does not produce debug output for the event processing execution paths even when Log4j or Logger configurations have been set to output debug level logs. To enable debug level logging, set this option in the configuration as well as in your Log4j configuration file.

Statement-level processing information can be output via the @Audit annotation, please see Section 15.12.1, “@Audit Annotation”.

When debug-level logging is enabled by setting the flag as below and by setting DEBUG in the Log4j configuration file, then the timer processing may produce extensive debug output that you may not want to have in the log file. The timer-debug setting in the XML or via API as below disables timer debug output which is enabled by default.

The API to use to enable debug logging and disable timer event output is shown here:

Configuration config = new Configuration();
config.getRuntime().getLogging().setEnableExecutionDebug(true);
config.getRuntime().getLogging().setEnableTimerDebug(false);

Note: this is a configuration option that applies to all runtime instances of a given Java module or VM.

The XML snippet is:

<esper-configuration xmlns="http://www.espertech.com/schema/esper">
  <runtime>
      <logging>
        <execution-path enabled="true"/>
        <timer-debug enabled="false"/>
    </logging>
  </runtime>
</esper-configuration>

This setting only applies if internal timer events control runtime time (default). If external timer events provide runtime clocking, the setting does not apply.

By default, the internal timer uses the call System.currentTimeMillis() to determine runtime time in milliseconds. Via this setting the internal timer can be instructed to use System.nanoTime() instead. Please see Section 16.9.2, “Time Resolution and Time Unit” for more information.

Note: This is a Java VM global setting. If running multiple runtime instances in a Java VM, the timer setting is global and applies to all runtime instances in the same Java VM, for performance reasons.

A sample XML configuration for this setting is shown below, whereas the sample setting sets the time source to the nanosecond time provider:

<esper-configuration xmlns="http://www.espertech.com/schema/esper">
  <runtime>
    <time-source>
      <time-source-type value="nano" />
    </time-source>
  </runtime>
</esper-configuration>

The equivalent code snippet using the configuration API is here:

Configuration config = new Configuration();
config.getRuntime().getTimeSource().setTimeSourceType(TimeSourceType.NANO);

This section explains how to enable and configure metrics reporting, which is by default disabled. Please see Section 16.12, “Runtime and Statement Metrics Reporting” for more information on the metrics data reported to your application.

The flag that enables metrics reporting is global to a Java virtual machine. If metrics reporting is enabled, the overhead incurred for reporting metrics is carried by all runtime instances per Java VM.

Metrics reporting occurs by a runtime-controlled separate daemon thread that each runtime instance starts at runtime initialization time, if metrics reporting and threading is enabled (threading enabled is the default).

Runtime and statement metric intervals are in milliseconds. A negative or zero millisecond interval value may be provided to disable reporting.

To control statement metric reporting for individual statements or groups of statements, the runtime provides a facility that groups statements by statement name. Each such statement group may have different reporting intervals configured, and intervals can be changed at runtime through runtime configuration. A statement group is assigned a group name at configuration time to identify the group.

Metrics reporting configuration is part of the runtime settings. All configuration options are also available via the Configuration API.

A sample XML configuration is shown below:

<esper-configuration xmlns="http://www.espertech.com/schema/esper">
  <runtime>
    <metrics-reporting enabled="true" runtime-interval="1000" statement-interval="1000" 
        threading="true"/>
  </runtime>
</esper-configuration>

The runtime-interval setting (defaults to 10 seconds) determines the frequency in milliseconds at which the runtime reports runtime metrics, in this example every 1 second. The statement-interval is for statement metrics. The threading flag is true by default since reporting takes place by a dedicated runtime thread and can be set to false to use the external or internal timer thread instead.

The next example XML declares a statement group: The statements that have statement names that fall within the group follow a different reporting frequency:

<esper-configuration xmlns="http://www.espertech.com/schema/esper">
  <runtime>
    <metrics-reporting enabled="true" statement-interval="0">
      <stmtgroup name="MyStmtGroup" interval="2000" default-include="true" num-stmts="100" 
           report-inactive="true">
        <exclude-regex>.*test.*</exclude-regex>
      </stmtgroup>
    </metrics-reporting>
  </runtime>
</esper-configuration>

The above example configuration sets the statement-interval to zero to disable reporting for all statements. It defines a statement group by name MyStmtGroup and specifies a 2-second interval. The example sets the default-include flag to true (by default false) to include all statements in the statement group. The example also sets report-inactive to true (by default false) to report inactive statements.

The exclude-regex element may be used to specify a regular expression that serves to exclude statements from the group. Any statement whose statement name matches the exclude regular expression is not included in the group. In the above example, all statements with the characters 'test' inside their statement name are excluded from the group.

Any statement not belonging to any of the statement groups follow the configured statement interval.

There are additional elements available to include and exclude statements: include-regex, include-like and exclude-like. The latter two apply SQL-like matching. All patterns are case-sensitive.

Here is a further example of a possible statement group definition, which includes statements whose statement name have the characters @REPORT or @STREAM, and excludes statements whose statement name have the characters @IGNORE or @METRICS inside.

<esper-configuration xmlns="http://www.espertech.com/schema/esper">
  <runtime>
    <metrics-reporting enabled="true">
      <stmtgroup name="MyStmtGroup" interval="1000">
        <include-like>%@REPORT%</include-like>
        <include-regex>.*@STREAM.*</include-regex>
        <exclude-like>%@IGNORE%</exclude-like>
        <exclude-regex>.*@METRICS.*</exclude-regex>
      </stmtgroup>
    </metrics-reporting>
  </runtime>
</esper-configuration>

By default, the runtime ignores event-precedence. This is because there can be a small performance cost for tracking event precedence.

Use this setting if your application requires a processing order of insert-into events according to event precedence. Enabling this setting means that the runtime makes sure that the events in the work queue are ordered by event precedence.

For more information on the work queue and order of event processing, see Section 16.8.2.2, “Processing Principles of Events and Listener Updates”.

For more information of the event-precedence keyword, please refer to Section 5.10.10, “Insert Into and Event Precedence”.

The XML configuration to enable the flag, which is disabled by default, is as follows:

<esper-configuration xmlns="http://www.espertech.com/schema/esper">
  <runtime>
    <execution precedence-enabled="true"/>
  </runtime>
</esper-configuration>

The API to change the setting:

Configuration config = new Configuration();
config.getRuntime().getExecution().setPrecedenceEnabled(true);

Use the settings as described here to register an exception handler factory class that provides an exception handler. The runtime invokes exception handlers in the order they are listed to handle a continues-query unchecked exception, as further described in Section 16.10, “Exception Handling”. Please provide the full-qualified class name of each class that implements the com.espertech.esper.common.client.hook.exception.ExceptionHandlerFactory interface in the runtime configuration as below.

By default, during a module undeploy when the runtime encounters a runtime exception for any of the statements it logs such exceptions as warnings. You can set the undeploy-rethrow-policy flag to rethrow_first instead have the runtime rethrow the first runtime exception.

The XML configuration is as follows:

<esper-configuration xmlns="http://www.espertech.com/schema/esper">
  <runtime>
    <exceptionHandling undeploy-rethrow-policy="warn">
      <handlerFactory class="my.company.cep.MyCEPRuntimeExceptionHandlerFactory"/>
    </exceptionHandling>
  </runtime>
</esper-configuration>

The API calls to register an exception handler factory are as follows:

Configuration config = new Configuration();
config.getRuntime().getExceptionHandling().addClass(MyCEPRuntimeExceptionHandlerFactory.class);
config.getRuntime().getExceptionHandling().setUndeployRethrowPolicy(UndeployRethrowPolicy.RETHROW_FIRST);

Tip

The application-provided exception handler receives an ExceptionHandlerContext instance that contains the exception detail. The application code that performs logging should log detailed information such as deployment and statement information. The information can be useful to troubleshoot exceptions.

For inspiration, there is a code extract of the runtime's default exception handling code below.

For reference, we include the default exception handling code here:

if (exceptionHandlers.isEmpty()) {
  StringWriter writer = new StringWriter();
  if (type == ExceptionHandlerExceptionType.PROCESS) {
    writer.append("Exception encountered processing ");
  } else {
    writer.append("Exception encountered performing instance stop for ");
  }
  writer.append("deployment-id '");
  writer.append(deploymentId);
  writer.append("' ");
  writer.append("statement '");
  writer.append(statementName);
  writer.append("'");
  if (optionalEPL != null) {
    writer.append(" expression '");
    writer.append(optionalEPL);
    writer.append("'");
  }
  writer.append(" : ");
  writer.append(t.getMessage());
  String message = writer.toString();

  if (type == ExceptionHandlerExceptionType.PROCESS) {
    log.error(message, t);
  } else {
    log.warn(message, t);
  }
  return;
}

ExceptionHandlerContext context = new ExceptionHandlerContext(runtimeURI, t, deploymentId, statementName, optionalEPL, type, optionalCurrentEvent);
for (ExceptionHandler handler : exceptionHandlers) {
  handler.handle(context);
}

Use the settings as described here to register a condition handler factory class that provides a condition handler. The runtime invokes condition handlers in the order they are listed to indicate conditions, which is the term used for notification when certain predefined limits are reached, as further described in Section 16.11, “Condition Handling”.

Please provide the full-qualified class name of each class that implements the com.espertech.esper.common.client.hook.condition.ConditionHandlerFactory interface in the runtime configuration as below.

The XML configuration is as follows:

<esper-configuration xmlns="http://www.espertech.com/schema/esper">
  <runtime>
    <conditionHandling>
      <handlerFactory class="my.company.cep.MyCEPRuntimeConditionHandlerFactory"/>
    </conditionHandling>
  </runtime>
</esper-configuration>

The API calls to register a condition handler factory are as follows:

Configuration config = new Configuration();
config.getRuntime().getConditionHandling().addClass(MyCEPRuntimeConditionHandlerFactory.class);

The Configuration object allows passing application objects such as services or other transient objects. This information can be used by extensions, listeners or subscribers, for example, to obtain application objects from the runtime. Your application may provide a custom class loader or class-for-name service.

Use setTransientConfiguration and provide a Map<String, Object> that contains the application objects. The runtime retains and makes available the same Map instance available via API. Its contents including services can be changed by an application at runtime. The API methods to retrieve transient configuration are:

  • The getConfigurationTransients method of EPRuntime

  • The getConfigurationDeepCopy method of EPRuntime

Certain configuration values accept type names. Type names can occur in the configuration of variable types, Map-event property types as well as XPath cast types, for example. Types names are not case-sensitive.

The table below outlines all possible type names:


For NEsper .NET also see Section J.18, “.NET Configurations - Logging Configuration”.

The compiler and runtime log all messages to SLF4J under an appropriate log level. To output log messages you can add Log4j and SLF4J-Log4j (1.2) to classpath and configure Log4j as below.

The only direct dependency for logging is the SLF4J interfaces (slf4j-api-x.y.z.jar). Please see the SLF4J documentation on redirecting logs to other logging frameworks.

Statement-level processing information can be output, please see Section 15.12.1, “@Audit Annotation”.

For performance reasons, the runtime does not log any debug-level or informational-level messages for event execution unless explicitly configured via Section 17.6.2.1, “Execution Path Debug Logging”.

A callback API for receiving certain critical runtime reports is available as described in Section 16.10, “Exception Handling”.

More information on configuring runtime-level settings for logging are at Section 17.6.2, “Runtime Settings Related to Logging”.

The next table explains the log levels:


Log4j is the default logging component. Please find additional information for Log4j configuration and extension in http://logging.apache.org/log4j.

The easiest way to configure Log4j is by providing a Log4J configuration file, similar to the log4j.xml file shipped in the etc folder of the distribution.

Add the log4j.configuration system property to the java command line and provide the file name of the Log4j configuration file, making sure your classpath also includes the directory of the file:

java -Dlog4j.configuration=log4j.xml ...