JBoss.orgCommunity Documentation
This chapter examines how to use facilities provided by the Teiid API to develop a JEE JCA Connector. Please note that these are standard JEE JCA connectors, nothing special needs to be done for Teiid. As an aid to our Translator developers, we provided a base implementation framework. If you already have a JCA Connector or some other mechanism to get data from your source system, you can skip this chapter.
If you are not familiar with JCA API, please read the JCA 1.5 Specification at http://java.sun.com/j2ee/connector/. There are lot of online tutorials on how to design and build a JCA Connector. The below we show you to build very simple connector, however building actual connector that supports transactions, security can get much more complex.
Refer to the JBoss Application Server Connectors documentation at http://docs.jboss.org/jbossas/jboss4guide/r4/html/ch7.chapt.html.
If you are going to use the Teiid framework for developing a JCA connector, follow these steps. The required classes are in
org.teiid.resource.api
package. Please note that Teiid framework does not make use JCA's CCI framework, only the JCA's SPI interfaces.
Define Managed Connection Factory
Define the Connection Factory class
Define the Connection class
Define the configuration properties in a "ra.xml" file
Extend the BasicManagedConnectionFactory
, and provide a implementation for the
"createConnectionFactory()" method. This method defines a factory method that can create connections.
This class also defines configuration variables, like user, password, URL etc to connect to the EIS system. Define an attribute for each configuration variable, and then provide both "getter" and "setter" methods for them. Note to use only "java.lang" objects as the attributes, DO NOT use Java primitives for defining and accessing the properties. See the following code for an example.
public class MyManagedConnectionFactory extends BasicManagedConnectionFactory
{
@Override
public Object createConnectionFactory() throws ResourceException
{
return new MyConnectionFactory();
}
// config property name (metadata for these are defined inside the ra.xml)
String userName;
public String getUserName() { return this.userName; }
public void setUserName(String name){ this.userName = name; }
// config property count (metadata for these are defined inside the ra.xml)
Integer count;
public Integer getCount() { return this.count; }
public void setCount(Integer value) { this.count = value; }
}
Extend the BasicConnectionFactory
class, and provide a implementation for the "getConnection()" method.
public class MyConnectionFactory extends BasicConnectionFactory
{
@Override
public MyConnection getConnection() throws ResourceException
{
return new MyConnection();
}
}
Since the Managed connection object created the "ConnectionFactory" class it has access to all the configuration
parameters, if "getConnection" method needs to do pass any of credentials to the underlying EIS system.
The Connection Factory class can also get reference to the calling user's javax.security.auth.Subject
during
"getConnection" method by calling
Subject subject = ConnectionContext.getSubject();
This "Subject" object can give access to logged-in user's credentials and roles that are defined. Note that this may be null.
Note that you can define "security-domain" for this resource adapter, that is separate from the Teiid defined "security-domain" for validating the JDBC end user. However, it is users responsibility to make the necessary logins before the Container's thread accesses this resource adapter, and this can get overly complex.
Extend the BasicConnection
class, and provide a implementation based on your access
of the Connection object in the Translator. If your
connection is stateful, then override "isAlive()" and "cleanup()" methods and provide proper implementations. These are called
to check if a Connection is stale or need to flush them from the connection pool etc. by the Container.
public class MyConnection extends BasicConnection
{
public void doSomeOperation(command)
{
// do some operation with EIS system..
// This is method you use in the Translator, you should know
// what need to be done here for your source..
}
@Override
public boolean isAlive()
{
return true;
}
@Override
public void cleanUp()
{
}
}
If your EIS source can participate in XA transactions, then on your Connection object, override the "getXAResource()" method and provide the "XAResource" object for the EIS system. Refer to Section 2.1.3, “Define the Connection class”. Also, You need to extend the "BasicResourceAdapter" class and provide implementation for method "public XAResource[] getXAResources(ActivationSpec[] specs)" to participate in crash recovery.
Note that, only when the resource adapters are XA capable, then Teiid can make them participate in a distributed transactions. If they are not XA capable, then source can participate in distributed query but will not participate in the transaction. Transaction semantics at that time defined by how you defined "-ds.xml" file. i.e. with local-tx or no-tx
Define a "ra.xml" file in "META-INF" directory of your RAR file. An example file is provided in Appendix A, ra.xml file Template.
For every configuration property defined inside the ManagedConnectionFactory class, define the following XML configuration fragment inside the "ra.xml" file. These properties are used by user to configure instance of this Connector inside a Container. Also, during the startup the Container reads these properties from this file and knows how to inject provided values in the "-ds.xml" file into a instance of "ManagedConnectionFactory" to create the Connection. Refer to Section 2.1.1, “Define Managed Connection Factory”.
<config-property>
<description>
{$display:"${display-name}",$description:"${description}", $allowed="${allowed}",
$required="${true|false}", $defaultValue="${default-value}"}
</description>
<config-property-name>${property-name}</config-property-name>
<config-property-type>${property-type}</config-property-type>
<config-property-value>${optioal-property-value}</config-property-value>
</config-property>
The format and contents of "<description>" element may be used as extended metadata for tooling. The special format must begin and end with curly braces e.g. {...}. This use of the special format and all properties is optional. Property names begin with '$' and are separated from the value with ':'. Double quotes identifies a single value. A pair of square brackets, e.g. [...], containing comma separated double quoted entries denotes a list value.
Extended metadata properties
$display: Display name of the property
$description: Description about the property
$required: The property is a required property; or optional and a default is supplied
$allowed: If property value must be in certain set of legal values, this defines all the allowed values
$masked: The tools need to mask the property; Do not show in plain text; used for passwords
$advanced: Notes this as Advanced property
$editable: Property can be modified; or read-only
Note that all these are optional properties; however in the absence of this metadata, Teiid tooling may not work as expected.
Once all the required code is developed, it is time to package them into a RAR artifact, that can be deployed into a Conainer. A RAR artifact is lot more similar to a WAR. To put together a RAR file it really depends upon build system you are using.
Eclipse: You can start out with building Java Connector project, it will produce the RAR file
Ant: If you are using "ant" build tool, there is "rar" build task available
Maven: If you are using maven, use <packaging> element value as "rar". Teiid uses maven, you can look at any of the "connector" projects for sample "pom.xml" file. Here is sample pom.xml file.
<?xml version="1.0" encoding="UTF-8"?>
<project xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<modelVersion>4.0.0</modelVersion>
<artifactId>connector-{name}</artifactId>
<groupId>org.company.project</groupId>
<name>Name Connector</name>
<packaging>rar</packaging>
<description>This connector is a sample</description>
<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>
</project>
Make sure that the RAR file, under its "META-INF" directory has the "ra.xml" file. If you are using maven refer to http://maven.apache.org/plugins/maven-rar-plugin/. In the root of the RAR file, you can embed the JAR file containing your connector code and any dependent library JAR files.
Once the RAR file is built, deploy it by copying the RAR file into "deploy" directory of JBoss AS's choosen profile. Typically the server does not need to be restarted when a new RAR file is being added. Alternatively, you can also use "admin-console" a web based monitoring and configuration tool to deploy this file into the container.
Once the Connector's RAR file is deployed into the JBoss container, now you can start creating a instance of this connector to be used with your Translator. Creating a instance of this Connector is no different than creating a "Connection Factory" in JBoss AS. Again, you have have two ways you can create a "ConnectionFactory".
Create "${name}-ds.xml" file, and copy it into "deploy" directory of JBoss AS.
<!DOCTYPE connection-factories PUBLIC
"-//JBoss//DTD JBOSS JCA Config 1.5//EN" "http://www.jboss.org/j2ee/dtd/jboss-ds_1_5.dtd">
<connection-factories>
<no-tx-connection-factory>
<jndi-name>${jndi-name}</jndi-name>
<rar-name>${name}.rar</rar-name>
<connection-definition>javax.resource.cci.ConnectionFactory</connection-definition>
<!--
define all the properties defined in the "ra.xml" that required or needs to be
modified from defaults each property is defined in single element
-->
<config-property name="prop-name" type="java.lang.String">prop-value</config-property>
</no-tx-connection-factory>
</connection-factories>
There are lot more properties that you can define for pooling, transactions, security etc in this file. Check JBoss AS documentation for all the avaialble properties.
Alternatively you can use the web based "admin-console" configration and monitoring program, to create a new Connection Factory. Just have your RAR file name and needed configuration properties handly and fill out web form and create the ConnectionFactory.