Skip to main content
Jump to: navigation, search

SMILA/Documentation/XQJ Implementation

< SMILA‎ | Documentation
Revision as of 05:56, 13 November 2008 by Pfreytag.brox.de (Talk | contribs) (Package structure & nomenclature)

Summary

This page specifies the IT-Design and Guidelines for the XQJ (JSR-225) implementation furthermore referenced as Bdx – XQJ Implementation within this web page. The Bdx XQJ Implementation will make possible for final Java clients to use the XQJ API in order to access the Oracle Berkeley DB Xml (“embeddable XML database with XQuery based access to documents stored in containers and indexed based on their content”).


Bdx XQJ Implementation Overview

The architecture does interface data from Oracle Berkeley DB Xml to end Java clients based on the XQJ (JSR-225) specifications. The following picture outlines a simplified overview of the structure together with the focus for this document.

BdxXQJImplementationOverview.jpg

Bdx XQJ implementation provides part of the XQJ functionality, especially for the query support.


UML Class Diagrams

XQJ (JSR-225) – class diagram

Fallowing two class diagrams represent the XQJ architecture as defined by the JSR-225 (http://jcp.org/en/jsr/detail?id=225)

  • XQJ Class Diagram 1

JSR225-subpart1.jpg

  • XQJ Class Diagram 2

JSR225-subpart2.jpg


Bdx XQJ Implementation

The following class diagram represents the current state of the Bdx XQJ implementation, considering as a basic priority the query functionality. Currently not all the XQJ interfaces (functionalities) have been implemented – only the necessary operations that provide query support.

BdxXQJ.jpg

Bdx XQJ Implementation – data type hierarchy

Bdx XQJ implementation provides its own type – value hierarchy for data representation. The type hierarchy is only internal used.

BdxValueType.jpg

Currently not all the data types (values) have been implemented; just the necessary types in order to support the main querying operations for few basic XS data types.


Bdx XQJ Implementation characteristics

Package structure & nomenclature

The base package of the Bdx XQJ Implementation is: org.eclipse.smila.xmlstorage.internal.xquery.bdx. Most of the Bdx XQJ implementation sources follow the next naming format:

  • for concrete implementation of XQJ interfaces: BdxXQNameImpl;
  • for sources that support the basic XQJ implementation: BdxName
  • there are also sources with only the concrete class name

The type – value hierarchy implementation sources follow the next naming format:

  • sources representing types: XQTypeNameType, BdxNameType
  • sources representing values: XQValueNameValue

Sub-packages details:

  • org.eclipse.smila.xmlstorage.internal.xquery.bdx: contains the implementation classes of the XQJ interfaces (javax.xml.xquery);
  • org.eclipse.smila.xmlstorage.internal.xquery.bdx.bind: provides the external binding that allows client code to bind variables;
  • org.eclipse.smila.xmlstorage.internal.xquery.bdx.map: maps/converts Oracle Berkeley DB Xml from/to XQJ items;
  • org.eclipse.smila.xmlstorage.internal.xquery.bdx.message: offers localized messages support. Current Bdx XQJ Implementation version doesn’t use this functionality for all error messages. It only shows how this featuring shall be used/adapted in order to support full internationalization messages support;
  • org.eclipse.smila.xmlstorage.internal.xquery.bdx.ou: object utilities class;
  • org.eclipse.smila.xmlstorage.internal.xquery.bdx.txn: provides transaction demarcation for client code
  • org.eclipse.smila.xmlstorage.internal.xquery.bdx.type and org.eclipse.smila.xmlstorage.internal.xquery.bdx.value provide the data type hierarchy which is internal used by the current implementation;
  • org.eclipse.smila.xmlstorage.internal.xquery.bdx.util: utility class for internal usage.

(Next versions of the Bdx XQJ Implementation will most probably have minor changes in current package structure – which will not affect the client code implementation)

Implemented functionalities

  • Creating data source (BdxXQDataSourceImpl)
  • Establishing connection through the data source (BdxXQConnectionImpl)
  • Creating expressions
  • Binding values to external values
  • Executing queries (BdxXQExpressionImpl)
  • Retrieving results from xquery
  • Closing (release) resources

Non-implemented functionalities

  • Load the XQDataSource object through JNDI
  • Binding value to the context item
  • Executing queries through XQPreparedExpression (BdxXQPreparedExpressionImpl exists but doesn’t provide functionality)
  • Using a Result Sequence as input

Following picture outlines the non-implemented interfaces/methods by cutting the method signature / interface with a red line. All the not-implemented operations will be implemented as soon as they will be required to support different operations, different data types and value conversions.

JSR225-NotImplemented.jpg

Technical requirements and dependencies

  • J2SE 5.0
  • Oracle Berkeley DB Xml 2.4.13. Required jars and libraries that come with the distribution: db.jar; dbxml.jar; libdb_java46.dll, libdb46.dll, libdbxml_java24.dll, libdbxml24.dll, msvcp71.dll, msvcr71.dll, xerces-c_2_8.dll, xqilla21.dll. The DLLs are to be used on Windows operating system. For linux system the so libraries have to be built: (libdb_java-4.6.so, libdb-4.6.so, libdb_cxx-4.6.so, libdbxml_java-2.4.so, libdbxml-2.4.so, libxerces-c.so, libxqilla.so);
  • javax.xml.stream
  • XQJ – javax.xml.xquery
  • Log4j – log4j.jar

Logging

The Apache Commons Logging library is used for logging.

Error & Message handling

Currently all the exceptions are wrapped into javax.xml.xquery.XQException. Bdx XQJ Implementation exceptions are concrete checked exceptions, which contain the initial cause (in case the exception is not recently thrown). They provide recursively call to method getCause, until a null value is returned, to navigate the chain of causes. This way client code is able to obtain the entire list of occurred exceptions. Client code shall avoid catching top-level exceptions – where it makes sense – in order to handle in the right way the XQJ exceptional operations. Current Bdx XQJ Implementation throw a new UnsupportedOperationException("Unimplemented method") exception for all unimplemented operations.

Internationalization

Bdx XQJ Implementation provides the localized messages support, but current version doesn’t use this functionality for all error messages. It only shows how this featuring shall be used / adapted in order to support full internationalization messages support. The messages are localized into properties files. The default file is ErrorMessages.properties (located under org.eclipse.eilf.xmlstorage.internal.xquery.bdx.message) which only contains two messages at the moment.

Tuning

For better performance the Oracle Berkeley DB Xml settings need to be adjusted according to the own needs. The BDB Xml settings are not currently available via Bdx XQJ Implementation. Proper configuration of JVM will improve performance, by configuring particularly parameters related to memory usage (“-Xms” initial java heap size and “-Xmx” maximum java heap size) and garbage collection.

Bdx XQJ Implementation Use–Cases / Developer guide

Environment setup

Bdx XQJ Implementation allows client code to setup following three properties:

  • Oracle Berkeley DB Xml environment path
  • Default BDB Xml container
  • Deadlock detection and resolving (not implemented yet since current version shall support most of the query operations – read only)

There are many properties/options that Oracle Berkeley DB Xml allows to be setup in order to obtain better performance and support, that are not directly exposed to the XQJ clients – they are configured internally by the Bdx XQJ Implementation. These optional parameters configuration could be considered currently as featuring, so in future they could be exposed to the XQJ clients as data source properties.

Data flow

BdxXQJ-DataFlow.jpg

The result obtained from the Oracle Berkeley DB Xml by applying XQuery statements are converted by the BDB Xml libraries into BDB Xml XmlResults. The XmlResult list is used to generate the XQJ result sequence of items by the Bdx XQJ Implementation. These items are returned by the Bdx XQJ Implementation and client code will use them in order to create value objects

Code sample

Following sample code outlines how the client code application can connect to an Oracle Berkeley DB Xml environment (XQuery engine), execute XQuery expression, handle results and release the resources.

final Properties props = new Properties();
    props.put(BdxXQDataSourceImpl.ENVIRONMENT_PATH_PROPERTY_KEY, envPath);
    props.put(BdxXQDataSourceImpl.CONTAINER_PROPERTY_KEY, "book.dbxml");
    props.put(BdxXQDataSourceImpl.DEADLOCKS_DETECTION_PROPERTY_KEY, "true");
 
    XQDataSource dataSource = new BdxXQDataSourceImpl(props);
 
    XQConnection connection = null;
    XQExpression expr = null;
    XQResultSequence result = null;
    try {
      connection = dataSource.getConnection();
 
      expr = connection.createExpression();
      expr.bindInt(new QName("year"), 2003, null);
      expr.bindDouble(new QName("price"), 49.99, null);
 
      final String myQuery =
        "declare variable $year as xs:decimal external; "
          + "for $part in (collection(\"book.dbxml\")/bookstore/book[year = $year and price = $price]/year/number()) return xs:integer($part)";
 
      // execute the XQuery expression
      result = expr.executeQuery(myQuery);
      while (result.next()) {
        final Integer value = result.getInt();
        debug("Year : " + value, LOG);
      }
    } catch (final XQException e) {
      e.printStackTrace();
    } finally {
      if (result != null) {
        result.close();
      }
 
      if (expr != null) {
        expr.close();
      }
 
      if (connection != null) {
        connection.close();
      }
    } // finally

For the above sample, consider the BDB Xml environment has been populated with following documents:

<bookstore>
<book category="COOKING">
  <title lang="en">Everyday Italian</title>
  <author>Giada De Laurentiis</author>
  <year>2005</year>
  <price>30.00</price>
</book>
<book category="CHILDREN">
  <title lang="en">Harry Potter</title>
  <author>J K. Rowling</author>
  <year>2005</year>
  <price>29.99</price>
</book>
<book category="WEB">
  <title lang="en">XQuery Kick Start</title>
  <author>James McGovern</author>
  <author>Per Bothner</author>
  <author>Kurt Cagle</author>
  <author>James Linn</author>
  <author>Vaidyanathan Nagarajan</author>
  <year>2003</year>
  <price>49.99</price>
</book>
<book category="WEB">
  <title lang="en">Learning XML</title>
  <author>Erik T. Ray</author>
  <year>2003</year>
  <price>39.95</price>
</book>
</bookstore>

DAO concept in client application

The Bdx XQJ Implementation should represent the Integration Tier solution, in order to decouple the persistency layer from the business layer (the overall architecture shall rely on the Abstract DAO Factory pattern). Applications that use current implementation should provide consistent interfaces to access persistent data from the core/business components (bundles).

BdxXQJ-DAO-Concept.jpg

Based on this architecture the XQExceptions shall not leave the Integration (persistence) layer, they shall be wrapped into business exception classes that make sense for the business tier.

Transaction support (demarcation)

Bdx XQJ Implementation provides transaction support through the XQConnection interface. The auto-commit (set on true) mode is the default one for connections; that means any xquery statement is executed and committed in a new separate transaction. In case of the auto-commit mode is turned off, the transaction needs to be ended explicitly by the client code. Next sample code shows how to run two different expressions in a single transaction by using the same connection:

…
    XQConnection connection = null;
    XQExpression expr1 = null;
    XQExpression expr2 = null;
    XQResultSequence result1 = null;
    XQResultSequence result2 = null;
    try {
      connection = dataSource.getConnection();
      connection.setAutoCommit(false);
 
      expr1 = connection.createExpression();
      expr2 = connection.createExpression();
 
      final String myQuery1 =
        "declare variable $year as xs:decimal external; "
          + "for $part in (collection(\"book.dbxml\")/bookstore/book[year = $year and price = $price]/year/number()) return xs:integer($part)";
 
      final String myQuery2 =
        "declare variable $year as xs:decimal external; "
          + "for $part in (collection(\"book.dbxml\")/bookstore/book[year = $year]) return $part";
 
      expr1.bindInt(new QName("year"), 2003, null);
      expr1.bindDouble(new QName("price"), 49.99, null);
      result1 = expr1.executeQuery(myQuery1);
      while (result1.next()) {
        final Integer value = result1.getInt();
        debug("Year : " + value, LOG);
      }
 
      expr2.bindInt(new QName("year"), 2003, null);
      result2 = expr2.executeQuery(myQuery2);
      while (result2.next()) {
        final Node value = result2.getNode();
        debug("DOM node name: " + value.getNodeName(), LOG);
        debug("DOM node value: " + value.getNodeValue(), LOG);
      }
 
      connection.commit();
 
    } catch (final XQException e) {
      e.printStackTrace();
    } finally {
      if (result1 != null) {
        result1.close();
      }
      if (expr1 != null) {
        expr1.close();
      }
      if (result2 != null) {
        result2.close();
      }
      // if (expr2 != null) {
      // expr2.close();
      // }
 
      if (connection != null) {
        connection.close();
      }
    } // finally

Bdx XQJ Implementation tries to auto detect resources (like expressions and results) that have not been released and to do the cleanup.

Back to the top