1 Overview of Creating Oracle CEP Applications

This section contains information on the following subjects:

1.1 Overview of the Oracle CEP Programming Model

Because Oracle CEP applications are low latency high-performance event-driven applications, they run on a lightweight container and are developed using a POJO-based programming model. In POJO (Plain Old Java Object) programming, business logic is implemented in the form of POJOs, and then injected with the services they need. This is popularly called dependency injection. The injected services can range from those provided by Oracle CEP services, such as configuration management, to those provided by another Oracle product such as Oracle Kodo, to those provided by a third party.

Oracle CEP defines a set of core services or components used together to assemble event-driven applications; the typical services are adapters, streams, and processors. You can also create your own business logic POJOs and Spring beans that are part of the application, as well as specialized event beans that are just like Spring beans but with full access to the Oracle CEP framework, such as monitoring and record/playback of events. In addition to these, Oracle CEP includes other infrastructure services, such as caching, clustering, configuration, monitoring, logging, and so on.

All services are deployed on the underlying Oracle microServices Architecture (mSA) technology. Oracle mSA is based upon the OSGi Service Platform defined by the OSGi Alliance (see http://www.osgi.org/ for more information.)

The following sections provide additional information about the Oracle CEP programming model and creating applications:

1.1.1 Components of the Oracle CEP Event Processing Network

The Oracle CEP Event Processing Network (EPN) represents the interconnections between the various Oracle CEP components of an Oracle CEP application.

Oracle CEP applications and their EPNs are made up of the following basic components:

Each component on the EPN is known as a stage. Within the Oracle CEP IDE for Eclipse, each component on the EPN is also known as a node.

For more information, see:

1.1.1.1 Adapter

An adapter is a component that provides an interface to incoming data feeds and converts the data into event types that the Oracle CEP application understands.

Adapters can be both incoming (receive data) and outgoing (send data). Oracle CEP includes some built-in adapters, such as JMS and HTTP publish-subscribe adapters and adapters for configuring high availability.

For more information, see:

1.1.1.2 Channel

A channel is a component that represents the physical conduit through which events flow.

Channels connect components that send events with components that receive events. For more information, see Chapter 9, "Configuring Channels".

1.1.1.3 Processor

A processor is a component that executes user-defined event processing rules against the events offered by channels.

The user-defined rules are written using either of the following:

Note:

Oracle CQL replaces Event Processing Language (EPL) in Oracle CEP 11g Release 1 (11.1.1). Oracle CEP supports EPL for backwards compatibility.

1.1.1.4 Event Bean

An event bean is a user-coded Plain Old Java Object (POJO) bean managed by Oracle CEP.

Event beans are analogous to Spring beans, which are managed by the Spring framework, however they support event-based features, such as the specification of a suspend and resume methods. For more information, see Chapter 15, "Configuring Custom Event Beans".

1.1.1.5 Spring Bean

A spring bean is a user-coded Plain Old Java Object (POJO) managed by the Spring framework.

These components are not managed by Oracle CEP; for example, you cannot monitor these components, record and playback of events, and so on. If you require this additional functionality for your POJO, consider creating an Oracle CEP event bean instead. For more information, see Section 16, "Configuring Custom Spring Beans".

1.1.1.6 Cache

A cache is a temporary storage area for events, created exclusively to improve the overall performance of your application and to handle large amounts of historical data.

For more information, see:

1.1.1.7 Table

A table is a component that connects a relational database table to the EPN as an event data source.

You can access a relational database table from an Oracle CQL query using:

  • table source: using a table source, you may join a stream only with a NOW window and only to a single database table.

    Note:

    Because changes in the table source are not coordinated in time with stream data, you may only join the table source to an event stream using a Now window and you may only join to a single database table. For more information, see "S[now]" in the Oracle Complex Event Processing CQL Language Reference.

    To integrate arbitrarily complex SQL queries and multiple tables with your Oracle CQL queries, consider using the Oracle JDBC data cartridge instead.

    For more information, Section 10.3, "Configuring an Oracle CQL Processor Table Source".

  • Oracle JDBC data cartridge: using the Oracle JDBC data cartridge, you may integrate arbitrarily complex SQL queries and multiple tables and datasources with your Oracle CQL queries.

    Note:

    Oracle recommends that you use the Oracle JDBC data cartridge to access relational database tables from an Oracle CQL statement.

    For more information, see "Understanding the Oracle JDBC Data Cartridge" in the Oracle Complex Event Processing CQL Language Reference.

In all cases, you must define datasources in the Oracle CEP server config.xml file. For more information, see "Configuring Access to a Relational Database" in the Oracle Complex Event Processing Administrator's Guide.

Oracle CEP relational database table event sources are pull data sources: that is, Oracle CEP will periodically poll the event source.

1.1.1.8 Nested Stages

When you define a child stage within a parent stage in an EPN, the child stage is said to be nested. Only the parent stage can specify the child stage as a listener.

Example 1-1 shows the EPN assembly source in which HelloWorldBean is nested within the helloworldOutputChannel. Only the parent helloworldOutputChannel may specify the nested bean as a listener.

Example 1-1 EPN Assembly File With Nested Bean

<wlevs:adapter id="helloworldAdapter" class="com.bea.wlevs.adapter.example.helloworld.HelloWorldAdapter" >
    <wlevs:instance-property name="message" value="HelloWorld - the current time is:"/>
</wlevs:adapter>

<wlevs:channel id="helloworldInputChannel" event-type="HelloWorldEvent" >
    <wlevs:listener ref="helloworldProcessor"/>
    <wlevs:source ref="helloworldAdapter"/>
</wlevs:channel>

<wlevs:processor id="helloworldProcessor" />

<wlevs:channel id="helloworldOutput" event-type="HelloWorldEvent" advertise="true">
    <wlevs:listener>
        <bean class="com.bea.wlevs.example.helloworld.HelloWorldBean"/>
    </wlevs:listener>
    <wlevs:source ref="helloworldProcessor"/>
</wlevs:channel>

Alternatively, you can define this EPN so that all nodes are nested as Example 1-2 shows. The helloworldAdapter, the outermost parent stage, is the only stage accessible to other stages in the EPN.

Example 1-2 EPN Assembly File With all Nodes Nested

<wlevs:adapter id="helloworldAdapter" class="com.bea.wlevs.adapter.example.helloworld.HelloWorldAdapter" >
    <wlevs:instance-property name="message" value="HelloWorld - the current time is:"/>
    <wlevs:listener>
        <wlevs: id="helloworldInput" event-type="HelloWorldEvent" >
            <wlevs:listener>
                <wlevs:processor id="helloworldProcessor">
                    <wlevs:listener>
                        <wlevs: id="helloworldOutput" event-type="HelloWorldEvent">
                            <wlevs:listener>
                                <bean class="com.bea.wlevs.example.helloworld.HelloWorldBean"/>
                            </wlevs:listener>
                        </wlevs:>
                    </wlevs:listener>
                </wlevs:processor>
            </wlevs:listener>
        </wlevs:>
    </wlevs:listener>
</wlevs:adapter>

For more information, see Section 6.2.9, "Nested Stages".

1.1.1.9 Foreign Stages

You can refer to a stage simply by its id attribute when you define both the source and target stage in the same application.

To refer to a stage you define in a different application, you use the following syntax:

FOREIGN-APPLICATION-NAME:FOREIGN-STAGE-ID

Where FOREIGN-APPLICATION-NAME is the name of the application in which you defined the foreign stage and FOREIGN-STAGE-ID is the id attribute of the foreign stage.

Example 1-3 shows how the reference in application1 to the foreign stage HelloWorldBeanSource that you define in application application2.

Example 1-3 Application 1 Referencing Foreign Stage in Application 2

<wlevs:stream id="helloworldInstream" >
    <wlevs:listener ref="helloworldProcessor"/>
    <wlevs:source ref="application2:HelloWorldBeanSource"/>
</wlevs:stream>

Example 1-4 Foreign Stage in Application 2

<wlevs:event-bean id="HelloWorldBeanSource"
class="com.bea.wlevs.example.helloworld.HelloWorldBeanSource"
advertise="true"/> 

The following stages cannot be foregin stages:

  • Cache

When creating Oracle CEP applications with foreign stages, you must consider foreign stage dependencies when assembling, deploying, and redeploying your application. For more information, see Section 24.2.3, "Assembling Applications With Foreign Stages".

1.1.2 Oracle CEP Event Types

Event types define the properties of the events that are handled by Oracle CEP applications. Adapters receive incoming events from different event sources, such as the Java Messaging System (JMS), or financial market data feeds. You must define an Oracle CEP event type for these events before a processor is able to handle them. You then use these event types in adapter and POJO Java code, and in the Oracle CQL and EPL rules you associate with the processors.

Events are JavaBean or Java class instances in which each property represents a data item from the event source. Oracle CEP supports a variety of event type implementations.

For more information, see Chapter 2, "Overview of Oracle CEP Events".

1.1.3 Transmitting Events in the EPN: Stream and Relation Sources and Sinks

All components in an EPN either produce events or consume events. Some components can do both, such as an event bean in the middle of an EPN that receives events from an upstream component, such as an adapter, and then sends events to a downstream component, such as a processor.

Components can act on the events they receive from an upstream component, pass events on to a downstream component, and create new events and insert them into an upstream or downstream channel.

In general, predefined components (such as JMS and HTTP publish-subscribe adapters, channels, and processors) all implement the required interfaces to operate as stream and relation sources and sinks. You can use them as is or configure their behavior using the EPN assembly file.

For custom adapters, event beans, and Spring beans, you must implement the appropriate interfaces to use these components as stream and relation sources and sinks.

This section describes:

For more information, see Section 1.1.9.6, "User Action: Calling Methods of Stream and Relation Sources and Sinks".

1.1.3.1 Streams and Relations

Oracle CEP models event flow as either streams or relations:

  • A stream S is a bag multi-set of elements (s,T) where s is in the schema of S and T is in the time domain. Stream elements are tuple-timestamp pairs, which can be represented as a sequence of timestamped tuple insertions. In other words, a stream is a sequence of timestamped tuples. There could be more than one tuple with the same timestamp. The tuples of an input stream are required to arrive at the system in the order of increasing timestamps.

    You specify a channel as a stream by setting EPN assembly element wlevs: attribute is-relation to false (the default).

  • A relation is an unordered, time-varying bag of tuples: in other words, an instantaneous relation. At every instant of time, a relation is a bounded set. It can also be represented as a sequence of timestamped tuples that includes insertions, deletions, and updates to capture the changing state of the relation.

    You specify a channel as a relation by setting EPN assembly element wlevs:channel attribute is-relation to true.

For more information, see:

1.1.3.2 Stream and Relation Sources

All components that produce events must implement one of the following interfaces:

com.bea.wlevs.ede.api.StreamSource

The StreamSource interface has one method, setEventSender; at runtime the event source component is injected with a com.bea.wlevs.ede.api.StreamSender instance.

The StreamSender instance, in turn, has a sendInsertEvent method that the component invokes to actually send events to the next component in the EPN.

The StreamSender instance also provides a sendHeartbeat method. The sendHeartBeat method applies only to application-timestamped channels.

If you enable batching on a channel, then components that send events to that channel must implement the com.bea.wlevs.ede.api.BatchStreamSender interface. The BatchStreamSender interface has a sendInsertEvents method that the component invokes to send a batch of events of type insert downstream to a BatchStreamSink. For more information, see Section 9.1.6, "Batch Processing Channels".

com.bea.wlevs.ede.api.RelationSource

The RelationSource interface has one method, setEventSender; at runtime the event source component is injected with a com.bea.wlevs.ede.api.RelationSender instance.

The RelationSender instance, in turn, has sendUpdateEvent and sendDeleteEvent methods that the component invokes to actually send events to the next component in the EPN.

When you configure a channel as a relation, the channel attribute primary-key determines event identity. For more information, see Section 9.1.2.2, "Channels as Relations".

For sendDeleteEvent, you must send an instance of the same event type as that configured for the channel.

For sendInsertEvent, a unique constraint violation exception will be raised and the input event discarded if an event with the same primary key is already in the relation.

For sendUpdateEvent, an invalid update tuple exception will be raised and the input event discarded if an event with the given primary key is not in the relation.

If you enable batching on a channel you configure as a relation, then components that send events to that channel must implement the com.bea.wlevs.ede.api.BatchRelationSender interface. The BatchRelationSender interface has a sendEvents method that the component invokes to send a batch of events of type insert, update, and delete downstream to a BatchRelationSink. For more information, see Section 9.1.6, "Batch Processing Channels".

1.1.3.3 Stream and Relation Sinks

All components that consume events must implement one of the following interfaces:

com.bea.wlevs.ede.api.StreamSink

The StreamSink interface has a single callback method, onInsertEvent, that components implement to receive a list of events from the previous component in the EPN.

If you enable batching on a channel, then components that receive events from that channel must implement the com.bea.wlevs.ede.api.BatchStreamSink interface. The BatchStreamSink interface has an onInsertEvents call-back method for receiving a batch of events of type insert. Events of type insert are used to model streams, as streams are append-only. In the case of single event, call-back method of StreamSink will be invoked. For more information, see Section 9.1.6, "Batch Processing Channels".

com.bea.wlevs.ede.api.RelationSink

The RelationSink interface extends StreamSink to model an Oracle CQL relation sink. The RelationSink interface also provides an onDeleteEvent and onUpdateEvent methods.

If you enable batching on a channel you configure as a relation, then components that receive events from that channel must implement the com.bea.wlevs.ede.api.BatchRelationSink interface. The BatchRelationSink interface has an onEvents call-back method for receiving a batch of events for each event type of insert, update, and delete. If there is no event of a particular kind, then the corresponding Collection will be an empty Collection. For more information, see Section 9.1.6, "Batch Processing Channels".

1.1.3.4 Transmitting Events in the EPN: Examples

The following example is based on the HelloWorld example that Figure 1-1 shows. It is modified here to illustrate:

Figure 1-1 The HelloWorld Example Event Processing Network

Description of Figure 1-1 follows
Description of "Figure 1-1 The HelloWorld Example Event Processing Network"

For more information, see:

Creating the HelloWorldEvent as a Tuple Event

First, create the tuple event in the EPN assembly file:

<wlevs:event-type-repository>
    <wlevs:event-type type-name="HelloWorldEvent">
        <wlevs:properties>
            <wlevs:property name="message" type="char" length="1000"/>
        </wlevs:properties>
    </wlevs:event-type>
</wlevs:event-type-repository>

Sending Events from the HelloWorldAdapter as a StreamSource

Modify the HelloWorldAdapter to inject an EventTypeRepository instance at runtime by adding a setEventTypeRepository method using the @Service annotation:

@Service
public void setEventTypeRepository(EventTypeRepository etr) {
    etr_ = etr;
}

Modify the HelloWorldAdapter's generateHelloMessage method to use the EventTypeRepository instance to instantiate a HelloWorldEvent, then configure the event's properties, and send the event to the helloWorldInputChannel using the StreamSender instance that Oracle CEP server injected at runtime:

private void generateHelloMessage() {
    String message = this.message + dateFormat.format(new Date());

    EventType type = etr_.getEventType("HelloWorldEvent");
    EventProperty messageProp = type.getProperty("message");
    Object event = type.createEvent();

    messageProp.setValue(event, message);

    eventSender.sendInsertEvent(event);
}

Receiving Events in the HelloWorldBean as a StreamSink

Modify the HelloWorldBean to inject an EventTypeRepository instance at runtime using the @Service annotation:

@Service
public void setEventTypeRepository(EventTypeRepository etr) {
    etr_ = etr;
}

Modify the HelloWorldBean's onInsertEvent method use the EventTypeRepository instance to get the type of the received insert event and get the event's property.

public void onInsertEvent(Object event) {
    EventType eventType = etr_.getEventType(event);
    String prop = (String)eventType.getPropertyValue(event, "message");

    System.out.println("Tuple Message: " + prop);
}

Sending Events from the HelloWorldBean as a StreamSource

Imagine that the HelloWorldBean is connected to another component and you want to send events from the HelloWorldBean to this downstream component.

First, modify the HelloWorldBean class to implement the StreamSource interface and add the required setEventSender method:

public class HelloWorldBean implements StreamSource, StreamSink {
 
    private StreamSender streamSender_;

    public void setEventSender(StreamSender sender) {
        streamSender_ = sender;
    }
...
}

Modify the HelloWorldBean to inject an EventTypeRepository instance at runtime by adding a setEventTypeRepository method using the @Service annotation:

@Service
public void setEventTypeRepository(EventTypeRepository etr) {
    etr_ = etr;
}

Modify the HelloWorldBean to use the EventTypeRepository instance to instantiate a HelloWorldEvent, then configure the event's properties, and send the event to the downstream component using the StreamSender instance that Oracle CEP server injected at runtime:

private void generateHelloMessage() {
    String message = this.message + dateFormat.format(new Date());

    EventType type = etr_.getEventType("HelloWorldEvent");
    EventProperty messageProp = type.getProperty("message");
    Object event = type.createEvent();

    messageProp.setValue(event, message);

    eventSender.sendInsertEvent(event);
}

1.1.4 EPN Assembly File

You assemble an Oracle CEP application and an Event Processing Network (EPN) assembly file before deploying it to the server; this EPN assembly file is an extension of the Spring framework XML configuration file.

The spring-wlevs-v11_1_1_3.xsd schema file describes the structure of EPN assembly files.

The structure of EPN assembly files is as follows. There is a top-level root element named beans that contains a sequence of sub-elements. Each individual sub-element contains the configuration data for an Oracle CEP component. For example:

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:osgi="http://www.springframework.org/schema/osgi"
       xmlns:wlevs="http://www.bea.com/ns/wlevs/spring"
       xsi:schemaLocation="
            http://www.springframework.org/schema/beans
            http://www.springframework.org/schema/beans/spring-beans.xsd
            http://www.springframework.org/schema/osgi
            http://www.springframework.org/schema/osgi/spring-osgi.xsd
            http://www.bea.com/ns/wlevs/spring
            http://www.bea.com/ns/wlevs/spring/spring-wlevs-v11_1_1_3.xsd">

    <wlevs:event-type-repository>
        <wlevs:event-type type-name="HelloWorldEvent">
            <wlevs:class>com.bea.wlevs.event.example.helloworld.HelloWorldEvent</wlevs:class>
        </wlevs:event-type>
    </wlevs:event-type-repository>

    <wlevs:adapter id="helloworldAdapter" 
                   class="com.bea.wlevs.adapter.example.helloworld.HelloWorldAdapter" >
        <wlevs:instance-property name="message" value="HelloWorld - the current time is:"/>
    </wlevs:adapter>

    <wlevs:channel id="helloworldInputChannel" event-type="HelloWorldEvent" >
        <wlevs:listener ref="helloworldProcessor"/>
        <wlevs:source ref="helloworldAdapter"/>
    </wlevs:channel>

    <wlevs:processor id="helloworldProcessor" />

    <wlevs:channel id="helloworldOutputChannel" 
                   event-type="HelloWorldEvent" advertise="true">
        <wlevs:listener>
            <bean class="com.bea.wlevs.example.helloworld.HelloWorldBean"/>
        </wlevs:listener>
        <wlevs:source ref="helloworldProcessor"/>
    </wlevs:channel>

</beans>

For some Oracle CEP features, you specify some configuration in the EPN assembly file and some in the component configuration file.

For more information, see:

1.1.5 Component Configuration Files

Each component in your event processing network (adapter, processor, channel, or event bean) can have an associated configuration file, although only processors are required to have a configuration file. The caching system also uses a configuration file, regardless of whether it is a stage in the event processing network. Component configuration files in Oracle CEP are XML documents whose structure is defined using standard XML Schema. You create a single file that contains configuration for all components in your application, or you can create separate files for each component; the choice depends on which is easier for you to manage.

The wlevs_application_config.xsd schema file describes the structure of component configuration files. This XSD schema imports the following schemas:

  • wlevs_base_config.xsd: Defines common elements that are shared between application configuration files and the server configuration file

  • wlevs_eventstore_config.xsd: Defines event store-specific elements.

  • wlevs_diagnostic_config.xsd: Defines diagnostic elements.

The structure of application configuration files is as follows. There is a top-level root element named config that contains a sequence of sub-elements. Each individual sub-element contains the configuration data for an Oracle CEP component (processor, channel, or adapter). For example:

<?xml version="1.0" encoding="UTF-8"?>
<n1:config xmlns:n1="http://www.bea.com/ns/wlevs/config/application"
           xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
    <processor>
        <name>helloworldProcessor</name>
        <rules>
            <query id="helloworldRule">
                <![CDATA[ select * from helloworldInputChannel [Now] ]]>
            </query>
        </rules>
    </processor>
    <channel>
        <name>helloworldInputChannel</name>
        <max-size>10000</max-size>
        <max-threads>2</max-threads>
    </channel>
    <channel>
        <name>helloworldOutputChannel</name>
        <max-size>10000</max-size>
        <max-threads>2</max-threads>
    </channel>
</n1:config>

For more information, see:

1.1.5.1 Accessing Component and Server Configuration Using the ConfigurationPropertyPlaceholderConfigurer Class

Using the ConfigurationPropertyPlaceholderConfigurer class, you can reference existing configuration file properties, in both component configuration and server configuration files, using a symbolic placeholder. This allows you to define a value in one place and refer to that one definition rather than hard-coding the same value in many places.

For example, given the element that Example 1-5 shows, you can refer to the netio element port value as Example 1-6 shows.

Example 1-5 netio Element

<netio>
    <name>MyNetIO</name>
    <port>9003</port>
</netio>

Example 1-6 Accessing the netio Element port Value

<property name="myprop" value="${MyNetIO.port}"/>

To use this feature, insert a ConfigurationPropertyPlaceholderConfigurer bean in the application context configuration file of your application bundle as Example 1-7 shows.

Example 1-7 Adding a ConfigurationPropertyPlaceholderConfigurer

 <bean class="com.bea.wlevs.spring.support.ConfigurationPropertyPlaceholderConfigurer"/>

For complete details, see the com.bea.wlevs.spring.support.ConfigurationPropertyPlaceholderConfigurer class in the Oracle Fusion Middleware Java API Reference for Oracle Complex Event Processing.

For more information on accessing property files, see Section 4.7.3, "How to Add a Property File to an Oracle CEP Project".

1.1.6 How Components Fit Together

Oracle CEP applications are made of services that are assembled together to form an Event Processing Network (EPN).

The server uses the Spring framework as its assembly mechanism due to Spring's popularity and simplicity. Oracle CEP has extended the Spring framework to further simplify the process of assembling applications. This approach allows Oracle CEP applications to be easily integrated with existing Spring-beans, and other light-weight programming frameworks that are based upon a dependency injection mechanism.

A common approach for dependency injection is the usage of XML configuration files to declaratively specify the dependencies and assembly of an application. You assemble an Oracle CEP application an EPN assembly file before deploying it to the server; this EPN assembly file is an extension of the Spring framework XML configuration file.

After an application is assembled, it must be package so that it can be deployed into Oracle CEP. This is a simple process. The deployment unit of an application is a plain JAR file, which must contain, at a minimum, the following artifacts:

  • The compiled application Java code of the business logic POJO.

  • Component configuration files. Each processor is required to have a configuration file, although adapters and streams do not need to have a configuration file if the default configuration is adequate and you do not plan to monitor these components.

  • The EPN assembly file.

  • A MANIFEST.MF file with some additional OSGi entries.

After you assemble the artifacts into a JAR file, you deploy this bundle to Oracle CEP so it can immediately start receiving incoming data.

For more information, see Chapter 24, "Assembling and Deploying Oracle CEP Applications".

1.1.7 Extending the EPN

In addition to the components that Oracle CEP provides, you can extend the EPN by creating custom adapters, event beans, and Spring beans.

You can also extend the EPN using the Oracle Java data cartridge and Oracle Spatial to incorporate Java and Oracle Spatial operations in your Oracle CQL queries.

You can also expose Oracle CEP applications as Web services and consume Web services in your Oracle CEP application.

For more information, see Part IV, "Extending the Oracle CEP Event Processing Network"

1.1.8 High Availability and Scalability

When designing an Oracle CEP application, it is a best practice to consider high availability and scalability early in the design process.

Oracle CEP provides a range of high availability options that allow you to declaratively configure the quality of service your application requires for recovering from server failures.

Oracle CEP also provides a variety of features that allow you to scale your application to accommodate increasing event rates.

For more information, see:

1.1.9 Oracle CEP Application Lifecycle

Figure 1-2 shows a state diagram for the Oracle CEP application lifecycle. In this diagram, the state names (STARTING, INITIALIZING, RUNNING, SUSPENDING, SUSPENDED, and FAILED) correspond to the ApplicationRuntimeMBean method getState return values. These states are specific to Oracle CEP; they are not OSGi bundle states.

Figure 1-2 Oracle CEP Application Lifecycle State Diagram

Description of Figure 1-2 follows
Description of "Figure 1-2 Oracle CEP Application Lifecycle State Diagram"

Note:

For information on Oracle CEP server lifecycle, see "Oracle CEP Server Lifecycle" in the Oracle Complex Event Processing Administrator's Guide.

This section describes the lifecycle of an application deployed to the Oracle CEP server and the sequence of com.bea.wlevs.ede.api API callbacks. The lifecycle description is broken down into actions that a user performs, including:

This information explains how Oracle CEP manages an application's lifecycle so that you can better use the lifecycle APIs in your application.

For a description of these lifecycle APIs (such as RunnableBean and SuspendableBean), see:

1.1.9.1 User Action: Installing an Application or Start the Server With Application Already Deployed

Oracle CEP performs the following actions:

  1. Oracle CEP installs the application as an OSGI bundle. OSGI resolves the imports and exports, and publishes the service.

  2. Oracle CEP creates beans (for both standard Spring beans and those that correspond to the Oracle CEP tags in the EPN assembly file). For each bean, Oracle CEP:

    • Sets the properties on the Spring beans. The <wlevs:instance-property> values are set on adapters and event-beans.

    • Injects appropriate dependencies into services specified by @Service or @ServiceReference annotations.

    • Injects appropriate dependencies into static configuration properties.

    • Calls the InitializingBean.afterPropertiesSet method.

    • Calls configuration callbacks (@Prepare,@Activate) on Spring beans as well as factory-created stages.

      For more information, see Section 1.4, "Configuring Oracle CEP Resource Access".

  3. Application state is now INITIALIZING.

  4. Oracle CEP registers the MBeans.

  5. Oracle CEP calls the ActivatableBean.afterConfigurationActive method on all ActivatableBeans.

  6. Oracle CEP calls the ResumableBean.beforeResume method on all ResumableBeans.

  7. For each bean that implements RunnableBean, Oracle CEP starts it running in a thread.

  8. Application state is now RUNNING.

1.1.9.2 User Action: Suspend Application

Oracle CEP performs the following actions:

  1. Oracle CEP calls the SuspendableBean.suspend method on all SuspendableBeans.

  2. Application state is now SUSPENDED.

1.1.9.3 User Action: Resume Application

Oracle CEP performs the following actions:

  1. Oracle CEP calls the ResumableBean.beforeResume method on all ResumableBeans

  2. For each bean that implements RunnableBean, Oracle CEP starts it running in a thread.

  3. Application state is now RUNNING.

1.1.9.4 User Action: Uninstall Application

Oracle CEP performs the following actions:

  1. Oracle CEP calls the SuspendableBean.suspend method on all SuspendableBeans.

  2. Oracle CEP unregisters MBeans.

  3. Oracle CEP calls the DisposableBean.dispose method on all DisposableBeans.

  4. Oracle CEP uninstalls application bundle from OSGI.

1.1.9.5 User Action: Update Application

This is equivalent to first unistalling an application and then installing it again.

See:

1.1.9.6 User Action: Calling Methods of Stream and Relation Sources and Sinks

You may not call a method on a stream or relation source or sink from a lifecycle callback because components may not be ready to receive events until after these phases of the application lifecycle complete.

For example, you may not call StreamSender method sendInsertEvent from a lifecycle callback such as such as afterConfigurationActive or beforeResume.

You can call a method on a stream or relation source or sink from the run method of beans that implement RunnableBean.

For more information, see:

1.1.10 Oracle CEP APIs

Oracle CEP provides a variety of Java APIs that you use in your adapter or event bean implementation.

This section describes the APIs in the com.bea.wlevs.ede.api package that you will most typically use in your adapters and event beans.

  • Adapter—Adapters must implement this interface.

  • AdapterFactory—Adapter factories must implement this interface.

  • Component life cycle interfaces—If you want some control over the life cycle of the component you are programming, then your component should implement one or more of the following interfaces:

    • ActivatableBean—Use if you want to run some code after all dynamic configuration has been set and the event processing network has been activated. Implement the afterConfigurationActive method.

    • DisposableBean—Use if you want to release resources when the application is undeployed. Implement the destroy method in your component code.

    • InitializingBean—Use if you require custom initialization after Oracle CEP has set all the properties of the component. Implement the afterPropertiesSet method.

    • ResumableBean—Use if you want to perform some task, such as acquire or configure resources, before the component resumes work.

    • RunnableBean—Use if you want the component to be run in a thread.

      The Spring framework implements similar bean life cycle interfaces; however, the equivalent Spring interfaces do not allow you to manipulate beans that were created by factories, while the Oracle CEP interfaces do.

    • SuspendableBean—Use if you want to suspend resources or stop processing events when the event processing network is suspended. Implement the suspend method.

    See also Appendix I, "Oracle CEP Metadata Annotation Reference" for additional lifecycle annotations.

  • EventBuilder—Use to create events whose Java representation does not expose the necessary setter and getter methods for its properties. If your event type is represented with a JavaBean with all required getter and setter methods, then you do not need to create an EventBuilder.

  • EventBuilder.Factory—Factory for creating EventBuilders.

  • StreamSink—Components that want to receive events as an Oracle CEP stream must implement this interface. An Oracle CEP stream has the following characteristics:

    • Append-only, that is, events are always appended to the end of the stream.

    • Unbounded and generally need a window to be defined before it can be processed.

    • Events have non-decreasing time-stamps.

    The interface has a callback method, onInsertEvent, in which programmers put the code that handles the received events.

  • StreamSource—Components that send events modeling an Oracle CEP stream, such as adapters, must implement this interface. The interface has a setEventSender method for setting the StreamSender, which actually sends the event to the next component in the network.

  • RelationSink—Components that want to receive events modeling an Oracle CEP relation must implement this interface. An Oracle CEP relation has the following characteristics:

    • Supports events that insert, delete, and update its content.

    • Is always known at an instant time.

    • Events have non-decreasing time-stamps.

    The interface has callback methods onDeleteEvent and onInsertEvent in which programmers put the code that handles event deletion and event insertion.

  • RelationSource—Components that send events modeling an Oracle CEP relation, such as adapters, must implement this interface. The interface has a setEventSender method for setting the RelationSender, which actually sends the event to the next component in the network.

For more information, see:

1.2 Oracle CEP IDE for Eclipse

Oracle provides an IDE targeted specifically to programmers that want to develop Oracle CEP applications. Oracle CEP IDE for Eclipse is a set of plugins for the Eclipse IDE designed to help develop, deploy, and debug applications for Oracle CEP.

The key features of the Oracle CEP IDE for Eclipse are as follows:

  • Project creation wizards and templates to quickly get started building event driven applications.

  • Advanced editors for source files including Java and XML files common to Oracle CEP applications.

  • Integrated server management to seamlessly start, stop, and deploy to Oracle CEP server instances all from within the IDE.

  • Integrated debugging.

  • Event Processing Network (EPN) visual design views for orienting and navigating in event processing applications.

  • Integrated support for the Oracle CEP Visualizer so you can use the Oracle CEP Visualizer from within the IDE.

Although it is not required or assumed that you are using the Oracle CEP IDE, Oracle recommends that you give it a try.

For detailed instructions on installing and using the IDE, see Chapter 3, "Overview of the Oracle CEP IDE for Eclipse".

1.3 Creating an Oracle CEP Application

The following procedure shows the suggested start-to-finish steps to create an Oracle CEP application. Although it is not required to program and configure the various components in the order shown, the procedure shows a typical and logical flow recommended by Oracle.

It is assumed in the procedure that you are using an IDE, although it is not required and the one you use is your choice. For one targeted to Oracle CEP developers, see Section 1.2, "Oracle CEP IDE for Eclipse."

To create an Oracle CEP application:

  1. Set up your environment as described in "Setting Your Development Environment" in the Oracle Complex Event Processing Getting Started.

  2. Create an Oracle CEP project using the Oracle CEP IDE for Eclipse.

    For more information, see Chapter 4, "Oracle CEP IDE for Eclipse Projects".

  3. Design your event processing network (EPN).

    Using the Oracle CEP IDE for Eclipse and the EPN editor, add the full list of components that make up the application and how they are connected to each other, as well as registering the event types used in your application.

    This step combines both designing of your application, in particular determining the components that you need to configure and code, as well as creating the actual XML file that specifies all the components (the EPN assembly file) and the XML file that specifies component configuration (the component configuration file). You will likely be constantly updating these XML files as you implement your application, but Oracle recommends you start with this step so you have a high-level view of your application.

    For more information, see:

  4. Determine the event types that your application is going to use, and, if creating your own JavaBean, program the Java file.

    See Chapter 2, "Creating Oracle CEP Event Types"

  5. Program, and optionally configure, the adapters or event beans that act as inbound, intermediate, or outbound components of your event processing network. You can create your own adapters or event beans, or use the adapters provided by Oracle CEP. For details, see:

  6. Configure the processors by creating their component configuration XML files; the most important part of this step is designing and declaring the initial rules that are associated with each processor.

    See:

  7. Design the rules that the processors are going to use to select events from their upstream channels and output events to their downstream channels.

    See:

    Note:

    Oracle CQL replaces Event Processing Language (EPL) in Oracle CEP 11g Release 1 (11.1.1). Oracle CEP supports EPL for backwards compatibility.
  8. Optionally configure the channels that stream data between adapters, processors, and the business logic POJO by creating their configuration XML files.

    See Chapter 9, "Configuring Channels."

  9. Optionally configure the caching system to publish or consume events to and from a cache to increase the availability of the events and increase the performance of your applications.

    See Chapter 12, "Configuring Caching."

  10. Optionally, use the Oracle CEP server log subsystem to write log messages from your application to the Oracle CEP server log:

    import org.apache.commons.logging.Log;
    import org.apache.commons.logging.LogFactory;
    ...
    Log LOG=LogFactory.getLog("LogName");
    ...
    LOG.debug("Some debug information");
    ...
    

    Using the Oracle CEP Visualizer, you can deploy your application, configure the log level for your application, and view the Oracle CEP server console.

    For more information, see:

See Section 1.5, "Next Steps" for the list of steps you should follow after you have completed programming your application, such as packaging and deploying.

1.4 Configuring Oracle CEP Resource Access

By using Oracle CEP and standard Java annotations and deployment XML, you can configure the Oracle CEP Spring container to inject resources (such as data sources or persistence managers, and so on) into your Oracle CEP application components.

The Spring container typically injects resources during component initialization. However, it can also inject and re-inject resources at runtime and supports the use of JNDI lookups at runtime.

Oracle CEP supports the following types of resource access:

See Section 1.4.4, "Understanding Resource Name Resolution" for information on resource name resolution.

See Appendix I, "Oracle CEP Metadata Annotation Reference" for complete details of all Oracle CEP annotations.

In the following sections, consider the example resource that Example 1-8 shows. This is a data source resource named StockDS that you specifiy in the Oracle CEP server config.xml file.

Example 1-8 Sample Resource: Data Source StockDS

<config ...>
    <data-source>
        <name>StockDs</name>
        ...
        <driver-params>
            <url>jdbc:derby:</url>
            ...
        <driver-params>
    </data-source>
...
</config>

1.4.1 Static Resource Injection

Static resource injection refers to the injection of resources during the initialization phase of the component lifecycle. Once injected, resources are fixed, or static, while the component is active or running.

You can configure static resource injection using:

1.4.1.1 Static Resource Names

When you configure static resource injection using static resource names, the resource name you use in the @Resource annotation or Oracle CEP assembly XML file must exactly match the name of the resource as you defined it. The resource name is static in the sense that you cannot change it without recompiling.

To configure static resource injection using static resource names at design time, you use the standard javax.annotation.Resource annotation as Example 1-9 shows.

To override design time configuration at deploy time, you use Oracle CEP assembly file XML as Example 1-10 shows.

In Example 1-9 and Example 1-10, the resource name StockDs exactly matches the name of the data source in the Oracle CEP server config.xml file as Example 1-8 shows.

Example 1-9 Static Resource Injection Using Static Resource Names: Annotations

import javax.annotation.Resource;

public class SimpleBean implements EventBean {
...
    @Resource (name="StockDs")
    public void setDataSource (DataSource dataSource){
        this.dataSource = dataSource;
    }
}

Example 1-10 Static Resource Injection Using Static Resource Names: XML

< wlevs:event-bean id="simpleBean" class="...SimpleBean"/>
    <wlevs:resource property="dataSource" name="StockDs"/>
</wlevs:event-bean>

If the name of the EventBean set method matches the name of the resource, then the @Resource annotation name attribute is not needed as Example 1-11 shows. Similarly, in this case, the wlevs:resource element name attribute is not needed as Example 1-12.

Example 1-11 Static Resource Injection Using Static Resource Names: Annotations

import javax.annotation.Resource;

public class SimpleBean implements EventBean {
...
    @Resource ()
    public void setStockDs (DataSource dataSource){
        this.dataSource = dataSource;
    }
}

Example 1-12 Static Resource Injection Using Static Resource Names: XML

< wlevs:event-bean id="simpleBean" class="...SimpleBean"/>
    <wlevs:resource property="dataSource"/>
</wlevs:event-bean>

1.4.1.2 Dynamic Resource Names

A dynamic resource name is one that is specified as part of the dynamic or external configuration of an application. Using a dynamic resource name, the deployer or administrator can change the resource name without requiring that the application developer modify the application code or the Spring application context.

To add a dynamic resource name to a component, such as an adapter or POJO, you must first specify custom configuration for your component that contains the resource name as Example 1-13 shows.

Example 1-13 Custom Component Configuration

<simple-bean>
    <name>SimpleBean</name>
    <trade-datasource>StockDs</trade-datasource>
</simple-bean>

To configure static resource injection using dynamic resource names at design time, you use the standard javax.annotation.Resource annotation as Example 1-14 shows.

To override design time configuration at deploy time, you use Oracle CEP assembly file XML as Example 1-15 shows.

Example 1-14 Static Resource Injection Using Dynamic Resource Names: Annotations

import javax.annotation.Resource;

public class SimpleBean implements EventBean {
...
    @Resource (name="trade-datasource")
    public void setDataSource (DataSource dataSource){
        this.dataSource = dataSource;
    }
}

Example 1-15 Static Resource Injection Using Dynamic Resource Names: XML

< wlevs:event-bean id="simpleBean" class="...SimpleBean"/>
    <wlevs:resource property="dataSource" name="trade-datasource"/>
</wlevs:event-bean>

1.4.2 Dynamic Resource Injection

Dynamic resource injection refers to the injection of resources dynamically while the component is active in response to a dynamic configuration change using Spring container method injection.

To configure dynamic resource injection at design time, you use the standard javax.annotation.Resource annotation as Example 1-16 shows.

Example 1-16 Dynamic Resource Injection: Annotations

import javax.annotations.Resource;

public class SimpleBean implements EventBean {
...
    @Resource ("trade-datasource")
    public abstract DataSource getDataSource ();
    ...
    }

The component calls the getDataSource method at run time whenever it needs to retrieve a new instance of the resource that the resource name trade-datasource refers to.

Typically, the component calls the getDataSource method during the @Prepare or @Activate methods when dynamic configuration changes are handled. For more information see:

Another strategy is to always call the getDataSource prior to using the data source. That is, the application code does not store a reference to the data source as a field in the component.

1.4.3 Dynamic Resource Lookup Using JNDI

Oracle CEP supports the use of JNDI to look up resources dynamically as Example 1-17.

Example 1-17 Dynamic Resource Lookup Using JNDI

import javax.naming.InitialContext;

public class SimpleBean implements EventBean {
...
    public abstract void getDataSource () throws Exception {
        InitialContext initialContext= new InitialContext ();
        return initialContext.lookup ("StockDs”);
    }
}

In Example 1-17, the JNDI name StockDs must exactly match the name of the data source in the Oracle CEP server config.xml file as Example 1-8 shows.

Note:

You must disable security when starting the Oracle CEP server in order to use JNDI. Oracle does not recommend the use of JNDI for this reason.

For more information, see "Configuring Security for Oracle CEP" in the Oracle Complex Event Processing Administrator's Guide.

1.4.4 Understanding Resource Name Resolution

Oracle CEP server resolves resource names by examining the naming scopes that Table 1-1 lists.

Table 1-1 Resource Name Resolution

Naming Scope Contents Resolution Behavior

Component

The property names of the component's custom configuration

Mapping

Application

The names of the configuration elements in the application configuration files

Matching

Server

The names of the configuration elements in the server configuration file

Matching

JNDI

The names registered in the server's JNDI registry

Matching


Each naming scope contains a set of unique names. The name resolution behavior is specific to a naming scope. Some naming scopes resolve names by simple matching. Other scopes resolve names by mapping the name used to do the lookup into a new name. Once a name is mapped, lookup proceeds recursively beginning with the current scope.

1.5 Next Steps

After you have programmed all components of your application and created their configuration XML files: