1. Trang chủ
  2. » Công Nghệ Thông Tin

Professional XML Databases phần 8 doc

84 195 0

Đang tải... (xem toàn văn)

Tài liệu hạn chế xem trước, để xem đầy đủ mời bạn chọn Tải xuống

THÔNG TIN TÀI LIỆU

Thông tin cơ bản

Định dạng
Số trang 84
Dung lượng 0,95 MB

Các công cụ chuyển đổi và chỉnh sửa cho tài liệu này

Nội dung

How XML Enhances JDBC and vice versa When you combine XML with J2EE Java 2, Enterprise Edition technologies and standard Internetprotocols such as HTTP, you can write enterprise applicat

Trang 1

XPath oddities like this compel us to recommend against the use of long paths like A/B in predicates.Most likely, the meaning you wanted is actually a nested predicate like

/Order[Product[@UnitPrice > 10]] anyway

Because SQL XML does not support positional predicates, it uses "any" semantics for both of theseXPaths That is, both /Order[0 + Product/@UnitPrice > 10] and

/Order[Product/@UnitPrice > 10] produce the same XML result in SQL XML

This deviation from the W3C standard also applies to relational and equality operators These operatorsapply special conversion rules to their operands that we will not explain in detail here For example, anexpression @Date > '1998-10-01' should first convert both the nodeset @Date and the string'1998-10-01' to number (which will result in NaN), and then compare them (which will result infalse, since NaN compared with anything is false) SQL XML instead performs a string comparison,with the expected result (true if and only if the value of @Date is a date later than the one indicated inthe string)

Here's an XPath that attempts string and date comparisons These would not work in ordinary XMLdocuments, but do work in SQL XML:

/Customer[@CustomerID > 'PARIS']/Order[@OrderDate <= '1999-01-01']

which results in the XML

<Order OrderID="10322" OrderDate="1996-10-04">

<Product ProductID="P52" UnitPrice="7.0000" Units="38"/>

</Order>

<Order OrderID="10354" OrderDate="1996-11-14">

<Product ProductID="P1" UnitPrice="18.0000" Units="39"/>

<Product ProductID="P29" UnitPrice="123.7900" Units="0"/>

</Order>

<Order OrderID="10474" OrderDate="1997-03-13">

<Product ProductID="P14" UnitPrice="23.2500" Units="35"/>

<Product ProductID="P28" UnitPrice="45.6000" Units="26"/>

<Product ProductID="P40" UnitPrice="18.4000" Units="123"/>

<Product ProductID="P75" UnitPrice="7.7500" Units="125"/>

</Order>

<! >

At the time of this writing, none of the XPath string functions (concat(), substring(), etc.) aresupported Microsoft has announced intentions to support these functions in the near future

XPath and the XML View

XPath works by translating the XPath into an equivalent FOR XML EXPLICIT query During thistranslation process, XPath makes use of the many annotations provided in the XML View

XPath applies join relationships when navigating from one node to another If the nodes are joined inthe schema, then the join relationship will be used in the SQL query Predicates correspond to existencetests (WHERE EXISTS)

Trang 2

Nodes that have an id-prefix are converted to string, and then the prefix is prepended to the value Notethat this prevents using those values as numbers in the XPath For example,

/Product[@ProductID=11] is an error; the correct XPath uses the id prefix:

/Product[@ProductID='P11']

In many cases, key information is required to correctly order and nest the resulting XML If an XPathquery seems to be returning odd results, or returns a FOR XML EXPLICIT error, the problem may bethat the schema is missing sql:key-fields Read the section about this annotation for instructions onits use

Finally, XPath queries must perform many data conversions XPath translates first from the SQL type tothe XDR type, and then from the XDR type to the XPath type This means that specifying XDR andSQL types in the schema can help eliminate unnecessary conversions When the query converts acolumn used as an index (for example, /Customer[@CustomerID='ALFKI']), eliminating theunnecessary conversion can result in a ten-fold performance improvement of the XPath query

Default Schema

XPath works best with an XML View, but can work without any schema at all – with some restrictions.These restrictions (names, flat hierarchy) are the same restrictions as on the default mapping used by an

XML View (See the earlier section, "The Default Mapping," for details.)

In addition, an XPath with no XML View must select the value of a single column from a single row.Because there is no schema to describe how the XML should be shaped, the XPath cannot return XML.The default schema can be especially convenient for so called "direct object" queries that use an XPath-like syntax to access objects in the database For example, the XPath

/Customers[@CustomerID='ALFKI']/@ContactName

is exactly the same as the SQL query

SELECT ContactName FROM Customers WHERE CustomerID='ALFKI'

XPath Parameters

XPath parameters are prefixed with the dollar-sign symbol (for example, $param) SQL XML supportsonly string-valued parameters, but this presents no great difficulties Parameters can be shared amongother queries in a template For example, the following template selects the Customer element with the

id parameter value that was passed to the template (which defaults to "ALFKI"):

Trang 3

Additional XPath Axes

XPath is not limited to top-down navigation (from an element to its children and attributes) XPath has arich set of navigation axes, including namespaces, descendants, ancestors, and so on However, at thetime of this writing, SQL XML supports only four axes: child, attribute, parent, and self Inparticular, the popular descendant-or-self shortcut "//" is not supported

All four of these have abbreviated forms that are more commonly used For the child and attributeaxes, we've seen that the abbreviations have the form child or @attribute, respectively For

parent, the short form is two dots ( ) and one dot (.) is the short form for self Thus, the XPath/Customer/Order[ /@CustomerID='ALFKI']

is equivalent to the XPath

The abbreviation is short for parent::node() and the abbreviation is short for self::node()

So the XPath above that uses could also be rewritten as:

/child::Customer/child::Order[parent::node()/attribute::CustomerID='ALFKI']

Updategrams

At this time, there is no W3C standard for updating XML documents Updategrams attempt to fill thisvoid by specifying a standard XML-based language for inserting, updating, and deleting XML data.Updategrams are declarative You describe what the XML currently is and what you want it to become,and the updategram takes care of all the details necessary to make it so Updategrams use the

namespace URI urn:schemas-microsoft-com:xml-updategram, which we will always assign tothe prefix u

In SQL Server 2000, updategram queries are executed through templates Each updategram uses anXML View of the database to determine the SQL query that is required to perform the update

NOTE: Updategrams require the latest SQL XML web release from MSDN, or SQL

Server 2000 SP1 or later The examples in this section are not compatible with the

early beta version of updategrams that was released for SQL Server 2000 beta 2.

Trang 4

Every updategram consists of one <u:sync> element, corresponding to one database transaction Thetransaction is described by a sequence of <u:before> and <u:after> pairs Every <before> musthave a matching <after>, and vice-versa; if one is missing, then it is equivalent to one with emptycontent The contents of the <before> element are compared with the contents of its matching

<after> element to determine whether an INSERT, UPDATE, or DELETE is required

To avoid conflicts between multiple, concurrent queries, updategrams employ "optimistic concurrencycontrol" If the current state of the database does not match the XML described in the <before>element, then the transaction will not be committed, and no change will be made Depending on howspecific the <before> element is, the synchronization will effectively range from none at all ("updatealways") to total synchronization ("update only if the row has not changed at all")

To demonstrate updategrams, let's create a table:

CREATE TABLE FictionalCharacters

(cid nvarchar(10) PRIMARY KEY, FirstName nvarchar(40), LastName nvarchar(40))

We now use the following schema, ch15_ex21.xdr, for mapping the table:

<Schema xmlns="urn:schemas-microsoft-com:xml-data"

xmlns:dt="urn:schemas-microsoft-com:datatypes"

xmlns:sql="urn:schemas-microsoft-com:xml-sql">

<ElementType name="First" content="textOnly" />

<ElementType name="Last" content="textOnly" />

<ElementType name="Person" sql:relation="FictionalCharacters"

sql:key-fields="cid">

<AttributeType name="ID" dt:type="id"/>

<attribute type="ID" sql:field="cid"/>

<element type="First" sql:field="FirstName"/>

<element type="Last" sql:field="LastName"/>

Trang 5

The result of executing this template, if the updategram succeeds, will be

We can now update this row, using this updategram (ch15_ex22a.xml):

especially NULL

Trang 6

Values, Absence and NULL

Up until now, we've said that absence of XML data is equivalent to a SQL NULL value, and vice-versa.Unfortunately, this equivalence presents a problem for an updategram, because optimistic concurrencycontrol applies only to the values in the before element If the value was NULL, it would be absent, andthus would not figure into the equation (even though we might not want to perform the update or delete

if the value has changed away from NULL) Therefore, updategrams need a way to explicitly differentiateNULL values from absent ones

Updategrams allow the user to specify a string value that will be used in the XML in place of a SQLNULL Whenever an XML value is equal to this string, the string is replaced with NULL in the equivalentSQL query The string is specified with the attribute u:nullvalue on the <u:sync> element or

This updategram will commit only if the FirstName is still NULL

Note that when evaluating the value of an element, updategrams don't use the usual definition of stringvalue In XPath syntax, string(element) usually takes all the text node descendants of the elementand concatenates them together in document order, which is equivalent to the XPath

string(element//text()) Updategrams use only the text nodes that are immediate children of theelement, equivalent to the XPath string(element/text()) When the string value of the elementmatches the u:nullvalue, NULL is substituted in its place

Also, updategrams are aware of XDR default That is, when an element or attribute value is absent,updategrams use the default value (if given) in the annotated XDR schema The default is indicated inthe schema on an <AttributeType> or <ElementType> using the default attribute When there is

no default value, no value is used for the absent element or attribute

Trang 7

Insert/Update/Delete Heuristics

Now that you understand how an updategram extracts the XML values out of the before and afterelements and how it handles absence and default values, the only remaining piece of the puzzle isdetermining which values in the after element correspond to which values in the before element.Once this matching has been performed, the updategram knows which rows to update, which to delete,and which to insert, and can create the corresponding SQL query to perform that work

An updategram matches elements based on an element key This key can be specified in the annotatedschema using sql:key-fields, or it can be specified in the updategram using the u:id annotation Ifthe u:id method is chosen, then it must be used everywhere in the updategram

As an example, consider the following updategram (ch15_ex24.xml):

<Person u:id="forty-two" ID="HGTTG42"/>

<Person u:id="fifty-four" ID="HGTTG54"/>

</u:before>

<u:after>

<Person u:id="fifty-four" ID="54"/>

<Person u:id="forty-two" ID="42"/>

</u:after>

</u:sync>

Trang 8

This updategram needs to change the value of the key itself The only way to do this is to identify theelements using u:id The values used for u:id are arbitrary; they are used only for matching elements

in the updategram, and will not be inserted into the database: as a result, this updategram will not work

Of course, u:id is not limited to key changes; it can be used any time

Parameters

Updategrams use parameters exactly like XPath does, and with a similar syntax Anywhere an

updategram contains the dollar-sign ($) followed by the name of a parameter, the parameter value will

Default Schema

We previously described the subset of XPath that can be executed without a schema Updategrams canalso use a default mapping, with some restrictions These restrictions (names, flat hierarchy) are similar

to the default mapping used by an XML View (See the earlier section, "The Default Mapping," for details).

In addition, updategrams cannot work with any of the SQL types binary, image, ntext, text, orvarbinary in the <before> element and binary, image, or varbinary in the <after> element.Values that map to monetary SQL types (money and smallmoney) must be preceded with a currencysymbol such as $; conversely, values preceded with a currency symbol cannot be inserted, updated, ordeleted from any string type column in the database (char, nvarchar, etc.)

Trang 9

Also, the generated value can be returned as part of the template result by using the u:returnidattribute on the u:after element For example, the template

Data Types

All values that map to any of the SQL types binary, image, ntext, text, or varbinary must bemarked in the schema as having that sql:datatype Otherwise, the updategram will not be able togenerate a valid SQL query Similarly, both monetary types (money, smallmoney) must be marked ashaving one of the XDR numeric types to be properly used, even though you could still have an attributetype unitprice, without either datatype

The XDR binary types bin.hex and bin.base64 are used when decoding binary values Binaryvalues cannot be referred to using a dbobject URL (as generated by sql:url-encode)

If an attribute or element has a sql:id-prefix in the schema, then that prefix will be stripped out ofthe value in the updategram

Trang 10

Advanced Topics

Namespaces and External Schemas

Most uses of XML require namespaces, whether some externally defined namespace or your owncustom one There are two central concepts required when using namespaces in XML Views:

namespace declarations and the sql:target-namespace annotation

Recall that namespace declarations come in two forms, xmlns="uri" and xmlns:prefix="uri", andare inherited of the descendants of the element where they were declared Namespace URIs are

commonly overloaded for many different purposes – versioning (like the XSL namespaces) and actualURLs (that you can visit on the Web) are just two examples For XML Views, there are three kinds ofnamespace URIs worth mentioning

First, there are the four special namespace URIs corresponding to XDR and SQL XML (all of whichbegin with urn:schemas-microsoft-com:, followed by one of xml-data, datatypes, xml-sql,

or xml-updategram) that identify schema contents or annotations, respectively Second, there are

external schema references, which we will explain next And finally, everything else – which are treated

as ordinary namespace names

External schema references are distinguished from ordinary namespace URIs by beginning with thestring x-schema: Every such namespace URI is treated as a reference to a schema at the file locationlisted after the colon The external schema will be loaded, and all its ElementType and

AttributeType declarations made available to the schema that imported it (and in fact, all of theschemas currently being processed)

The following two schemas demonstrate the concept:

<! ch15_ex27.xdr >

<Schema xmlns="urn:schemas-microsoft-com:xml-data"

xmlns:sql="urn:schemas-microsoft-com:xml-sql">

<ElementType name="Customer" sql:relation="Customers">

<element type="x:Order" xmlns:x="x-schema:ch15_ex28.xdr">

<sql:relationship key-relation="Customers" key="CustomerID"

foreign-relation="Orders" foreign-key="CustomerID" />

</element>

</ElementType>

</Schema>

Trang 11

<Order CustomerID="ALFKI" OrderID=""/>

<Order CustomerID="ALFKI" OrderID=""/>

<Order CustomerID="ALFKI" OrderID=""/>

</Customer>

<Customer>

<Order CustomerID="ANATR" OrderID=""/>

<Order CustomerID="ANATR" OrderID=""/>

</Customer>

<! >

exactly as if there had been only one schema

The second part of using namespaces in XML Views is the sql:target-namespace annotation Thesql:target-namespace annotation is used on the Schema element, and declares that all the top-leveldeclarations in the schema will go into that namespace URI This annotation can be used on a schema

by itself; but it is most commonly used in conjunction with external schemas, creating a web of schemas,one for each namespace URI

If we modify the second schema above to use a target namespace:

<y:Order xmlns:y="your namespace" CustomerID="ALFKI" OrderID=""/>

<y:Order xmlns:y="your namespace" CustomerID="ALFKI" OrderID=""/>

<y:Order xmlns:y="your namespace" CustomerID="ALFKI" OrderID=""/>

</Customer>

<Customer>

<y:Order xmlns:y="your namespace" CustomerID="ANATR" OrderID=""/>

<y:Order xmlns:y="your namespace" CustomerID="ANATR" OrderID=""/>

</Customer>

<! >

Trang 12

Note that the prefix used in the schema is not necessarily preserved in the XML result Also note that,although the Order element is placed into a namespace, none of its attributes are This is consistentwith the normal interaction between attributes and namespace declarations If you require an attribute

to be placed in the target namespace, declare it at the top-level of the schema

We should note that the use of namespaces in XPath is currently limited to templates XPath usesnamespace prefixes, so it requires those prefixes to be bound to namespace URIs Currently SQL Serverdoes not provide a way to perform this binding in a URL, so the binding must occur in XML (usingordinary namespace declarations)

Structural Recursion

Unfortunately, XML Views currently do not directly support recursion The reason is that creatingrecursive hierarchies usingFOR XML EXPLICIT (which XPath uses) requires advance knowledge of thedepth of the hierarchy to construct the query This problem is demonstrated by the SQL query

FROM Employees E1 JOIN Employees E2 ON E1.EmployeeID = E2.ReportsTo

WHERE E1.ReportsTo = NULL

FROM Employees E1 JOIN Employees E2 ON E1.EmployeeID = E2.ReportsTo

JOIN Employees E3 ON E2.EmployeeID = E3.ReportsToWHERE E1.ReportsTo = NULL

ORDER BY 3, 4, 5FOR XML EXPLICIT

This limitation of XML Views prevents the use of recursive schemas like:

Trang 13

because the EXPLICIT query needed is data-dependent Until XML Views provides explicit support forrecursion, an alternative method is required.

The natural first attempt, an almost-recursive schema like the one below, also does not work Let's look

at this to see why:

<! This schema will not work! >

The problem with this schema is that the join relationship from the table to itself, a so-called self-join, is

also not supported by XML Views at the time of this writing

However, all is not lost! Using a little imagination, it is possible to create recursive hierarchies Onesolution is to alias the table using a SQL view, then use that view in the annotated schema The

following example demonstrates this technique using the Employees table in the Northwind database.First, prepare a SQL view that mirrors the Employees table:

CREATE VIEW Managers AS SELECT * FROM Employees

Then, use the SQL view in the schema (ch15_ex31.xdr):

Trang 14

Updategrams, XPaths, and ordinary SQL queries can be executed from XML templates, and the resultsfrom these queries substituted into the XML template Combined with other standard XML processingtechniques (such as XSL), these query languages provide a powerful way to transport and present XMLdata on the Web.

Trang 17

If you are an enterprise Java developer who specializes in writing database applications using the JDBCAPI, you have probably had to confront the thorny issue of extending your applications to today'spervasive computing environment Nowadays, people expect to be able to access mission-critical dataanytime, anywhere, and from any device, regardless of what data access API is being used to

manipulate the underlying data source The challenge of the enterprise Java developer is to create JDBCapplications that allow platform-neutral, device-independent access to data By XML-enabling yourJDBC applications, you can accomplish this Here is the good news; it's easier than you might think

How XML Enhances JDBC (and vice versa)

When you combine XML with J2EE (Java 2, Enterprise Edition) technologies and standard Internetprotocols (such as HTTP), you can write enterprise applications that provide universal data access toJDBC data sources with a minimal amount of coding With XML, XSLT, and JDBC, you can designscalable and extensible architectures that facilitate device-independent data delivery in J2EE

applications This allows end users to access your data using web browsers, WAP devices, PDAs, or anyother current or future device that renders content using an XML-based markup language

Moreover, combining XML and JDBC facilitates the creation of web services using J2EE Web services

are HTTP applications that provide an application programming interface rather than a user interface With

web services, your trading partners can integrate your business processes and data with their

applications, regardless of which hardware platform and operating system they are built on, or

programming language that they are written in

Trang 18

This chapter will give you some practical, hand-on examples of how to integrate XML with JDBC inyour J2EE applications in a manner that facilitates device-and-platform independent universal dataaccess in today's pervasive computing environment Specifically, it will cover two scenarios:

Generating XML from a JDBC data source: We will walk through the construction of a simpleXML gateway architecture for JDBC This architecture contains software components thatallow you to execute SQL statements against arbitrary JDBC data sources, returning the resultsets as well-formed XML data structures that can then be consumed by any application withXML parsing capabilities Next, we will show you how to add server-side XSLT processingcapabilities to this architecture to illustrate how easy it is to transform the XML-serializedJDBC result set, to a mark-up language that targets a particular device, such as a web browser

Using XML to update a JDBC data source: In this scenario, we will show you how to use

WebRowSets, an emerging Java technology, to create distributed JDBC applications that useXML to marshal disconnected Result sets between remote machines Please note that, as ofthis writing, the WebRowSet binaries are still in "early access" status, and could change

slightly before becoming part of the core API

Software Needed for This Chapter

Before getting started, you should make sure that you install and configure the core software needed towork through the examples provided in the chapter This software includes JDK 1.3, the Xalan XSLTprocessor for Java, Tomcat 3.1, and a relational database system with a JDBC driver For the most part,the code samples in this chapter will compile and run on virtually any system for which a reasonableimplementation of the Java virtual machine has been ported Since we developed and tested thesesamples on Windows NT 4.0, most of the examples in this chapter are NT-centric

JDK 1.3

The first piece of software needed is JDK 1.3 You can download this free of charge from

http://java.sun.com When you download it, ensure that you select the correct installer for the operatingsystem you are using If you are using NT, for example, you will download and run the InstallShieldself-extracting setup program I also recommend that you download the JDK documentation, which isavailable as a separate download While you can browse this documentation on Sun's Java web site, youwill find it infinitely more convenient to have it available on your local file system

One point of clarification: while we recommend JDK 1.3, we have also tested the code in this chapter

on JDK 1.2.2 This is important because JDK 1.3 has not been ported to as many platforms as theubiquitous JDK 1.2.2 One word of caution: if you do decide to use JDK 1.2.2, make sure you downloadthe JNDI (Java Naming and Directory Interface) reference implementation The WebRowSet examplescovered later require JNDI While JDK 1.3 includes JNDI, JDK 1.2.2 does not, and you must add this as

a separate download We will discuss this in more detail later in the chapter

Xalan XSLT Processor for Java

The next piece of software we will use is Xalan for Java version 1.2 Xalan is an open-source XSLTprocessor that is maintained by the Apache Group You can download it from http://xml.apache.org.After downloading and unpacking the xalan-j_1_2_D02.zip archive, locate the xalan.jar andxerces.jar (the Xerces XML parser) archives and copy them to the \jdk1.3\lib directory

Trang 19

If you don't want to use Xalan, or you would like to try another XSLT processor, there are severalquality XSLT processors implemented in Java Examples include:

❑ IBM LotusXSL (http://alphaworks.ibm.com/tech/LotusXSL)

❑ James Clark's XT package (http://www.jclark.com/xml/xt.html)

Software Needed to Implement Rowsets

To run the sample distributed JDBC application, you'll need to download the Java packages used toimplement the WebRowSet framework This framework provides a transparent mechanism for

serializing the data, metadata, and properties of a JDBC result set to XML for transportation andmanipulation by a remote application across the network We will cover this framework in more detaillater The packages needed to use the WebRowSet framework include the sun.jdbc.rowset andjavax.sql packages, and the JNDI reference implementation We'll cover the framework in moredetail later; for now, just follow the instructions below to download and install the software

The sun.jdbc.rowset Package

To download this package, point your browser at:

http://developer.java.sun.com/developer/earlyAccess/crs/ This is "early access" technology, so youmust create a free account with the Sun Java Developer Connection if you haven't already done so Thesamples in this chapter have been tested with the "early access 4" release Once you have downloadedthe rowset-1_0-ea4.zip archive, locate the rowset.jar file and place it in the C:\jdk1.3\libdirectory

The WebRowSet implementation contained in this package is an experimental,

unsupported technology Therefore, it may change before it becomes an official part of

the Java platform Please do not use this technology in a production application until

it is released as a final, stable product.

The javax.sql Package

The JDBC 2.0 API includes two packages: java.sql, which contains the JDBC 2.0 core API, andjavax.sql, which contains the JDBC 2.0 standard extension API The java.sql package is includedwith the JDK, so it should already be on your system Since the WebRowSet class uses the JDBC 2.0standard extension API, we'll need the javax.sql package, which is provided as a separate download

To download this package, point your browser at http://java.sun.com/products/jdbc/download.html,and select the JDBC 2.0 Optional Package Binary Download the jdbc2_0-stdext.jar archive, andplace it in the C:\jdk1.3\lib directory

The JNDI Reference Implementation

The WebRowSet class uses JNDI (Java Naming and Directory Interface) If you installed JDK version1.3, you can skip this step JDK 1.3 ships with JNDI If you are using JDK 1.2.2, you must download theJNDI reference implementation from Sun's web site To do so, point your browser at

http://java.sun.com/products/jndi/index.html Download the jndi1_2_1.zip archive and unpack it;locate the jndi.jar file, and place it in your CLASSPATH

Trang 20

Tomcat 3.1

Since all of the sample applications covered in this chapter are implemented at least in part using theJava servlet API, you will need to install and configure a servlet container on your system The

examples provided should work in any servlet container that supports the Java servlet API version 2.2

or higher We recommend Tomcat 3.1, the open-source servlet and JSP reference implementationdeveloped by the Apache Software Foundation This is a lightweight, high performance servlet

container that is easy-to-use, implements the standard religiously (it is, after all, the reference

implementation), and includes a lightweight HTTP listener that eliminates the need to install a separateweb server To qualify this comment, the HTTP listener is useful for unit-testing applications In aproduction environment, you should use a commercial-quality web server with the appropriateconnector Tomcat provides connectors for Apache, IIS, and Netscape/iPlanet Enterprise Server Since

it is implemented in Java, Tomcat will run on a variety of different platforms Here are the installationsteps for Windows NT 4.0:

❑ Download jakarta-tomcat.zip from http://jakarta.apache.org

❑ Install it by unpacking the zip archive into a directory on your hard drive

❑ Modify the jakarta-tomcat\bin\tomcat.bat file to point the JAVA_HOME variable to thedirectory in which you installed JDK 1.3 This variable assignment does not exist in the batchfile, so you will need to add it For example, if you installed the JDK on the C drive, add thisvariable assignment to the file: set JAVA_HOME=C:\jdk1.3

❑ You also want to change the jakarta-tomcat\bin\tomcat.bat file to add the rowset,JDBC standard extensions, Xerces, and Xalan code base to Tomcat's CLASSPATH To do so,insert the following code on or about line 35 of tomcat.bat (this assumes that you put theJAR files, as recommended, in the jdk1.3\lib directory):

rem This is an existing line in the batch file Look for it to find

rem the right spot to add your additional JARs to the CLASSPATH:

set CLASSPATH=%CLASSPATH%;%JAVA_HOME%\lib\tools.jar

rem Start adding your additional jars here:

set CLASSPATH=%CLASSPATH%;%JAVA_HOME%\lib\rowset.jar

set CLASSPATH=%CLASSPATH%;%JAVA_HOME%\lib\jdbc2_0-stdext.jar

set CLASSPATH=%CLASSPATH%;%JAVA_HOME%\lib\xerces.jar

set CLASSPATH=%CLASSPATH%;%JAVA_HOME%\lib\xalan.jar

❑ Run the jakarta-tomcat\bin\startup.bat to start Tomcat

❑ Point your browser to http://127.0.0.1:8080 By default, Tomcat's HTTP server listens on port

8080 to preclude any conflict with a web server that might already be installed on your systemand listening on port 80 Of course, you can change the port assignment, if desired, by editingthe server.xml configuration file (see the Tomcat documentation for more details) Whenyou hit this URL, you will see the Tomcat home page

If you are using a UNIX variant, the installation and configuration steps are similar, with a few keydifferences Instead of downloading the ZIP archive, you want to download and unpack the tararchive In addition, you will need to modify the tomcat.sh UNIX shell script instead of the

tomcat.bat batch file Refer to the Tomcat documentation for additional information

Trang 21

At the end of the chapter, we will cover all of the steps required to package our sample applications fordeployment to Tomcat or any other J2EE-compliant servlet container In the meantime, you might want

to download the web application archive provided with the sample code for this chapter from our website; details on how to get all of the code for this book is supplied in the support and errata appendix.This will allow you to test the examples while you are going through the chapter To do so, followthese steps:

❑ If Tomcat is already running, stop it using the shutdown.bat batch file located in the

In addition to the HTML and the compiled binaries, this archive also includes all of the source codediscussed in this chapter

A JDBC Data Source and Driver (Oracle, SQL Server, etc.)

Finally, you will need to have access to a database with a JDBC driver The examples are writtengenerically enough to work with a variety of different relational database products Most databaseproducts on the market today include a JDBC driver The three that we will use in this chapter areOracle 8i via the Oracle thin JDBC driver, and Microsoft SQL Server 7.0 and Microsoft Access 97, bothvia the JDBC-ODBC Bridge

Trang 22

The Oracle JDBC driver is typically packaged in a file called classes111.zip This file comes withany Oracle installation, so your Oracle database administrator will be able to provide it for you Youcan also download it from http://www.oracle.com The JDBC-ODBC Bridge ships with the JDK.

To preclude any problems from occurring, you want to ensure that the JDBC driver you will use isadded to the CLASSPATH If you are using the JDBC-ODBC Bridge, this was taken care of when youinstalled the JDK, so you don't need to worry about it If your database does not have a JDBC driver(or you are unsure), you can simply use the JDBC-ODBC Bridge (assuming that the database productprovides an ODBC driver, as most do) Please consult your specific database product's documentationfor more information

Generating XML from JDBC

As we touched on earlier, XML and JDBC complement each other very well Using these two

technologies, you can create "universal data access" applications that can run on a variety of differentJ2EE-compliant application servers and access a variety of different data sources It gives you the best ofall worlds The use of XML allows you to make your data and metadata available to virtually anyapplication, regardless of how it was written or the type of platform on which it runs The use of Javaand the J2EE APIs gives the application developer platform and vendor freedom of choice; a variety ofdifferent vendors have created J2EE-compliant application servers that run on a variety of differenthardware and OS combinations A short list includes ATG, BEA Systems, IBM, and the iPlanet Sun-Netscape Alliance The use of JDBC as the data access API allows you to leverage decades worth ofrelational data technology and thought leadership

The challenge, then, is to create an architecture that allows you to extract data from a JDBC datasource, serialize it to XML, and send it to the requesting client, using XSLT as appropriate to createoutput that targets a particular device For extensibility purposes, this architecture should be designed in

a manner that abstracts the process of accessing the data source via JDBC and serializing the Result set

as XML, thereby shielding the application developer from these details, and promoting code reuse Toillustrate this, we will create a simple XML gateway architecture for JDBC

Our Simple XML Gateway Architecture for JDBC

The heart of our XML gateway architecture for JDBC is the JDBC2XML class This class controls access

to the JDBC data source Briefly, it executes a SQL statement against the specified JDBC data source,serializes the returned JDBC result set as XML, and returns this XML document to the calling client Inour architecture, the JDBC2XML class will be reused by two Java servlets: the XMLDataGateway servlet and the JDBC2HTML servlet The XMLDataGateway servlet provides a generic XML-over-HTTPinterface to JDBC data sources for XML-enabled applications The JDBC2HTML servlet returns JDBCresult sets as HTML to web browsers using the specified XSL stylesheet This servlet essentially acts as afilter; when an HTTP user agent submits an HTTP GET or POST request to an XSL stylesheet, therequest is delegated to the JDBC2HTML servlet for handling The following figure shows this

architecture:

Trang 23

A Simple XML Gateway Architecture for JDBC

XML-enabled Application

XMLDataGateway

Servlet

Web browser

HTML over HTTP

XSL Stylesheet

Delegated to

JDBC2HTML Servlet

JDBC2XML Class

XSLT

In-process

call

In-process call

XML serialized resultset

XML serialized resultset

JDBC

JDBC Data Source

This section will walk you through creating and using this architecture Specifically, it will show youhow to do the following:

❑ Develop the JDBC2XML class

❑ Develop the XMLDataGateway servlet

❑ Query a JDBC data source using the XMLDataGateway servlet

❑ Develop the JDBC2HTML servlet

❑ Write an XSL stylesheet that defines HTML presentation logic for our <resultset/> XMLschema

❑ Query a JDBC data source using the JDBC2HTML servlet

Trang 24

The JDBC2XML Class

The class encapsulates the functionality required to query a JDBC data source and return the results ofthat query as a well-formed XML document Essentially, it executes a SQL statement against thespecified JDBC data source, serializes the returned JDBC result set as XML, and returns this XMLdocument to the calling client as a string Create the JDBC2XML.java file and enter the following code:

To accomplish this, the JDBC2XML class implements several different methods These methods include:

❑ Methods that apply XML encoding rules, including the encodeXML() method

❑ A method that serializes a JDBC result set to XML, the writeXML() method

❑ The method that brings everything together by executing the search and returning the results

as XML (the execute() method)

This section will show you how to implement each method

Applying XML Encoding Rules to the Result Set Data

The encodeXML() method is a generic method that allows you to apply XML encoding rules to certainspecial characters A well-formed XML document with element or attribute values containing thesespecial characters must be specially encoded to escape them out Otherwise, an XML parser will not beable to process the document This table shows those characters and their encoded values:

Character Encoded value

The encodeXML() method simply does a search-and-replace operation on the passed-in string,

replacing instances of the special characters with their encoded equivalent This method will be used bythe writeXML() method to ensure that any data retrieved from the database is encoded properlybefore being serialized to XML:

Trang 25

String encodeXML(String sData)

{

String[] before = {"&","<",">","\"", "\'"};

String[] after = {"&amp;","&lt;","&gt;","&quot;", "&apos;"};

if(sData!=null)

{

for(int i=0;i<before.length;i++){

sData = Replace(sData, before[i], after[i]);

}}

String Replace(String content, String oldWord, String newWord)

Serializing the Result Set's Metadata and Data as XML

The next step is to add code to our JDBC2XML class that serializes a JDBC result set to XML Toaccomplish this, we need to do two things: design an XML data structure that encapsulates the data andmetadata of a result set, and implement the writeXML() method that performs the actual serialization

Designing the <resultset> XML Structure

The first step is to define an XML data structure that will represent the serialized state of our JDBCresult set For simplicity, we will create a DTD-less document that can be parsed by non-validatingXML parsers The root element is the <resultset> element This element contains two sub-elements:

a <metadata> element, and a <records> element

The <metadata> element contains a <field> element for each database field This element containstwo attributes: a name attribute, and a datatype attribute The <records> element contains a

<record> element for each row in the result set The <record> element also contains a <field>element for each column This code fragment shows the structure of our <resultset> XML

Trang 26

<record>

<field name="field name goes here">

field's value goes here

</field>

</record>

</records>

</resultset>

Implementing the writeXML() Method

The writeXML() method serializes the specified JDBC result set as an XML document that conforms

to the structure defined above The first action it performs is to create a StringBuffer that containsthe <?xml?> processing instruction and the <resultset> root element We will use this

StringBuffer object to hold our output Next, it enumerates through the result set's metadata,creating a <field> element for each column Finally, it enumerates through each record of the resultset, creating a <record> element that contains a <field> element for each column Field values arepre-processed with the encodeXML() method defined above to ensure compliance with XML encodingrules Once we have looped through the entire result set, we terminate the <resultset> element, andreturn the XML document:

String writeXML(ResultSet rs)

{

StringBuffer strResults = new StringBuffer

("<?xml version=\"1.0\" encoding=\"ISO-8859-1\"?>\r\n<resultset>\r\n");try

{

ResultSetMetaData rsMetadata = rs.getMetaData();

int intFields = rsMetadata.getColumnCount();

strResults.append("<metadata>\r\n");

for(int h =1; h <= intFields; h++){

strResults.append("<field name=\"" + rsMetadata.getColumnName(h) +

"\" datatype=\"" + rsMetadata.getColumnTypeName(h) + "\"/>\r\n");}

strResults.append("</metadata>\r\n<records>\r\n");

while(rs.next()){

}}catch(Exception e) {}

strResults.append("</records>\r\n</resultset>");

return strResults.toString();

}

}

Trang 27

Executing the Query

The execute() method brings it all together by executing a query against a JDBC data source andreturning the results as an XML document It takes five input parameters:

String output = new String();

The first step is to register and instantiate the JDBC driver Next, we will connect to the database andcreate a statement object After that, we will execute the SQL statement using the statement object'sexecuteQuery() method This will return a result set We will then serialize the result set to XMLusing the writeXML() method we created above:

Now our JDBC2XML reusable class is complete, and we can start using it in our sample applications

The XMLDataGateway Servlet

The XMLDataGateway servlet uses the JDBC2XML class to provide a generic XML-over-HTTP interface

to JDBC data sources In this section, we will show how to implement and use this servlet

Trang 28

Implementing the Servlet

To implement the XMLDataGateway servlet, we will write a Java class that subclasses the

javax.servlet.http.HttpServlet class We will also override the doGet() and doPost()methods to handle HTTPGET and HTTPPOST requests

Overriding the doGet() Method

The doGet() method allows the XMLDataGateway servlet to respond to HTTP GET requests The code

in this method is actually simple First, we will set the MIME type to "text/xml." That way, requestingHTTP user agents will know that the response sent should be handled as an XML document Next, wewill get a reference to the PrintWriter object that enables us to write a response back to the client.Finally, we'll instantiate the JDBC2XML class and call the execute() method This method will returnthe XML-serialized result set, which we will pass immediately to the HTTP response stream's

PrintWriter We will obtain the SQL and JDBC connection information needed by the execute()method from the HttpServletRequest object, which encapsulates key-value pairs obtained from theURL's query string If this seems a little confusing right now, don't worry; it will become much clearerwhen we run a sample application

public void doGet(HttpServletRequest request, HttpServletResponse response)throws IOException, ServletException

}

Overriding the doPost() Method

The next step is to override the doPost() method In this particular servlet, we will handle HTTPPOSTs the same way we handle HTTP GETs Therefore, our doPost() implementation will simplymake a call to doGet()

public void doPost(HttpServletRequest request, HttpServletResponse response)throws IOException, ServletException

{

doGet(request, response);

}

}

Trang 29

That's all there is to writing the XMLDataGateway servlet Now, you would compile the Java sourceinto bytecode and package it for deployment to a J2EE-compliant servlet container We will cover thisprocess in detail at the end of the chapter once we have completed the entire application In themeantime, we will walk through a few examples of how to use the XMLDataGateway servlet, using thepre-built jdbcxml.war web application downloaded from the Wrox web site For more information onhow to deploy jdbcxml.war to Tomcat, please refer to the section in this chapter on installing andconfiguring Tomcat.

Developing an HTML Form Interface

In order to test the XMLDataGateway servlet, we must create a user interface for it Since the servlet is

an HTTP application, we will create a simple HTML form that allows you to test it from a web browser

We will save it in an HTML file, and name that file xmlsqlquery.html

The XMLDataGateway servlet of course will be the action handler for the HTML form, and the formwill use HTTP POST as the request method The form contains five fields, each corresponding to theassociated request parameter expected by the servlet Here's the source listing for the

XMLDataGateway's HTML front end For brevity purposes, only the HTML form itself is shown,omitting the HTML opening and closing tags and any other tags the file might have:

<form action="/jdbcxml/servlet/XMLDataGateway" method="POST">

<td align="right"><font face="Arial">password </font></td>

<td><font face="Arial"><input type="password"

size="50" name="pwd"></font></td>

</tr>

<tr>

<td align="right"><font face="Arial">SQL Statement:</font></td>

<td><textarea name="sql" rows="10" cols="50"></textarea></td>

Trang 30

Using the XMLDataGateway Servlet

As we mentioned earlier, the XMLDataGateway servlet can be used from any HTTP client that knowshow to parse and render (or manipulate) well-formed XML This section will discuss two scenarios forusing the XMLDataGateway servlet: from a web browser, and from a Win32 application

Using XMLDataGateway from a Web Browser

Now we are ready to start using the XMLDataGateway servlet First, start Tomcat if it isn't alreadyrunning Then, point your browser at http://127.0.0.1:8080/jdbcxml/xmlsqlquery.html Since the resultswill come back as XML, I recommend you use a browser that knows how to consume and display well-formed XML, such as Microsoft Internet Explorer 5.x or higher On the HTML form, type in the name

of the JDBC driver you want to use, the URL of the JDBC data source, the user ID and passwordrequired to log onto the database server, and the SQL statement Then, click the Submit Query button

to execute the query

To give you a specific example, we will walk through a search of a Microsoft Access database Tofacilitate this, we have provided a sample MS-Access database as part of the chapter's sample codedownload This database is named contacts.mdb, and is located in the

\Chapter16\jdbcxml\sql directory

Prior to running through this example, we need to set up this Access database as a System DSN usingthe Windows NT Control Panel ODBC applet After launching this applet, you will see the ODBCData Source Administrator Click on the Add button, and you will see this dialog:

Trang 31

Select the Microsoft Access driver, and click on Finish You will see this dialog:

For the data source name, type in contacts Click on the Select button, and browse to the location ofthe contacts.mdb file on your local system Once you have completed that, click on OK You shouldnow be back to the ODBC Data Source Administrator, and it should show your new contacts SystemDSN added to the list:

Trang 32

Now we are ready to execute a query On the xmlsqlquery.htmlform, type in the followinginformation:

❑ The fully qualified class name of the Sun JDBC-ODBC:

driver:(sun.jdbc.odbc.JdbcOdbcDriver)

❑ The Contacts database's JDBC URL (jdbc:odbc:contacts)

❑ Since the Contacts database does not implement any security, you can simply leave the user

ID and password blank

❑ For the SQL statement, type in SELECT * FROM contacts

The completed form should look like this:

Trang 33

To execute the query, click on the Submit Query button Your results should look like this:

To give you a more advanced example, we will walk through a search of an Oracle 8i database We willuse the Oracle thin driver This example should work with any Oracle installation, since it merelyqueries the user_tables entity To make the connection, we'll type in the following information:

❑ The fully qualified class name of the Oracle JDBC driver:

(oracle.jdbc.driver.OracleDriver) You must ensure that the Oracle JDBC driver is inTomcat's CLASSPATH To add it, please view the Tomcat setup instructions that were coveredearlier in this chapter

❑ The Oracle database's JDBC URL, using the following form:

jdbc:oracle:thin:@oraclehostname:port:oracledbname, where oraclehostname

is the name of the server on which the Oracle database resides, port is the IP port on which

to connect to the Oracle database, and oracledbname is the name of the particular database

to query

❑ The user ID and password with which to log onto the Oracle database server

Trang 34

Finally, we'll type in the SQL statement This example is a simple query of the Oracle user_tablesentity Here's what the complete query looks like:

When we execute the query, the servlet sends the XML-serialized result set showing the query results.This is what it looks like in MS Internet Explorer 5.x:

Trang 35

As we have mentioned before, if you don't have access to Oracle, you can use the XMLDataGatewayservlet to query any database product for which a JDBC driver has been written To preclude anyproblems that might occur when testing it with another database product, please ensure that the JDBCdriver for this database is added to Tomcat's CLASSPATH In addition, if you are using a desktopdatabase product such as Microsoft Access, many of these products allow you to create databases that

do not require verification of user credentials If this is the case, then you simply leave the user ID andpassword fields blank You should also note that the JDBC URL format is driver-dependent Therefore,

if you are using a database other than Oracle, please consult the product's documentation for

information on how to form a valid JDBC URL

Using the XMLDataGateway Servlet from Other XML-Enabled Applications

As we mentioned before, one of the great advantages of using the XMLDataGateway servlet is that itallows you to extend the availability of your JDBC data source to non-Java applications For example,one of your trading partners might use a system that is implemented as a Win32 application written inVisual C++ Your internal systems might be built on the J2EE architecture, using JDBC to access anOracle database server running on Solaris

One of the easiest ways to integrate these two systems over the Internet is via XML-over-HTTP, whichour XMLDataGateway servlet implements Your trading partner's Win32 application can be modified touse MSXML to execute SQL statements against your Oracle database via HTTP GET From there, it canperform any necessary integration steps

Note: If you are planning to make your data available over the Internet via

XML-over-HTTP, please ensure that you attend to the security details For example, ensure

that default passwords are changed for database administrator accounts, access

control lists are properly set, and SSL encryption is used.

To show you a simple example of this process, we will use the Microsoft XML Notepad to execute thesame Microsoft Access query we covered in the previous section You can download Microsoft XMLNotepad from http://msdn.microsoft.com/xml/notepad/

After you have installed XML Notepad, launch the application, click on File in the menu bar, and thenclick on Open You'll see a dialog box that looks like this:

Select the From URL radio button, and then type in the following URL Yes, it is that long:

http://127.0.0.1:8080/jdbcxml/servlet/XMLDataGateway?driver=sun.jdbc.odbc.JdbcOdbcDriver&jdbcurl=jdbc:odbc:contacts&sql=select+*+from+contacts

Trang 36

In this example, you'll notice that we are using HTTP GET instead of HTTP POST The input parametersthat the servlet takes are placed as ampersand-delimited key-value pairs in the URL's query string Oncethe query is executed, XML Notepad will display the results as follows:

Summary

In this section, we walked through the creation of the XMLDataGateway servlet, a simple example ofhow you can create an architecture-neutral XML-over-HTTP gateway to your JDBC data sources In thenext section, we will take it a step further by extending this architecture to perform device-specifictransformations of JDBC data using XML and XSLT

Trang 37

The JDBC2HTML servlet is designed as a filter; in other words, the servlet is not invoked directly.Instead, the servlet container is configured to dispatch requests for URLs with a particular mapping tothis servlet for handling In the case of the JDBC2HTML servlet, we will configure the servlet container

to pass any URL requests for files ending in xsl to the JDBC2HTML servlet for execution This ishow the servlet will know which XSL stylesheet to use for the XSLT operation If this sounds confusing,don't worry; we will cover how this process works in detail as the chapter proceeds

This section will show you how to implement this framework, specifically the following tasks:

❑ Writing the servlet itself

❑ Writing a generic XSL stylesheet that transforms the XML-serialized result set into an HTMLtable

❑ Using the JDBC2HTML servlet to query a Microsoft SQL Server database

Implementing the JDBC2HTML Servlet

As with the XMLDataGateway servlet, we will implement the JDBC2HTML servlet by writing a Javaclass that subclasses the javax.servlet.http.HttpServlet class We will also override thedoGet() and doPost() methods to handle HTTP GET and HTTP POST requests respectively Since

we are using the Xalan XSLT processor in the servlet, we will import the org.apache.xalan.xsltpackage We will also import the org.xml.sax.SAXException class, which is thrown by the XercesSAX parser (the underlying parser used by Xalan) if either the XML document or the XSL stylesheet isnot well formed:

Overriding the doGet() Method

The next step is to override the doGet() method for HTTP GET request handling Since the

JDBC2HTML servlet is a filter, the first order of business is to determine the physical file location of therequested stylesheet It first checks the PATH_INFO environment variable If it is Null, the servletassumes that it was invoked as a result of a direct URL request for an XSL stylesheet (for example,http://hostname/dir/myStylesheet.xsl), and obtains the stylesheet's real path by passing the

SCRIPT_NAME environment variable (obtained via the getServletPath() method call) to the servletcontext's getRealPath() implementation Otherwise, it uses the PATH_INFO (for example, thePATH_INFO for http://hostname/servlet/JDBC2HTML/dir/myStylesheet.xsl is

/dir/myStylesheet.xsl), and gets the PATH_INFO 's real path via the Request object's

getPathTranslated() method

public void doGet(HttpServletRequest request, HttpServletResponse response)throws IOException, ServletException

{

Trang 38

Finally, it will use the Xalan XSLT processor to transform the results of the query to HTML using therequested XSL stylesheet file, and place the output in the HTTP response stream:

try

{

XSLTProcessor processor = XSLTProcessorFactory.getProcessor();

processor.process(new XSLTInputSource(newjava.io.StringReader(output)), new XSLTInputSource("file:///" +qryDoc), new XSLTResultTarget(out));

Overriding the doPost() Method

The next step is to override the doPost() method As with the XMLDataGateway servlet, the

JDBC2HTML servlet will handle HTTP POSTs the same way we handle HTTP GETs Therefore, ourdoPost() implementation will simply make a call to doGet()

public void doPost(HttpServletRequest request, HttpServletResponse response)throws IOException, ServletException

{

doGet(request, response);

}

}

That's all there is to writing the JDBC2HTML servlet While a bit more complex than the

XMLDataGateway servlet, it is still straightforward Moreover, the same concepts could be easilyapplied to other device types, such as a WAP phone The only difference would be in the MIME type(for example, text/vnd.wap.wml vs text/html), the output syntax (WML vs HTML), and thedisplay constraints of WAP devices vis-à-vis web browsers

Trang 39

Now, you would compile the Java source code into bytecode and package it for deployment to a compliant servlet container Part of this packaging process would include creating a mapping thatinstructs the servlet container to hand off all requests for xsl files to the JDBC2HTML servlet We willcover this process in detail at the end of the chapter In the meantime, we will walk through a fewexamples of how to use the JDBC2HTML servlet using the jdbcxml.war web application downloadedfrom our web site, and deployed to Tomcat in an earlier section.

to match the root element of the document:

The Resultset Template

The next template is for the top-level <resultset> element This template does two things First, itsets up the basic structure of the HTML document Second, it uses the <xsl:apply-templates>element at the appropriate spots to apply the templates for the <metadata> element (which will bedisplayed as the table's heading) and the <records> element (which will be displayed as the tablebody) In the case of the <records> element, the //resultset/records notation tells the XSLTprocessor to match any <records> element that is a descendant of the <resultset> element:

Trang 40

The Metadata and Metadata Field Templates

The next two templates set up the table header row from the <metadata> element and its <field>child elements The meta-data template creates the table row The field template creates a table cell foreach field:

The Records and Record Templates

The next two templates create a table row for each record, with a table cell containing the data for eachfield:

The Error Template

Finally, we have a template to handle any errors that might occur As you might recall, the

JDBC2XML's execute() method returns an <error> element containing information from anyexception that is thrown within that method This template ensures that this information is displayed in

Ngày đăng: 13/08/2014, 12:21