An event type is a data structure that defines the data contained in an event. When raw event data comes into the Oracle Stream Analytics application, the application binds that data to an event of a particular event type. In your application, you define the event type in terms of its data set and the corresponding data types.
This chapter includes the following sections:
An event is structured data that relates to something that happens or is happening. For example, if your application reacts to changes to a cluster of servers, events capture snapshot data that is collected by the device that monitors the servers.
Or if your application monitors trends and patterns related to stock market trades, events contain event data that corresponds to stock trades.
Event data can arrive at an application in many forms. By creating an event type to represent the data inside the application, you create a predictable way for application logic to work with the data.
Events carry event data through the event processing network (EPN). When you design the event type, keep in mind how you plan to access, process, and manipulate the event data in your code.
An event type can get its structure from a JavaBean
class, a tuple, or a java.util.Map
class. Oracle recommends that you use JavaBean
classes to structure event types. JavaBeans provide greater flexibility within your application and simplify integration with existing systems.
JavaBean event types are flexible. For example, you assign a JavaBean event type to a property of a tuple or java.util.Map
event type. The following code shows the event type Student
that defines its address
property as the JavaBean event type Address
.
<wlevs:event-type-repository> <wlevs:event-type type-name="Student"> <wlevs:properties> <wlevs:property name="name" type="char"/> <wlevs:property name="address" type="classpackage.Address"/> </wlevs:properties> </wlevs:event-type> </wlevs:event-type-repository>
JavaBeans also enable you to closely control event type instantiation by implementing an event type builder class. For more information on event type builder classes, see Control Event Type Instantiation with an Event Type Builder Class.
Table 3-1 compares JavaBean classes, tuples, and java.util.Map
classes.
Table 3-1 Data Types for Event Types
Data Type | Description | Benefits and Limitations |
---|---|---|
JavaBean |
A Java class written to JavaBean conventions. In addition to being used by logic you write, the type's accessor (get and set) methods will be used by the Oracle Stream Analytics server and Oracle CQL processor to retrieve and set event property values. |
Benefits: This type is the best practice because it provides the greatest flexibility and ease of use for application logic that handles events. You access property values directly through accessor methods. A JavaBean class is more likely to be useful when integrating your Oracle Stream Analytics application with other systems. For control over how the type is instantiated, you can implement an event type builder class. Limitations: Requires writing a JavaBean class, rather than simply declaring the event type in a configuration file. Oracle CQL does not support JavaBean properties in GROUP BY, PARTITION BY, and ORDER BY, although you can work around this by using an Oracle CQL view. |
Tuple |
A structure that you create and register declaratively in the EPN assembly file. For more information, see Create and Register a Tuple Event Type. |
Benefits: Requires no Java programming to create the event type. An event type is created by declaring it in the EPN assembly file. Useful for quick prototyping. Limitations: Using instances of this type in Java application logic requires programmatically accessing the event type repository to get the instance's property values. A tuple is also unlikely to be useful when integrating the Oracle Stream Analytics with other systems. |
|
Based on an instance of For more information, see Create and Register a Map Event Type. |
Benefits: Requires no Java programming to create the type. An event type is created by declaring it in the EPN assembly file. Useful for quick prototyping. Limitations: Does not perform as well as other types. |
Keep in mind the following CSV adapter and database table constraints when you design event types.
CSV Adapter Constraints
When you declaratively specify the properties of an event type for use with CSV adapters, you can only use the data types that Table 3-2 describes.
Table 3-2 CSV Adapter Types
Type | Usage |
---|---|
|
Single or multiple character values. Use for both Optionally, you may use the |
|
Numeric values in the range that |
|
Numeric values in the range that |
|
Numeric values in the range that |
|
Numeric values in the range that |
For more information, see:
Database Table Constraints
You can use a relational database table as a source of event data, binding data from the table to your event type instance at runtime. When your event data source is a database table, you must follow the guidelines represented by the following tables.
When an event type will receive data from a database table, a property configured for the type will each receive data from a particular column in the database. When configuring the event type, note that its property child elements have attributes that have particular meanings and value constraints, as described in Table 3-3.
Table 3-3 EPN Assembly File event-type Element Property Attributes
|
When you specify the properties of an event type for use with a relational database table, you must observe the additional JDBC type restrictions listed in Table 3-4.
When you join a stream with the Derby database, where the join condition compares two timestamp values - one value is from the stream attribute and the other value is from the Derby data source attribute, the Derby database performs the predicate evaluation. However, the Derby database supports only the yyyy-MM-dd-HH.mm.ss[.nnnnnn]
format. For the Derby database to perform the evaluation correctly, the stream timestamp value must use the Derby database format.
Table 3-4 SQL Column Types and Oracle Stream Analytics Type Equivalents
|
For more information, see: Configure a Table Source.
Oracle Stream Analytics manages event types in an event type repository. The Oracle Stream Analytics server accesses the assembly file at run time to retrieve the information it needs to manage the application.
The following example shows an event type entry in the repository:
<wlevs:event-type-repository> <wlevs:event-type type-name="TradeEvent"> <wlevs:class>tradereport.TradeEvent</wlevs:class> </wlevs:event-type> </wlevs:event-type-repository>
To define and edit event types, you can use the Oracle JDeveloper Event tab, work in the assembly file directly, or call APIs from your application code. The Event tab displays when you open the EPN diagram for an Oracle JDeveloper project.
For more information, see Access the Event Type Repository.
When you create an event type, you add the <wlevs:properties>
and <wlevs:property>
elements to the <wlevs:event-type>
element to define the event type properties.
Properties have name
and type
attributes that define the kind of information, such as ticker name, ticker symbol, and closing price, and the corresponding data type, such as String
, String
, and Double
. For more information about the <wlevs:event-type>
element, see wlevs:event-type in Schema Reference for Oracle Stream Analytics.
Assembly File
The following assembly file entries show a simple event type with one event type and one property defined by the <wlevs:class>
element. The properties for this event type are defined in a JavaBean class.
<wlevs:event-type-repository> <wlevs:event-type type-name="TradeEvent"> <wlevs:class>tradereport.TradeEvent</wlevs:class> </wlevs:event-type> </wlevs:event-type-repository>
The following assembly file entries show a message count event type with properties defined by the <wlevs:properties>
element, which encloses three <wlevs:property>
elements.
<wlevs:event-type-repository> <wlevs:event-type id="messagecounts" type-name="SimpleEvent"> <wlevs:properties> <wlevs:property name="msg" type="char" /> <wlevs:property name="count" type="long" /> <wlevs:property name="time_stamp" type="timestamp" /> </wlevs:properties> </wlevs:event-type> ... </wlevs:event-type-repository>
Event types also support the day-to-second and year-to-month interval properties and the time stamp with local time zone properties.
The following assembly file entries show the interval properties.
<wlevs:event-type-repository> <wlevs:event-type type-name="IntervalDataTypeEvent"> <wlevs:properties> <wlevs:property name="Comment" type="char" length="256" /> <wlevs:property name="intervalProp" type="interval day(1) to second(2)"/> <wlevs:property name="intervalymProp" type="interval year(2) to month"/> <wlevs:property name="intervaldhProp" type="interval day to hour"/> <wlevs:property name="intervaldmProp" type="interval day to minute"/> <wlevs:property name="intervalhsProp" type="interval hour(1) to second(2)"/> <wlevs:property name="intervalhmProp" type="interval hour to minute"/> <wlevs:property name="intervalmsProp" type="interval minute(2) to second(2)"/> <wlevs:property name="intervaldProp" type="interval day(1)"/> <wlevs:property name="intervalyProp" type="interval year(2)"/> <wlevs:property name="intervalmProp" type="interval month"/> </wlevs:properties> </wlevs:event-type> </wlevs:event-type-repository>
Day-to-second combinations:
INTERVAL DAY[(day_precision)] TO SECOND[(fractional_seconds_precision)]
day_precision
is the number of digits in the DAY
date-time field. Accepted values are 0 to 9. The default is 2.
fractional_seconds_precision
is the number of digits in the fractional part of the SECOND
date-time field. Accepted values are 0 to 9. The default value is 6.
Year-to-month combinations:
INTERVAL YEAR [(year_precision)] TO MONTH
year_precision
is the number of digits in the YEAR
date-time field. The default value for year_precision
is 2.
The following assembly file entries show the time stamp with local time zone properties.
<wlevs:event-type-repository> <wlevs:event-type type-name="IntervalDataTypeEvent"> <wlevs:properties> <wlevs:property name="Comment" type="char" length="256" /> <wlevs:property name="timestamptzProp" type="timestamp with time zone"/> <wlevs:property name="timestampltzProp" type="timestamp with local time zone"/> </wlevs:properties> </wlevs:event-type> </wlevs:event-type-repository>
With time zone:
TIMESTAMP [(fractional_seconds_precision)] WITH TIME ZONE
fractional_seconds_precision
optionally specifies the number of digits Oracle stores in the fractional part of the SECOND
datetime field. When you create a column of this data type, the value can be a number in the range 0 to 9. The default value is 6.
With local time zone:
TIMESTAMP [(fractional_seconds_precision)] WITH LOCAL TIME ZONE
fractional_seconds_precision
optionally specifies the number of digits Oracle stores in the fractional part of the SECOND
datetime field. When you create a column of this data type, the value can be a number in the range 0 to 9. The default value is 6.
First, identify the event data that the event type carries and then decide the properties the event type requires. This section walks you through the following steps. To make the JavaBean an event source or sink, see Event Beans .
You can use the following Java types for the properties:
The fully qualified name of a Java class. The name must conform to the Class.forName
rules and be available in the application class loader.
A Java primitive such as int
or float
.
An array by appending square brackets ([])
to the primitive or class name. For example, short[]
or java.lang.Integer[]
.
Steps 1 and 2 are the same as steps 1 and 2 in Create a JavaBean Event Type Declaratively. Then, for step 3, do the following.
To register a JavaBean event type programmatically, use the EventTypeRepository
class as shown:
EventTypeRepository rep = getEventTypeRepository(); rep.registerEventType("MarketEvent", com.bea.wlevs.example.algotrading.event.MarketEvent.getClass() );
For more information, see Access the Event Type Repository.
Once you create a JavBean even type, you can reference it in your application Java code. The following code references the MarketEvent
event type in the onInsertEvent
method implementation. The onInsertEvent
method is from an event sink class that receives events. For more information on event sinks, see Event Sink Interfaces.
public void onInsertEvent(Object event) throws EventRejectedException {
if (event instanceof MarketEvent){
MarketEvent marketEvent = (MarketEvent) event;
System.out.println("Price: " + marketEvent.getPrice());
}
}
The following Oracle CQL rule shows how to reference the MarketEvent
event type in a SELECT
statement. It assumes an upstream channel called marketEventChannel
with a MarketEvent
event type.
<query id="helloworldRule"> <![CDATA[ SELECT MarketEvent.price FROM marketEventChannel [NOW] > </query>
Also, with property data types implemented as JavaBeans, Oracle CQL code can get values within those properties by using standard JavaBean-style property access. For example, the following configuration snippet declares a StudentType
event type that is implemented as a JavaBean class. The school.Student
class is a JavaBean with an address
property that is an Address
JavaBean class. The following query suggests how you might access values of the Address
object underlying the address property. This query selects student addresses whose postal code begins with 97.
<query id="studentAddresses"> FOR StudentType SELECT student.address FROM StudentType as student WHERE student.address.postalCode LIKE '^97' </query>
EventRejectedException Behavior in onInsertEvent Implementations
You need to explicitly throw EventRejectedException
in onInsertEvent
implementations for exceptions you do not want to get dropped. You can raise an EventProcessingException
and it is propagated all the way to the source of the error through a CQL processor. An EventRejectedException can chain exceptions from its downstream listeners, in case there is more than one exception. The CQL processor converts the EventRejectedException
to a soft exception. See Fault Handling for more information.
First, identify the event data that the event type carries and then decide the properties the event type requires. When you design your event, you must restrict the properties to the data types described in Design Constraints.
With a tuple-based event type, your Java code must always set and get its property values with the EventTypeRepository
APIs.
Note:
The order in which the EPN processes tuples with the same time stamp is not guaranteed when the EPN is made up of multiple streams.
Data Types
When you specify the tuple event type properties declaratively in the application assembly file, you can use any of the native Oracle CQL data types in the property type.
The following XML shows the use of different types in the application assembly file.
<wlevs:event-type-repository> <wlevs:event-type type-name="SimpleEvent"> <wlevs:properties> <wlevs:property name="id" type="char" length="1000" /> <wlevs:property name="msg" type="char" /> <wlevs:property name="count" type="double" /> <wlevs:property name="time_stamp" type="timestamp" /> </wlevs:properties> </wlevs:event-type> ... </wlevs:event-type-repository>
Procedures
Register your event type declaratively in the Oracle Stream Analytics event type repository with the wlevs:event-type-repository
element and the wlevs:event-type
child element.
Create a Tuple Event Type in the Assembly File
The following XML stanzas create a the CrossRateEvent
tuple event type with the properties price
, fromRate
, and toRate
.
<wlevs:event-type-repository> <wlevs:event-type type-name="CrossRateEvent"> <wlevs:properties> <wlevs:property name="price" type="double"/> <wlevs:property name="fromRate" type="char"/> <wlevs:property name="toRate" type="char"/> </wlevs:properties> </wlevs:event-type> </wlevs:event-type-repository>
See wlevs:event-type-repository in Schema Reference for Oracle Stream Analytics.
Before you can use a tuple event type in Java code, you must create an event type repository. You use the event type repository to get the property names and values so you can work on them in your code. To create an event type repository, include the com.bea.wlevs.ede.api.EventTypeRepository
class.
The following code is part of an event sink class. The code creates an event type repository with a call to the setEventTypeRespository
method. The Oracle Stream Analytics server then calls the onInsertEvent
method with an event
parameter. The onInsertEvent
method gets information about the event
from the event type repository.
For more information about creating an EventTypeRepository
object, see Access the Event Type Repository.
@Service // Create an event type repository public void setEventTypeRepository(EventTypeRepository etr) { etr_ = etr; } ... // Called by the server to pass in the event type instance. public void onInsertEvent(Object event) throws EventRejectedException { // Get the event type for the current event instance EventType eventType = etr_.getEventType(event); // Get the event type name String eventTypeName = eventType.getTypeName(); // Get the event property names String[] propNames = eventType.getPropertyNames(); // See if property you're looking for is present if(eventType.isProperty("fromRate")) { // Get property value Object propValue = eventType.getProperty("fromRate").getValue(event); } // Throw com.bea.wlevs.ede.api.EventRejectedException to have an // exception propagated up to senders. Other errors will be // logged and dropped. }
The following Oracle CQL rule shows how to reference the CrossRateEvent
in a SELECT
statement. FxQuoteStream
is a channel with the CrossRateEvent
event type.
<query id="FindCrossRatesRule"><![CDATA[ select ((a.price * b.price) + 0.05) as internalPrice, a.fromRate as crossRate1, b.toRate as crossRate2 from FxQuoteStream [range 1] as a, FxQuoteStream [range 1] as b where NOT (a.price IS NULL) and NOT (b.price IS NULL) and a.toRate = b.fromRate ></query>
First, identify the event data that the event type carries and then decide the properties the event type requires. You create a java.util.map
event type by adding the configuration XML to the application assembly file.
An event type based on a hash map is called a map-based event type.
Data Types
You can use the following Java types for the properties:
The fully qualified name of a Java class. The name must conform to the Class.forName
rules and be available in the application class loader.
A Java primitive such as int
or float
.
An array by appending square brackets ([])
to the primitive or class name. For example, short[]
or java.lang.Integer[]
.
The following XML code shows examples of event property declarations in the event repository.
<wlevs:event-type-repository> <wlevs:event-type type-name="AnotherEvent"> <wlevs:properties type="map"> <wlevs:property> <entry key="name" value="java.lang.String"/> <entry key="employeeId" value="java.lang.Integer[]"/> <entry key="salary" value="float"/> <entry key="projectIds" value="short[]"/> </wlevs:property> <wlevs:properties> </wlevs:event-type> </wlevs:event-type-repository>
To create and register a java.util.Map event type:
First, identify the event data that the event type carries and then decide the properties the event type requires.
To register declaratively, edit the EPN assembly file using the wlevs:event-type-repository
element wlevs:event-type
child element as shown:
<wlevs:event-type-repository> <wlevs:event-type type-name="AnotherEvent"> <wlevs:properties type="map"> <wlevs:property name="name" value="java.lang.String"/> <wlevs:property name="age" value="java.lang.Integer"/> <wlevs:property name="address" value="java.lang.String"/> </wlevs:properties > </wlevs:event-type> </wlevs:event-type-repository>
At runtime, Oracle Stream Analytics generates a bean instance of the AnotherEvent
class for you. The AnotherEvent
class has three properties: name
, age
, and address
.
To register programmatically, use the EventTypeRepository
class as shown:
EventTypeRepository rep = getEventTypeRepository(); java.util.Map map = new Map({name, java.lang.String}, {age, java.lang.Integer}, {address, java.lang.String}); rep.registerEventType("AnotherEvent", map);
Usages
public void onInsertEvent(Object event)
throws EventRejectedException {
java.util.Map anEvent = (java.util.Map) event;
System.out.println("Age: " + anEvent.get("age"));
}
The following Oracle CQL rule shows how you can reference the MarketEvent
in a SELECT
statement:
<query id="helloworldRule"> <![CDATA[ select age from eventChannel [now] > </query>
The Oracle Stream Analytics event type repository keeps track of the event types defined for your application. When you create an event type in Oracle JDeveloper, it becomes available to the Oracle Stream Analytics application.
In some cases, you might need to write code that explicitly accesses the repository. For example, when your event type is created as a tuple, Java logic that accesses instance of the type will need to first retrieve the type definition using the repository API, then use the API to access the instance property values.
The EventTypeRepository
is a singleton OSGi service. Because it is a singleton, you only need to specify its interface name to identify it. You can get a service from OSGi in any of the following ways:
For more information, see Java API Reference for Oracle Stream Analytics.
You can access the EventTypeRepository
by specifying an osgi:reference
in the EPN assembly file.
<osgi:reference id="etr" interface="com.bea.wlevs.ede.api.EventTypeRepository" /> <bean id="outputBean" class="com.acme.MyBean" > <property name="eventTypeRepository" ref="etr" /> </bean>
Then, in the MyBean
class, you can access the EventTypeRepository
using the eventTypeRepository
property initialized by Spring.
package com.acme; import com.bea.wlevs.ede.api.EventTypeRepository; import com.bea.wlevs.ede.api.EventType; public class MyBean { private EventTypeRepository eventTypeRepository; public void setEventTypeRepository(EventTypeRepository eventTypeRepository) { this.eventTypeRepository = eventTypeRepository; } public void onInsertEvent(Object event) throws EventRejectedException { // get the event type for the current event instance EventType eventType = eventTypeRepository.getEventType(event);
// Throw com.bea.wlevs.ede.api.EventRejectedException to have an // exception propagated up to senders. Other errors will be // logged and dropped.
} }
You can access the EventTypeRepository
by using the Spring-DM @ServiceReference
annotation to initialize a property in your Java source.
import org.springframework.osgi.extensions.annotation.ServiceReference; import com.bea.wlevs.ede.api.EventTypeRepository; ... @ServiceReference setEventTypeRepository(EventTypeRepository etr) { ... }
You can access the EventTypeRepository
with the Oracle Stream Analytics @Service
annotation to initialize a property in your Java source.
import com.bea.wlevs.util.Service; import com.bea.wlevs.ede.api.EventTypeRepository; ... @Service setEventTypeRepository(EventTypeRepository etr) { ... }
Each Oracle Stream Analytics application gets its own Java classloader and loads application classes using that class loader. This means that, by default, one application cannot access the classes in another application.
However, because the event type repository is a singleton service, you can configure the repository in one bundle and then explicitly export the event type classes so that applications in separate bundles (deployed to the same Oracle Stream Analytics server) can use these shared event types.
The event type names in this case are scoped to the entire Oracle Stream Analytics server instance. This means that you will get an exception if you try to create an event type that has the same name as an event type that has been shared from another bundle, but the event type classes are different.
To share event type classes, add their package name to the Export-Package
header of the MANIFEST.MF
file of the bundle that contains the event type repository you want to share.
Be sure you deploy the bundle that contains the event type repository before all bundles that contain applications that use the shared event types, or you will get a deployment exception.
For more information, see:
You can create an event type builder to have more control over how event type instances are created. For example, using an event type builder you can ensure that the properties of a configured event are correctly bound to the properties of an event type class, such as one you have implemented as a JavaBean.
You would need an event type builder in a case, for example, where event property names assumed in CQL code are different from the names of properties declared in the class.
For example, assume the event type has a firstname
property, but the CQL rule that executes on the event type assumes the property is called fname
. Assume also that you cannot change either the event type class (because you are using a shared event class from another bundle, for example) or the CQL rule to make them compatible with each other. In this case you can use an event type builder factory to change the way the event type instance is created so that the property is named fname
rather than firstname
.
At runtime, an event type builder class receives property values from the Oracle Event Processing server and uses those values to create an instance of the event type class you created. Your event type builder then returns the instance to the server. In this way, your builder class is in effect an intermediary, instantiating event types in cases where the server is unable to determine how to map configured properties to event type properties.
Creating and using an event type builder involves implementing the builder class and configuring a JavaBean event type to use the builder, as described in the following sections:
When you program the event type builder factory, you must implement the EventBuilder.Factory
inner interface of the com.bea.wlevs.ede.api.EventBuilder
interface; see the Java API Reference for Oracle Stream Analytics for details about the methods you must implement, such as createBuilder
and createEvent
.
The following example of an event type builder factory class is taken from the FX sample:
package com.bea.wlevs.example.fx; import java.util.HashMap; import java.util.Map; import com.bea.wlevs.ede.api.EventBuilder; import com.bea.wlevs.example.fx.OutputBean.ForeignExchangeEvent; public class ForeignExchangeBuilderFactory implements EventBuilder.Factory { // Called by the server to get an instance of this builder. public EventBuilder createBuilder() { return new ForeignExchangeBuilder(); } // Inner interface implementation that is the builder. static class ForeignExchangeBuilder implements EventBuilder { // A Map instance to hold properties until the event type is instantiated. private Map<String,Object> values = new HashMap<String,Object>(10); // Called by the server to put an event type property. Values from the map // will be used to instantiate the event type. public void put(String property, Object value) throws IllegalStateException { values.put(property, value); } // Called by the server to create the event type instance once property // values have been received. public Object createEvent() { return new ForeignExchangeEvent( (String) values.get("symbol"), (Double) values.get("price"), (String) values.get("fromRate"), (String) values.get("toRate")); } } }
When you register the event type in the EPN assembly file, use the <wlevs:property name="builderFactory">
child element of the wlevs:event-type
element to specify the name of the event type builder class. The hard-coded builderFactory
value of the name
attribute alerts Oracle Stream Analytics that it should use the specified factory class, rather than its own default factory, when creating instances of this event. For example, in the FX example, the builder factory is registered as shown in bold:
<wlevs:event-type-repository> <wlevs:event-type type-name="ForeignExchangeEvent"> <wlevs:class>com.bea.wlevs.example.fx.OutputBean$ForeignExchangeEvent</wlevs:class> <wlevs:property name="builderFactory"> <bean id="builderFactory" class="com.bea.wlevs.example.fx.ForeignExchangeBuilderFactory"/> </wlevs:property> </wlevs:event-type> </wlevs:event-type-repository>