XQuare Binding Component (petals-binding-jdbc)
1. Purpose
The XQuare BC has a double purpose :
- JDBC data servicing
- JDBC data emission
1.1. Data Servicing Purpose
The XQuare BC Processor builds upon the XQuare Bridge library (see web site,
tutorial and reference documentation at
http://xquare.objectweb.org/ )
in order to allow users to interact with databases through its three
operations :
insert, *query* and
storedQuery.
1.2. Data Emission Purpose
The XQuare BC Listener "listens" to new data in any XQuareBC service unit's target database
and builds upon the XQuery capabilities of the companion XQuareBCJBIProcessor in
order to get them, format them as XML and send it as a message to the configured
service. The "listening" part is done by regularly looking for
"new data" as the
results of a configured SQL query.
WARNING : polling is not a best practice to integrate databases. Databases are
usually application-driven, and those applications (or their users) should drive
the "new data" lookup process. This implementation is provided as fitting the most
generic needs.
2. Data Servicing Operations detail
2.1. insert
The
"insert" operation lets the user provide as the content of an
incoming JBI message an XML document defining insertion or update of
database records according to the configured XQuare mapping (mapping
XML file and insertion XML schema file). Note that updating existing
data or adding new records are both possible. Look at the XQuare
Bridge reference documentation for more details. The content of the
response is (if no fault because of an internal exception)
the single tag "success".
2.2. query
The
"query" operation lets the user provide as the content of an
incoming JBI message an XQuery wrapped within the "query" top tag.
This XQuery must be XQuare compliant and consistent with the
configured database and mapping for the targeted service. It should
also be XML encoded (even if the parser tries to be nice by formatting
and including XML subnodes) - typically the results formatting should
be, since they comprise XML tags. The response is an XML document
whose top tag is "Results" and whose elements are specified by
the XQuery's results formatting part. Note that modules (akin to
XML / SQL views, defined in ".mod" files provided in the service
unit's deployment directory) can be imported and used in such
queries. Look at the XQuare XQuery reference documentation for
more details.
There is a way to
specify the top tag in the query : by writing
it down in xquery and using a
service configured with the queryResults.wrapInRootTag at false. Ex.
<query><result>{for $i in collection("item")/item return $i}</result></query>
will return :
<result><item><id>0</i><label>jean</label></item>...</result>
2.3. storedQuery
The
"storedQuery" operation lets the user provide as the content of
an incoming JBI message the id of the stored parameterized query
to be executed and the value of its parameters. Concretely it must
consist in the "storedQuery" top tag with the "id" attribute and
zero or more subtags with "name" and "value" attributes. Thoses
"names" must be consistent with the parameters defined within the
XQuery code of the stored query (see examples), since the "parameter"
mechanism of XQuare / XQuery is used by the processor. Otherwise
it is similar to the "query" operation in its behaviour.
3. Data Servicing Configuration
3.1. Since petals-bc-xquare 1.3
3.1.1 Global database configuration
The target database is configured through the keyvalue extension
provided by a given service unit and uses the following nodes :
- database/url : the JDBC URL of the targeted database. Required for accessing the database through JDBC. Ex. jdbc:mysql://localhost/petals_samples_xquare_auction
- database/user : the user required by the JDBC connection. Required for accessing the database through JDBC. Ex. petals_samples
- database/password : the password required by the JDBC connection. Required for accessing the database through JDBC. Ex. petals_samples
- jndidatasource/name : if provided, is used as the preferred way to access the target database. Note that the given JNDI name must exist in the Petals context and target a J2EE Datasource Ex. jdbc/myDS
Sample :
<database>
<url>jdbc:mysql://localhost/petals_samples_xquare_auction</url>
<user>petals_samples</user>
<password>petals_samples</password>
</database>
<jndidatasource>
<name>jdbc/myDS</name>
</jndidatasource>
3.1.2. Additional properties for configuring XQuare Bridge :
- database/mapping : the name of the XQuare mapping file to be found in the service unit deployment directory Required. Ex. auction.map
- queryResults/wrapInRootTag : whether to always wrap the query results in a top "" tag. If set to false, single results won't be wrapped.
- xmlconnection/baseuri : The base URI where to find modules (.mod files) to import if such are specified in user or stored queries. Optional, defaults to the service unit's deployment directory
- (not a property per se) The schema definition of insertion XML documents must be provided in the service unit's deployment directory, with the same prefix than the corresponding mapping file (ex. auction.xsd).
Sample :
<database>
<mapping>auction.map</mapping>
</database>
<queryResults>
<wrapInRootTag>false</wrapInRootTag>
</queryResults>
<xmlconnection>
<baseuri></baseuri>
</xmlconnection>
3.1.3. Configuring stored queries :
Stored queries must be defined in a tag <storedQuery id="x">.
The query id is a String and is its XQuery definition. Note that parameters are
implicitly defined using the corresponding XQuare / XQuery concept.
Sample :
<storedQueries>
<storedQuery id="0"><![CDATA[
declare variable $var as xs:string external
<result> {
for $i in collection("items")/items
where contains($i/description, $var)
return $i
} </result>]]>
</storedQuery>
</storedQueries>
3.2. Before petals-bc-xquare 1.3
3.2.1. Global database configuration
The target database is configured through the .properties file
provided by a given service unit and uses the following properties :
- database.url : the JDBC URL of the targeted database. Required for accessing the database through JDBC. Ex. jdbc:mysql://localhost/petals_samples_xquare_auction
- database.user : the user required by the JDBC connection. Required for accessing the database through JDBC. Ex. petals_samples
- database.password : the password required by the JDBC connection. Required for accessing the database through JDBC. Ex. petals_samples
- jndidatasource.name : if provided, is used as the preferred way to access the target database. Note that the given JNDI name must exist in the Petals context and target a J2EE Datasource Ex. jdbc/myDS
3.2.2. Additional properties for configuring XQuare Bridge :
- database.mapping : the name of the XQuare mapping file to be found in the service unit deployment directory Required. Ex. auction.map
- queryResults.wrapInRootTag : whether to always wrap the query results in a top "" tag. If set to false, single results won't be wrapped.
- xmlconnection.baseuri : The base URI where to find modules (.mod files) to import if such are specified in user or stored queries. Optional, defaults to the service unit's deployment directory
- (not a property per se) The schema definition of insertion XML documents must be provided in the service unit's deployment directory, with the same prefix than the corresponding mapping file (ex. auction.xsd).
3.2.3. Configuring stored queries :
Stored queries must be defined as a property whose name is
"storedQuery_" followed by the query id (must be a String), and
whose value is its XQuery definition. Note that parameters are
implicitly defined using the corresponding XQuare / XQuery concept.
See examples. Ex. "storedQuery_0"
4. Data Emission Features
4.1. What it does and how it works
This default implementation identifies "new data" by a given field that must be
incremental - that is, be different and always greated in newly inserted records.
The usual case for it is being a record identifier or primary key, be it works
well with other kind of fields as well, like timestamps.
Concretely, it executes
the configured "oldDataDelimiterSelect" to get the old "new data delimiting value",
then it executes the configured "newDataDelimiterSelect" to get the new "new data
delimiting value" as available in the actual data. If they are different,
the configured XQuery is then executed through the XQuareBCJBIProcessor and its
results formatted as an XML document and sent as a JBI message to the configured
JBI service. Finally the "old data delimiting value" is updated to the new one.
4.2. Notes
This requires
a new table to be added to the target database, that will contain
a single record with a single field being the last seen "maximum data delimiting
value". This table may start empty, in which case the "initDataDelimiter" will be
used the first time.
Before executing the XQuery, in its code the $$OLD_DATA_DELIMITER$$ and
$$NEW_DATA_DELIMITER$$ expressions are replaced by the values found in the
preceding executions of "oldDataDelimiterSelect" and "newDataDelimiterSelect".
WARNING xwiki can't display them, but those tokens use actually sharps instead of dollar characters.
Many such listeners may be deployed in different service units to listen
to different kinds of "new data" in the same database. Each one must have its own additional table.
Since it uses the XQuareBCJBIProcessor's "query" capabilities, look at its
documentation for more details on how it behaves.
4.3. Configuration
The datasource to the target database and the XQuareBCJBIProcessor's XQuery
capabilities are configured through the XQuareBCJBIProcessor (look at its
javadoc for details).
4.3.1 Since petals-bc-xquare 1.3
The configuration specific to this listener is configured in the jbi.xml provided by a given service unit, and uses the following additional nodes :
- newdatalistener/service : The fully qualified name of the service to which the new data messages will be sent. Ex.
- newdatalistener/operation : This service's operation. Ex. sayHello
- newdatalistener/delimiter/oldDataDelimiterSelect : An SQL query that must return the single value of the saved, old data delimiter. Ex.
select max(bid_date) from bids_xqbc
- newdatalistener/delimiter/newDataDelimiterSelect : An SQL query that must return the single value of the current "new data" delimiter. Ex.
select max(bid_date) from bids
- newdatalistener/delimiter/initDataDelimiter : The new data delimiter initial value if none in its own table and field. Ex. 1970-01-01 or merely 0
- newdatalistener/delimiter/newDataDelimiterUpdates : An SQL insert that must update the value of the "new data" delimiter from "old" to "new". Note that the $$NEW_DATA_DELIMITER$$ expression is replaced within the SQL code before its execution. Ex.
delete from bids_xqbc;
insert into bids_xqbc (bid_date) values ("$$NEW_DATA_DELIMITER$$")
- newdatalistener/delimiter/newDataXquery : An XQuery that must return and format the current new data. Note that the $$OLD_DATA_DELIMITER$$ and $$NEW_DATA_DELIMITER$$ expressions are replaced within the SQL code before its execution. Ex.
for $i in collection("bids")/bids
where $i/bid_date > xs:date("$$OLD_DATA_DELIMITER$$") and $i/bid_date <= xs:date("$$NEW_DATA_DELIMITER$$") return
<bid>{ $i/bid_date }</bid>WARNING Note that the SQL or XQuery in the XQuareBC's jbi.xml configuration files must be in a CDATA section.
Sample :
<newdatalistener>
<service>{http://petals.objectweb.org/}HelloworldService</service>
<operation>sayHello</operation>
<delimiter>
<oldDataDelimiterSelect><![CDATA[select max(bid_date) from bids_xqbc]]></oldDataDelimiterSelect>
<newDataDelimiterSelect><![CDATA[select max(bid_date) from bids]]></newDataDelimiterSelect>
<initDataDelimiter>1970-01-01</initDataDelimiter>
<newDataDelimiterUpdates><![CDATA[
delete from bids_xqbc;
insert into bids_xqbc (bid_date) values ("$$NEW_DATA_DELIMITER$$")]]>
</newDataDelimiterUpdates>
<newDataXquery><![CDATA[
for $i in collection("bids")/bids
where $i/bid_date > xs:date("$$OLD_DATA_DELIMITER$$") and $i/bid_date <= xs:date("$$NEW_DATA_DELIMITER$$")
return <bid>{ $i/bid_date }</bid>]]>
</newDataXquery>
</delimiter>
</newdatalistener>
4.3.2 Before petals-bc-xquare 1.3
The configuration specific to this listener is configured through the same
.properties file provided by a given service unit, and uses the following additional properties :
: The fully qualified name of the service to which the new data messages will be sent. Ex.
- newdatalistener.operation : This service's operation. Ex. sayHello
- newdatalistener.delimiter.oldDataDelimiterSelect : An SQL query that must return the single value of the saved, old data delimiter. Ex.
select max(bid_date) from bids_xqbc
- newdatalistener.delimiter.newDataDelimiterSelect : An SQL query that must return the single value of the current "new data" delimiter. Ex.
select max(bid_date) from bids
- newdatalistener.delimiter.initDataDelimiter : The new data delimiter initial value if none in its own table and field. Ex. 1970-01-01 or merely 0
- newdatalistener.delimiter.newDataDelimiterUpdates : An SQL insert that must update the value of the "new data" delimiter from "old" to "new". Note that the $$NEW_DATA_DELIMITER$$ expression is replaced within the SQL code before its execution. Ex.
delete from bids_xqbc;
insert into bids_xqbc (bid_date) values ("$$NEW_DATA_DELIMITER$$")
- newdatalistener.delimiter.newDataXquery : An XQuery that must return and format the current new data. Note that the $$OLD_DATA_DELIMITER$$ and $$NEW_DATA_DELIMITER$$ expressions are replaced within the SQL code before its execution. Ex.
for $i in collection("bids")/bids
where $i/bid_date > xs:date("$$OLD_DATA_DELIMITER$$") and $i/bid_date <= xs:date("$$NEW_DATA_DELIMITER$$") return
<bid>{ $i/bid_date }</bid>WARNING Note that when specifying SQL or XQuery in the XQuareBC's .properties configuration files, new lines within a property value must be escaped using a line-ending backslash.
5. Deploying an XQuareBC service unit onto Petals
5.1. Writing its jbi.xml
5.1.1 Since petals-bc-xquare 1.3
Here is a sample jbi.xml :
<jbi version="1.0"
xmlns="http://java.sun.com/xml/ns/jbi"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:petals="http://petals.objectweb.org/"
xmlns:extensions="http://petals.objectweb.org/extensions/"
xmlns:xquare="http://petals.objectweb.org/extensions/xquare/">
<services binding-component="true">
<provides
interface-name="mySampleXquare"
service-name="petals:SampleXquareService"
endpoint-name="mySampleXquareEndpoint">
<extensions:extensions>
<extension xmlns="http://petals.objectweb.org/extensions/xquare/">
<jndidatasource>
<name>jdbc/myDS</name>
</jndidatasource>
<database>
<url>jdbc:mysql://localhost/petals_samples_xquare_auction</url>
<user>petals_samples</user>
<password>petals_samples</password>
<mapping>auction.map</mapping>
</database>
<queryResults>
<wrapInRootTag>false</wrapInRootTag>
</queryResults>
<xmlconnection>
<baseuri></baseuri>
</xmlconnection>
<storedQueries>
<storedQuery id="0"><![CDATA[
declare variable $var as xs:string external
<result> {
for $i in collection("items")/items
where contains($i/description, $var)
return $i
} </result>]]>
</storedQuery>
</storedQueries>
<newdatalistener>
<service>{http://petals.objectweb.org/}HelloworldService</service>
<operation>sayHello</operation>
<delimiter>
<oldDataDelimiterSelect><![CDATA[select max(bid_date) from bids_xqbc]]></oldDataDelimiterSelect>
<newDataDelimiterSelect><![CDATA[select max(bid_date) from bids]]></newDataDelimiterSelect>
<initDataDelimiter>1970-01-01</initDataDelimiter>
<newDataDelimiterUpdates><![CDATA[
delete from bids_xqbc;
insert into bids_xqbc (bid_date) values ("$$NEW_DATA_DELIMITER$$")]]>
</newDataDelimiterUpdates>
<newDataXquery><![CDATA[
for $i in collection("bids")/bids
where $i/bid_date > xs:date("$$OLD_DATA_DELIMITER$$") and $i/bid_date <= xs:date("$$NEW_DATA_DELIMITER$$")
return <bid>{ $i/bid_date }</bid>]]>
</newDataXquery>
</delimiter>
</newdatalistener>
</extension>
</extensions:extensions>
</provides>
</services>
</jbi>
5.1.2 Before petals-bc-xquare 1.3
The jbi.xml must mention the petals-extensions "type" specific to XQuareBC : "xquare_service" .
Here is a sample jbi.xml :
<jbi version="1.0" xmlns='http://java.sun.com/xml/ns/jbi'
xmlns:xsi='http://www.w3.org/2001/XMLSchema-instance'>
<services binding-component="true">
<consumes interface-name="foo" service-name="{namespace}fooService" endpoint-name="fooServiceEndpoint" />
<provides interface-name="mySampleXquare" service-name="{http://petals.objectweb.org/}SampleXquareService" endpoint-name="mySampleXquareEndpoint" />
<type>xquare_service</type>
</services>
</jbi>
5.2. What must be provided withing the Service Unit
- as for any JBI component, META-INF/jbi.xml
- the .wsdl file describing the provided JBI service
- before petals-bc-xquare 1.3 : the .properties file configuring the XQuareBC SU (see reference above)
- the .map file configuring XQuare's XML to SQL mapping (this file must be specified in the .properties file)
- and its .xsd XML schema file
- any .mod file whose XQuery functions (describing "views" on available data) have to be provided to XQuare for this Service Unit
5.3. Sample
See attached file "myxquare.zip".
It binds with the XQuare sample "auction" database, which must be provided by a MySQL server. The data base schema is provided in the XQuareBC tests source code. It emits new bids according to their date and target them to the HelloworldService (which must be deployed).
sample SA
sample sql
sample xqbc sql
5.4 Using another database engine than MySQL
The MySQL driver is packaged within the standard release of the XQuareBC component.
In order to support other database engines (among those supported by XQuare), their drivers must be included in the component .zip package and added to the component classpath within its jbi.xml .