6 Oracle Java Data Cartridge

This chapter describes how to use the Oracle Java Data Cartridge, an extension of Oracle Continuous Query Language (Oracle CQL). You can use Oracle CQL to write CQL code that interacts with Java classes in your Oracle Stream Analytics application.

This chapter describes the types, methods, fields, and constructors that the Oracle Java data cartridge exposes. You can use these types, methods, fields, and constructors in Oracle CQL queries and views as you would Oracle CQL native types.

This chapter includes the following sections:

6.1 Understanding the Oracle Java Data Cartridge

The Oracle Java data cartridge is a built-in Java cartridge that enables you to write Oracle CQL queries and views that interact with the Java classes in your Oracle Stream Analytics application.

This section describes:

6.1.1 Data Cartridge Name

The Oracle Java data cartridge uses the cartridge ID com.oracle.cep.cartrdiges.java.

The Oracle Java data cartridge is the default Oracle Stream Analytics data cartridge.

For types under the default Java package name or types under the system package of java.lang, you can reference the Java type in an Oracle CQL query unqualified by package or data cartridge name:

<query id="q1"><![CDATA[
    select String(“foo") …
></query>

Note:

To simplify Oracle Java data cartridge type names, you can use aliases as described in Oracle Fusion Middleware Oracle CQL Language Reference for Oracle Stream Analytics.

For more information, see: Class Loading.

6.1.2 Class Loading

The Oracle Java data cartridge supports the following policies for loading the Java classes that your Oracle CQL queries reference:

For more information, see:

6.1.2.1 Application Class Space Policy

This is the default class loading policy.

In this mode, the Oracle Java data cartridge uses the class-space of the application in scope when searching for a Java class.

This is only applicable when a type is specified only by its local name, that is, there is a single identifier, and no other identifiers are being used for its package. That is:

select String(“foo") …

And not:

select java.lang.String(“foo") …

In this case the procedure is as follows:

  • Attempt to load the class defined by the single identifier (call it ID1) using the application's class-space as usual; if this fails then:

  • Verify if the application defines any class within its bundle's internal class-path whose name matches ID1, independent of the package; if this fails then:

  • Verify if application specifies an Import-Package MANIFEST header statement which in conjunction with ID1 can be used to load a Java class.

For an example, see Class Loading Example.

6.1.2.2 No Automatic Import Class Space Policy

This is an optional class loading policy. To use this policy, you must include the following MANIFEST header entry in your Oracle Stream Analytics application:

OCEP_JAVA_CARTRIDGE_CLASS_SPACE: APPLICATION_NO_AUTO_IMPORT_CLASS_SPACE

This mode is similar to the application class space policy except that Oracle Event Processing does not attempt to combine the package with ID1.

For more information, see Application Class Space Policy.

6.1.2.3 Server Class Space Policy

This is an optional class loading policy. To use this policy, you must include the following MANIFEST header entry in your Oracle Stream Analytics application:

OCEP_JAVA_CARTRIDGE_CLASS_SPACE: SERVER_CLASS_SPACE

An Oracle CQL query can reference any exported Java class, regardless of whether or not the class package is imported into the application or bundle

The query can also access all classes visible to the OSGi framework's parent class-loader, which includes the runtime JDK classes.

This means that an Oracle CQL application may contain an Oracle CQL query that references classes defined by other Oracle Stream Analytics applications, as long as they are exported. This behavior facilitates the creation of Java-based cartridges whose sole purpose is to provide new Java libraries.

Note:

You can only reference a Java class that is part of the internal class path of an Oracle Stream Analytics application if it is exported, even when a processor within this application defines the Oracle CQL query.

For an example, see Class Loading Example.

6.1.2.4 Class Loading Example

Consider the example that Figure 6-1 shows: application B1 imports package package2 that application B2 exports.

Figure 6-1 Example Oracle Stream Analytics Event Processing Applications

Description of Figure 6-1 follows
Description of "Figure 6-1 Example Oracle Stream Analytics Event Processing Applications"

Table 6-1 summarizes which classes these two different applications can access depending on whether they are running in the application class space or server class space.

Table 6-1 Class Accessibility by Class Loading Policy

Class Loading Policy Application B1 Application B2

Application Class Space

  • mypackage1.A

  • myprivatepackage1.B

  • package2.C

  • package2.C

  • privatepackage2.D

Server Class Space

  • package2.C

  • package2.C

In application B1, you can use any of the Java classes A, B, and C in your Oracle CQL queries:

select A …
select B …
select C …

However, in application B2, you cannot use Java classes A and B in your Oracle CQL queries. You can only use Java classes C and D:

select C …
select D …

6.1.3 Method Resolution

An Oracle CQL expression that accesses a Java method uses the following algorithm to resolve the method:

  1. All parameter types are converted to Java types as Datatype Mapping describes.

    For example, an Oracle CQL INTEGER is converted to a Java primitive int.

  2. Standard Java method resolution rules are applied as the Java Language Specification, Third Edition, Section 15.12, "Method Invocation Expressions" describes.

Note:

Variable arity methods are not supported. For more information, see the Java Language Specification, Third Edition, Section 12.12.2.4.

As an example, consider the following Oracle CQL expression:

attribute.methodA(10)

Where attribute is of type mypackage.MyType which defines the following overloaded methods:

  • methodA(int)

  • methodA(Integer)

  • methodA(Object)

  • methodA(long)

As the literal 10 is of the primitive type int, the order of precedence is:

  • methodA(int)

  • methodA(long)

  • methodA(Integer)

  • methodA(Object)

For more information, see Class Loading.

6.1.4 Datatype Mapping

The Oracle Java data cartridge applies a fixed, asymmetrical mapping between Oracle CQL native data types and Java data types.

  • Table 6-2 lists the mappings between Oracle CQL native data types and Java data types.

  • Table 6-3 lists the mappings between Java data types and Oracle CQL native data types.

Table 6-2 Oracle Java Data Cartridge: Oracle CQL to Java Data Type Mapping

Oracle CQL Native Data Type Java Data Type

BIGINT

long

BOOLEAN

boolean

BYTE

byte[]

CHAR

java.lang.String

DOUBLE

double

FLOAT

float

INTEGER

int

INTERVAL

long

INTERVAL_DAY

long, java.lang.String

INTERVAL_DAY_TO_SECOND

java.lang.String

INTERVAL_YEAR

long, java.lang.String

INTERVAL_MONTH

long, java.lang.String

INTERVAL_YEAR_TO_MONTH

java.lang.String

XMLTYPE

java.lang.String

Table 6-3 Oracle Java Data Cartridge: Java Data Type to Oracle CQL Mapping

Java Datatype Oracle CQL Native Data Type

long

BIGINT

boolean

BOOLEAN

byte[]

BYTE

java.lang.String

CHAR

double

DOUBLE

float

FLOAT

int

INTEGER

java.sql.Date

java.sql.Timestamp

INTERVAL

java.sql.SQLXML

XMLTYPE

All other Java classes are mapped as a complex type.

For more information on these datatype mappings:

6.1.4.1 Java Data Type String and Oracle CQL Data Type CHAR

Oracle CQL data type CHAR is mapped to java.lang.String and java.lang.String is mapped to Oracle CQL data type CHAR. This means you can access java.lang.String member fields and methods for an attribute defined as Oracle CQL CHAR. For example, if a1 is declared as type Oracle CQL CHAR, then you can write a query like this:

<query id="q1"><![CDATA[ 
    select a1.substring(1,2)
></query>

6.1.4.2 Literals

You cannot access member fields and methods on literals, even Oracle CQL CHAR literals. For example, the following query is not allowed:

<query id="q1-forbidden"><![CDATA[ 
    select "hello".substring(1,2)
></query>

6.1.4.3 Arrays

Java arrays are converted to Oracle CQL data cartridge arrays, and Oracle CQL data cartridge arrays are converted to Java arrays. This applies to both complex types and simple types.

You can use the data cartridge TABLE clause to access the multiple rows returned by a data cartridge function in the FROM clause of an Oracle CQL query.

For more information, see Collections.

6.1.4.4 Collections

Typically, the Oracle Java data cartridge converts an instance that implements the java.util.Collection interface to an Oracle CQL complex type.

An Oracle CQL query can iterate through the members of the java.util.Collection.

You can use the data cartridge TABLE clause to access the multiple rows returned by a data cartridge function in the FROM clause of an Oracle CQL query.

For more information, see Arrays.

6.1.5 Oracle CQL Query Support for the Oracle Java Data Cartridge

You may use Oracle Java data cartridge types in expressions within a SELECT clause and WHERE clause.

You may not use Oracle Java data cartridge types in expressions within an ORDER BY clause.

For more information, see Using the Oracle Java Data Cartridge.

6.2 Using the Oracle Java Data Cartridge

This section describes common use-cases that highlight how you can use the Oracle Java data cartridge in your Oracle Stream Analytics applications, including:

For more information, see Oracle CQL Query Support for the Oracle Java Data Cartridge.

6.2.1 How to Query Using the Java API

This procedure describes how to use the Oracle Java data cartridge in an Oracle Stream Analytics application that uses one event type defined as a tuple (Student) that has an event property type defined as a Java class (Address.java).

To query with Java classes:

  1. Implement the Address.java class.
    package test;
    
    class Address {
        String street;
        String state;
        String city;
        String [] phones;
    }
    

    In this example, assume that the Address.java class belongs to this application.

    If the Address.java class belonged to another Oracle Stream Analytics application, it must be exported in its parent application. For more information, see How to Query Using Exported Java Classes.

  2. Define the event type repository.
    <event-type-repository>
        <event-type name="Student">
            <properties>
                <property name="name" type="char"/>
                <property name="address" type="Address"/>
            </properties>
        </event-type>
    
        <event-type name="Address">
            <class-name>test.Address</class-name>
        </event-type>
    <event-type-repository>
    

    Because the test.Address class belongs to this application, it can be declared in the event type repository. This automatically makes the class globally accessible within this application; its package does not need to be exported.

  3. Assume that an adapter is providing Student events to channel StudentStream:
    <channel id="StudentStream" event-type="Student"/>
    
  4. Assume that the StudentStream is connected to a processor with the Oracle CQL query q1.
    <processor> 
        <rules>
    
            <query id="q1"><![CDATA[ 
    
                select 
                    name, 
                    address.street as street, 
                    address.phones[0] as primary_phone 
                from 
                    StudentStream
    
            ></query>
    
        </rules>
    </processor>
    

    The Oracle Java data cartridge allows you to access the address event property from within the Oracle CQL query using normal Java API.

6.2.2 How to Query Using Exported Java Classes

This procedure describes how to use the Oracle Java data cartridge in an Oracle Stream Analytics application that uses one event type defined as a tuple (Student) that has an event property type defined as a Java class (Address.java). In this procedure, the Address.java class belongs to a separate Oracle Stream Analytics application. It is exported in its parent application to make it accessible to other Oracle Stream Analytics applications deployed to the same Oracle Stream Analytics server.

To query with Java classes:

  1. Implement the Address.java class.
    package test;
    
    class Address {
        String street;
        String state;
        String city;
        String [] phones;
    }
    
  2. Export the test package that contains the Address.java class.

    For more information, see Developing Applications for Event Processing with Oracle Stream Analytics.

    The test package may be part of this Oracle Stream Analytics application or it may be part of some other Oracle Stream Analytics application deployed to the same Oracle Stream Analytics server as this application.

  3. Define the event type repository.
    <event-type-repository>
        <event-type name="Student">
            <property name="name" type="char"/>
            <property name="address" type="Address"/>
        </event-type>
    <event-type-repository>
    
  4. Assume that an adapter is providing Student events to channel StudentStream:
    <channel id="StudentStream" event-type="Student"/>
    
  5. Assume that the StudentStream is connected to a processor with the Oracle CQL query q1.
    <processor> 
        <rules>
    
            <query id="q1"><![CDATA[ 
    
                select 
                    name, 
                    address.street as street, 
                    address.phones[0] as primary_phone 
                from 
                    StudentStream
    
            ></query>
    
        </rules>
    </processor>
    

    The Oracle Java data cartridge allows you to access the address event property from within the Oracle CQL query using normal Java API.

6.2.3 Java Cast Function

The Java cartridge provides the Java Cast function that enables a Java extensible type to be cast to another Java extensible type, providing the latter can be assigned from the former. To use this function, you must have the Java cartridge installed.

Syntax

T cast@java(l-value, class-literal<T>)

Parameters

l-value: A event attribute that contains the data that you want to cast. If l-value cannot be assigned from T, then Java Cartridge raises a RuntimeInvocationException during the invocation of the cast function

class-literal<T>: The name of the class to which you want to cast. For example, if you want to cast an int to long, then class-literal<T> is Long.class.

Example

Consider the following class hierarchy:

public class Parent 
{
...
}
 
public class Child extends Parent
{
...
}

The following example casts an object of type Child.

cast@java(S.parent, Child.class)