JBoss.orgCommunity Documentation

Chapter 3. Translator Development

3.1. Setting up the build environment
3.2. Extending the ExecutionFactory Class
3.2.1. ConnectionFactory
3.2.2. Connection
3.2.3. Configuration Properties
3.2.4. Initializing the Translator
3.2.5. TranslatorCapabilities
3.2.6. Execution (and sub-interfaces)
3.2.7. Metadata
3.2.8. Logging
3.2.9. Exceptions
3.3. Connections to Source
3.3.1. Obtaining connections
3.3.2. Releasing Connections
3.4. Executing Commands
3.4.1. Execution Modes
3.4.2. ExecutionContext
3.4.3. ResultSetExecution
3.4.4. Update Execution
3.4.5. Procedure Execution
3.4.6. Asynchronous Executions
3.4.7. Reusable Executions
3.4.8. Bulk Execution
3.4.9. Command Completion
3.4.10. Command Cancellation
3.5. Command Language
3.5.1. Language
3.5.2. Language Utilities
3.5.3. Runtime Metadata
3.5.4. Language Visitors
3.5.5. Translator Capabilities
3.6. Large Objects
3.6.1. Data Types
3.6.2. Why Use Large Object Support?
3.6.3. Handling Large Objects
3.6.4. Inserting or Updating Large Objects
3.7. Delegating Translator
3.8. Adding Dependent Libraries
3.9. Packaging
3.10. Deployment

For Eclipse create a empty java project and add dependencies to "teiid-common-core", "teiid-api" and JEE "connector-api" jars.

For using maven use following as your dependencies.



    <dependencies>
        <dependency>
            <groupId>org.jboss.teiid</groupId>
            <artifactId>teiid-api</artifactId>
            <scope>provided</scope>
        </dependency>
        <dependency>
            <groupId>org.jboss.teiid</groupId>
            <artifactId>teiid-common-core</artifactId>
            <scope>provided</scope>
        </dependency>
        <dependency>
            <groupId>javax.resource</groupId>
            <artifactId>connector-api</artifactId>
            <scope>provided</scope>
        </dependency>
    </dependencies>        
        

You can find teiid artifacts in the JBoss maven repository

The main class in the translator implementation is ExecutionFactory. A base class is provided in the Teiid API, so a custom translator must extend org.teiid.translator.ExecutionFactory to connect and query an enterprise data source. This extended class must provide a no-arg constructor that can be constructed using Java reflection libraries. This Execution Factory need define/override following elements.



package org.teiid.translator.custom;
@Translator(name="custom", description="Connect to My EIS")
public class CustomExecutionFactory extends ExecutionFactory<MyConnectionFactory, MyConnection> {
    public CustomExecutionFactory() {
    }
}                
         

Define the annotation @Translator on extended "ExecutionFactory" class. This annotation defines name and description of your translator, and also used as identifier during the deployment. This is name you would be using in the VDB and else where in the configuration to refer to this translator.

If the translator requires external configuration, that defines ways for the user to alter the behavior of a program, then define a attribute variable in the class and define "get" and "set" methods for that attribute. Also, annotate each "get" method with @TranslatorProperty annotation and provide the metadata about the property.

For example, if you need a property called "foo", by providing the annotation on these properties, the Teiid tooling can automatically interrogate and provide graphical way to configure your Translator while designing your VDB.

private String foo = "blah";

@TranslatorProperty(display="Foo property", description="description about Foo") 
public String getFoo() 
{
   return foo;
}
public void setFoo(String value) 
{
   return this.foo = value;
} 

Only java primitive (int, boolean), primitive object wrapper (java.lang.Integer), or Enum types are supported as Translator properties. Complex objects are not supported. The default value will be derived from calling the getter method, if available, on a newly constructed instance. All properties should have a default value. If there is no applicable default, then the property should be marked in the annotation as required. Initialization will fail if a required property value is not provided.

The @TranslatorProperty defines the following metadata that you can define about your property

Teiid sends commands to your Translator in object form. These classes are all defined in the "org.teiid.language" package. These objects can be combined to represent any possible command that Teiid may send to the Translator. However, it is possible to notify Teiid that your Translator can only accept certain kinds of constructs via the capabilities defined on the "ExecutionFactory" class. Refer to Section 3.5.5, “Translator Capabilities” for more information.

The language objects all extend from the LanguageObject interface. Language objects should be thought of as a tree where each node is a language object that has zero or more child language objects of types that are dependent on the current node.

All commands sent to your Translator are in the form of these language trees, where the root of the tree is a subclass of Command. Command has several sub-interfaces, namely:

  • QueryExpression

  • Insert

  • Update

  • Delete

  • BatchedUpdates

  • Call

Important components of these commands are expressions, criteria, and joins, which are examined in closer detail below. For more on the classes and interfaces described here, refer to the Teiid JavaDocs http://docs.jboss.org/teiid/7.6/apidocs.

This section covers utilities available when using, creating, and manipulating the language interfaces.

Teiid uses a library of metadata, known as "runtime metadata" for each virtual database that is deployed in Teiid. The runtime metadata is a subset of metadata as defined by models in the Teiid models that compose the virtual database.  While builing your VDB in the Designer, you can define what called "Extension Model", that defines any number of arbitary properties on a model and its objects. At runtime, using this runtime metadata interface, you get access to those set properties defined during the design time, to define/hint any execution behavior.

Translator gets access to the RuntimeMetadata interface at the time of Excecution creation. Translators can access runtime metadata by using the interfaces defined in org.teiid.metadata package.  This package defines API representing a Schema, Table, Columns and Procedures, and ways to navigate these objects.

The API provides a language visitor framework in the org.teiid.language.visitor package.  The framework provides utilities useful in navigating and extracting information from trees of language objects.

The visitor framework is a variant of the Visitor design pattern, which is documented in several popular design pattern references.  The visitor pattern encompasses two primary operations: traversing the nodes of a graph (also known as iteration) and performing some action at each node of the graph.  In this case, the nodes are language interface objects and the graph is really a tree rooted at some node.  The provided framework allows for customization of both aspects of visiting.

The base AbstractLanguageVisitor class defines the visit methods for all leaf language interfaces that can exist in the tree.  The LanguageObject interface defines an acceptVisitor() method – this method will call back on the visit method of the visitor to complete the contract.  A base class with empty visit methods is provided as AbstractLanguageVisitor.  The AbstractLanguageVisitor is just a visitor shell – it performs no actions when visiting nodes and does not provide any iteration.

The HierarchyVisitor provides the basic code for walking a language object tree.  The HierarchyVisitor performs no action as it walks the tree – it just encapsulates the knowledge of how to walk it.  If your translator wants to provide a custom iteration that walks the objects in a special order (to exclude nodes, include nodes multiple times, conditionally include nodes, etc) then you must either extend HierarchyVisitor or build your own iteration visitor.  In general, that is not necessary.

The DelegatingHierarchyVisitor is a special subclass of the HierarchyVisitor that provides the ability to perform a different visitor’s processing before and after iteration.  This allows users of this class to implement either pre- or post-order processing based on the HierarchyVisitor.  Two helper methods are provided on DelegatingHierarchyVisitor to aid in executing pre- and post-order visitors.  

The ExecutionFactory class defines all the methods that describe the capabilities of a Translator. These are used by the Connector Manager to determine what kinds of commands the translator is capable of executing. A base ExecutionFactory class implements all the basic capabilities methods, which says your translator does not support any capabilities. Your extended ExecutionFactory class must override the the necessary methods to specify which capabilities your translator supports.  You should consult the debug log of query planning (set showplan debug) to see if desired pushdown requires additional capabilities.

The following table lists the capabilities that can be specified in the ExecutionFactory class.

Table 3.2. Available Capabilities

Capability

Requires

Description

SelectDistinct

Translator can support SELECT DISTINCT in queries.

SelectExpression

Translator can support SELECT of more than just column references.

AliasedTable

Translator can support Tables in the FROM clause that have an alias.

InnerJoins

Translator can support inner and cross joins

SelfJoins

AliasedGroups and at least on of the join type supports.

Translator can support a self join between two aliased versions of the same Table.

OuterJoins

Translator can support LEFT and RIGHT OUTER JOIN.

FullOuterJoins

Translator can support FULL OUTER JOIN.

InlineViews

AliasedTable

Translator can support a named subquery in the FROM clause.

BetweenCriteria

Not currently used - between criteria is rewriten as compound comparisions.

CompareCriteriaEquals

Translator can support comparison criteria with the operator "=".

CompareCriteriaOrdered

Translator can support comparison criteria with the operator ">" or "<".

LikeCriteria

Translator can support LIKE criteria.

LikeCriteriaEscapeCharacter

LikeCriteria

Translator can support LIKE criteria with an ESCAPE character clause.

SimilarTo

Translator can support SIMILAR TO criteria.

LikeRegexCriteria

Translator can support LIKE_REGEX criteria.

InCriteria

MaxInCriteria

Translator can support IN predicate criteria.

InCriteriaSubquery

Translator can support IN predicate criteria where values are supplied by a subquery.

IsNullCriteria

Translator can support IS NULL predicate criteria.

OrCriteria

Translator can support the OR logical criteria.

NotCriteria

Translator can support the NOT logical criteria. IMPORTANT: This capability also applies to negation of predicates, such as specifying IS NOT NULL, "<=" (not ">"), ">=" (not "<"), etc.

ExistsCriteria

Translator can support EXISTS predicate criteria.

QuantifiedCompareCriteriaAll

Translator can support a quantified comparison criteria using the ALL quantifier.

QuantifiedCompareCriteriaSome

Translator can support a quantified comparison criteria using the SOME or ANY quantifier.

OnlyLiteralComparison

Translator if only Literal comparisons (equality, ordered, like, etc.) are supported for non-join conditions.

Convert(int fromType, int toType)

Used for fine grained control of convert/cast pushdown. If ExecutionFactory.getSupportedFunctions() contains SourceSystemFunctions.CONVERT, then all of the default Teiid pushdown conversions are supported. So typically this method will be implemented when ExecutionFactory.getSupportedFunctions() contains SourceSystemFunctions.CONVERT. See TypeFacility.RUNTIME_CODES for the possible type codes. The engine will does not care about an unnecessary conversion where fromType == toType.

OrderBy

Translator can support the ORDER BY clause in queries.

OrderByUnrelated

OrderBy

Translator can support ORDER BY items that are not directly specified in the select clause.

OrderByNullOrdering

OrderBy

Translator can support ORDER BY items with NULLS FIRST/LAST.

GroupBy

Translator can support an explict GROUP BY clause.

Having

GroupBy

Translator can support the HAVING clause.

AggregatesAvg

Translator can support the AVG aggregate function.

AggregatesCount

Translator can support the COUNT aggregate function.

AggregatesCountStar

Translator can support the COUNT(*) aggregate function.

AggregatesDistinct

At least one of the aggregate functions.

Translator can support the keyword DISTINCT inside an aggregate function.  This keyword indicates that duplicate values within a group of rows will be ignored.

AggregatesMax

Translator can support the MAX aggregate function.

AggregatesMin

Translator can support the MIN aggregate function.

AggregatesSum

Translator can support the SUM aggregate function.

AggregatesEnhancedNumeric

Translator can support the VAR_SAMP, VAR_POP, STDDEV_SAMP, STDDEV_POP aggregate functions.

ScalarSubqueries

Translator can support the use of a subquery in a scalar context (wherever an expression is valid).

CorrelatedSubqueries

At least one of the subquery pushdown capabilities.

Translator can support a correlated subquery that refers to an element in the outer query.

CaseExpressions

Not currently used - simple case is rewriten as searched case.

SearchedCaseExpressions

Translator can support "searched" CASE expressions anywhere that expressions are accepted.

Unions

Translator support UNION and UNION ALL

Intersect

Translator supports INTERSECT

Except

Translator supports Except

SetQueryOrderBy

Unions, Intersect, or Except

Translator supports set queries with an ORDER BY

RowLimit

Translator can support the limit portion of the limit clause

RowOffset

Translator can support the offset portion of the limit clause

FunctionsInGroupBy

GroupBy

Translator can support non-column reference grouping expressions.

InsertWithQueryExpression

Translator supports INSERT statements with values specified by an QueryExpression.

supportsBatchedUpdates

Translator supports a batch of INSERT, UPDATE and DELETE commands to be executed together.

BulkUpdate

Translator supports updates with multiple value sets

InsertWithIterator

Translator supports inserts with an iterator of values. The values would typically be from an evaluated QueryExpression.

CommonTableExpressions

Translator supports the WITH clause.

ElementaryOlapOperations

Translator supports window functions and analytic functions RANK, DENSE_RANK, and ROW_NUMBER.

WindowOrderByWithAggregates

ElementaryOlapOperations

Translator supports windowed aggregates with a window order by clause.

WindowDistinctAggregates

ElementaryOlapOperations, AggregatesDistinct

Translator supports windowed distinct aggregates.

AdvancedOlapOperations

ElementaryOlapOperations

Translator supports aggregate conditions.


Note that any pushdown subquery must itself be compliant with the Translator capabilities.

The method ExecutionFactory.getSupportedFunctions() can be used to specify which scalar functions the Translator supports.  The set of possible functions is based on the set of functions supported by Teiid. This set can be found in the Reference documentation at http://www.jboss.org/teiid//docs.html. If the Translator states that it supports a function, it must support all type combinations and overloaded forms of that function.

There are also five standard operators that can also be specified in the supported function list: +, -, *, /, and ||.

The constants interface SourceSystemFunctions contains the string names of all possible built-in pushdown functions. Note that not all system functions appear in this list. This is because some system functions will always be evaluted in Teiid, are simple aliases to other functions, or are rewriten to a more standard expression.

This section examines how to use facilities provided by the Teiid API to use large objects such as blobs, clobs, and xml in your Translator.

In some instances you may wish to extend several differnt kinds of translators with the same functionality. Rather than create separate subclasses for each extension, you can use the delegating translator framework which provides you with a proxying mechanism to override translator behavior. It implement a delegating translator, your common translator logic should be added to a subclass of BaseDelegatingExecutionFactory where you can override any of the delegation methods to perform whatever logic you want.


You will bundle and deploy your custom delegating translator is just like any other custom translator development. To you use your delegating translator in a vdb, you define a translator override that wires in the delegate.


Add MANIFEST.MF file in the MATA-INF directory, and the following line to add the core Teiid API dependencies for resource adapter. Dependencies: org.jboss.teiid.common-core,org.jboss.teiid.api,javax.api If your translator depends upon any other third party jar files, then those jar files need to be defined under a module and then you can add the module name to the above MANIFEST.MF file to define as dependency.

Once the "ExecutionFactory" class is implemented, package it in a JAR file. Then add the following named file in "META-INF/services/org.teiid.translator.ExecutionFactory" with contents specifying the name of your main Translator file. Note that, the name must exactly match to above. This is java's standard service loader pattern. This will register the Translator for deployment when the jar is deployed into JBoss AS.



org.teiid.translator.custom.CustomExecutionFactory        
        

Copy the JAR file that defines the Translator into "deploy" directory of the JBoss AS's chosen profile, and the Translator will be deployed automatically. There is no restriction that, JBoss AS need to be restarted. However, if your Translator has external dependencies to other modules, they need to be placed inside the "modules" directory of the JBoss AS. This will require a restart of the JBoss Server. You can also use JBoss CLI, Admin API, admin-consle to deploy the jar file into JBoss AS server.