There is a large variety of XQuery implementations, both from an architectural perspective, as well as in the range of supported data sources. XQJ is designed that all these different architectures can be plugged in. For example, based on the XQJ and XQuery implementation, the required parameters and settings to configure the implementation might be different. Some implementations are server based, and require information to locate the server. Or, if the XQJ and XQuery implementation are co-located, you might need to specify the default location to query files on the local file system.
An XQJ application always starts with accessing an XQDataSource object. Such object encapsulates all parameters and settings needed to create a session with a specific implementation and eventually execute XQuery expressions and process results.
Every XQJ driver has its own XQDataSource implementation. This XQDataSource object supports a number of implementation-specific properties. For each of these properties, a "getter" and "setter" method is provided.
Assume an application wants to query both an Oracle database, and some files located in "/usr/joe/data" with DataDirect XQuery. Two properties need to be specified, the base uri and the jdbc url to connect to the Oracle database (feel free to replace Oracle with your favorite database, be it SQL server, MySQL or yet another one),
[cc lang="java"]DDXQDataSource xqds = new DDXQDataSource(); xqds.setBaseUri("/usr/joe/data"); xqds.setJdbcUrl("jdbc:xquery:oracle://sales:1521;SID=ORA10");[/cc]
Or envision another Oracle specific implementation where the server parameters are specified in individual properties rather than through a jdbc url. It could be as follows,
[cc lang="java"]OracleDataSource xqds = new OracleDataSource() xqds.setServerName("sales"); xqds.setPortNumber(1521); xqds.setSID("ORA10");[/cc]
Having access to an XQDataSource object, what's next? An XQDataSource is a factory for XQConnection objects. The XQConnection object represents a session in which XQuery expression are executed.
Establishing such a session is straightforward,
[cc lang="java"]XQConnection xqc = xqds.getConnection();[/cc]
In case user credentials are needed, these can be specified as arguments to the getConnection() method,
[cc lang="java"]XQConnection xqc = xqds.getConnection("joe", "topsecret");[/cc]
So far so good. Using the approach outlined above to create XQDataSource objects, makes the application dependent on a specific XQJ implementation. The proprietary classes DDXQDataSource and OracleDataSource are referenced. This is not necessarily wrong, there are scenarios where hard-coding the underlying XQJ implementation makes sense.
But often this is not desirable, XQJ is all about making your application independent from the underlying XQuery implementation. How can we make our application independent of the XQJ implementation? We'll show two approaches.
Assume all the XQDataSource properties are stored in a Java properties file, and in addition a property ClassName to identify the XQDataSource implementation to use.
For the DataDirect XQuery example above, the properties file would look as follows,
[cc lang="java"]ClassName = com.ddtek.xquery3.xqj.DDXQDataSource BaseUri = /usr/joe/data JdbcUrl = jdbc:xquery:oracle://sales:1521;SID=ORA10[/cc]
For the Oracle implementation,
[cc lang="java"]ClassName = org.example.xqj.OracleDataSource ServerName = sales PortNumber = 1521 SID = ORA10[/cc]
Using such properties file, an application can easily abstract out any hard-coded dependencies on the underlying XQJ implementation. The XQDataSource class is loaded through reflection and next it is simply a matter of passing in the properties.
[cc lang="java"]// load the properties file Properties p = new Properties(); p.load(new FileInputStream("/tmp/xqjds.prop"));
// create an XQDataSource instance using reflection String xqdsClassName = properties.getProperty("ClassName"); Class xqdsClass = Class.forName(xqdsClassName); XQDataSource xqds = (XQDataSource)xqdsClass.newInstance();
// remove the ClassName property // the XQJ implementation will not recognize // it and raise an error p.remove("ClassName");
// set the remaining properties xqds.setProperties(tmpProperties);
// create an XQConnection XQConnection xqc = xqds.getConnection();[/cc]
Of course, this is just an example, it might well be that for some applications another means to load the datasource properties is better suited.
Similar to JDBC, running in a J2EE environment, the XQDataSource object can be stored in a JNDI-enabled naming service. This allows your application to access the XQDataSource by simply specifying a logical name.
[cc lang="java"]// get the initial JNDI context Context ctx = new InitialContext(); // load the XQDataSource instance XQDataSource xqds = (XQDataSource)ctx.lookup("xqj/sales"); // create an XQConnection XQConnection xqc = xqds.getConnection();[/cc]
For the readers with a JDBC background; JDBC has two mechanisms to establish a connection
Don't look in XQJ for DriverManager-like functionality, XQJ doesn't offer this legacy functionality.
We have now learned how to create an XQConnection. In our next post we will do some real work, and show how to execute queries.
digg_skin = 'compact';
View all posts from Marc Van Cappellen on the Progress blog. Connect with us about all things application development and deployment, data integration and digital business.
Let our experts teach you how to use Sitefinity's best-in-class features to deliver compelling digital experiences.
Learn MoreSubscribe to get all the news, info and tutorials you need to build better business apps and sites