Enterprise Java Technologies Tech Tips
Tips, Techniques, and Sample Code
Welcome to the Enterprise Java Technologies Tech Tips for
July 30, 2004. Here you'll get tips on using enterprise Java
technologies and APIs, such as those in Java 2 Platform,
Enterprise Edition (J2EE).
This issue covers:
* Using Existing Web Resources
* Using TrAX for XPath
These tips were developed using the Java 2, Enterprise Edition,
v 1.4 SDK. You can download the SDK at
http://java.sun.com/j2ee/1.4/download-dr.html.
This issue of the Tech Tips is written by Mark Johnson, president
of elucify technical communications (http://www.elucify.com/),
and co-author of Designing Enterprise Applications with the J2EE
Platform, 2nd Edition (http://java.sun.com/blueprints/guidelines/
designing_enterprise_applications_2e/). Mark Johnson runs an open
forum for discussion of the tips at
http://groups.yahoo.com/group/techtipsarchive/.
You can view this issue of the Tech Tips on the Web at
http://java.sun.com/developer/EJTechTips/2004/tt0730.html.
See the Subscribe/Unsubscribe note at the end of this newsletter
to subscribe to Tech Tips that focus on technologies and products
in other Java platforms.
You can download the sample archive for these tips at
http://java.sun.com/developer/EJTechTips/download/ttjul2004.ear.
Any use of this code and/or information below is subject to the
license terms at
http://developers.sun.com/dispatcher.jsp?uid=6910008.
For more Java technology content, visit these sites:
java.sun.com - The latest Java platform releases, tutorials, and
newsletters.
java.net - A web forum for collaborating and building solutions
together.
java.com - The marketplace for Java technology, applications and
services.
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
USING EXISTING WEB RESOURCES
With all of the attention being paid to SOAP-based XML Web
services, it's easy to forget that there are a lot of useful
services and content out there that are not available with SOAP.
The following tip shows how to use a servlet to use existing Web
resources from the Web tier. In this case, the existing Web
resource is a non-standards-based XML service.
Leveraging Existing Resources
Most content on the Web isn't available in the form of
standards-based Web services -- at least not yet. Much static
content exists in the form of existing HTML pages, text files,
document files (such as PDF files and word processor
documents), files on ftp sites, and images. Some services
actively produce XML in response to HTTP POST or GET requests.
Other services, such as RSS feeds, have static URLs, but act as
services because their data is dynamic, and their content is
usually used by programs rather than directly by human readers.
Enterprise Java technology is excellent for interoperating with
existing resources, both in organizational intranets and on the
Internet at large. Enterprise Java technology can be used in any
tier to integrate existing information assets into new systems.
You don't need to wait for SOAP-based Web services to create
valuable new systems that integrate existing resources.
Search Engines at Work
The National Library of Medicine is one of the National
Institutes of Health, a US federal government agency. One of
NLM's services is PubMed*, a searchable database of biomedical
publication abstracts. PubMed's search engine is called Entrez.
You can use Entrez to search the abstracts at
http://www.ncbi.nlm.nih.gov/entrez/query.fcgi, or just type
pubmed into the address bar of your browser and hit return.
PubMed also offers a service called e-utilities that provides a
programmatic interface to the search engine. e-utilities receive
HTTP GET requests from clients and can return XML that represents
search results.
The sample code that accompanies this tip is a servlet that
accesses two of the e-utilities:
o esearch. Performs a search and returns a list of IDs.
o efetch. Fetches requested documents in a variety of formats.
You also have the option of specifying that the XML returned by
either esearch or efetch be transformed by an XSLT stylesheet
for presentation in the browser. Depending on what parameters are
provided by the client, the servlet uses an appropriate
stylesheet.
An Overview of the Servlet
The sample code servlet, called Jul2004Servlet, uses the
existing Web services esearch and efetch to provide new
functionality. The servlet converts its input parameters into
GET URLs, and uses them to retrieve data for analysis and
display. The servlet first calls esearch to execute a search,
and then calls efetch to retrieve results.
1. The servlet receives POST parameters from a user form and
builds an HTTP GET URL with the parameters required by
esearch.
2. The servlet executes HTTP GET with the URL. The esearch
e-utility sends back XML containing data that identifies the
server-side result set.
3. The servlet parses the XML returned by esearch, and uses
DOM API calls to retrieve the WebEnv and QueryKey. It then
uses these values to build a URL to get the data.
4. The servlet executes another HTTP GET, this time to efetch.
It indicates the result set, and includes formatting
parameters specified in the original request.
5. The servlet receives the requested document data from efetch,
and optionally transforms the data with XSL before returning
a result to the browser.
Searching the Database
The first step in retrieving document information from the
Entrez server is to perform an esearch with several parameters
from the input form in the application's index.html page. The
esearch service executes the query on the Entrez server and
returns data corresponding to the results of the query. If the
HTTP GET query string includes the parameter "usehistory=y", the
Entrez server also returns two additional items of data: a WebEnv
string and a QueryKey. A WebEnv string is a unique identifier for
user state within a session in the Entrez server. This state
includes a history of previous queries and their result sets.
A QueryKey is a small integer that identifies the specific query
within the session. Together, the WebEnv and the QueryKey
represent the query result set on the server.
The servlet receives several parameters from the input form in
the application's index.html page.
The servlet code uses the POST parameters to build a URL, like
this:
AbstractMap paramMap = new TreeMap();
res.setContentType("text/html");
OutputStream os = res.getOutputStream();
// Get parameters
String query = req.getParameter("query");
// Execute esearch
// db=PubMed: search PubMed database
// usehistory=y: return key to server-side result set
// term=$query: search for "$term" in PubMed
paramMap.put("db", "PubMed");
paramMap.put("usehistory", "y");
paramMap.put("term", query);
// Create the URL and get its content
String surl = buildUrl(BASEURL_ESEARCH, paramMap);
InputStream is = getContent(surl);
The buildUrl method used here takes a base URL and constructs an
HTTP GET URL by creating a key=content string for each
(key, content) pair in the map. The content is URL-encoded, and
the parameters are joined with the string "&" to produce an
HTTP GET URL. For example, if the form query is
"neanderthal DNA", then the query string will be:
db=PubMed&term=neanderthal+dna&usehistory=y
The method getContent simply opens an HttpUrlConnection to the
requested URL and returns an InputStream to the resulting
content, as follows:
protected InputStream getContent(String surl)
throws ServletException {
Object content = null;
try {
// Connect to URL
URL url = new URL(surl);
HttpURLConnection conn =
(HttpURLConnection)url.openConnection();
conn.connect();
// Get content as stream
content = conn.getContent();
} catch (Exception e) {
throw new ServletException(e);
}
return (InputStream)content;
}
The input stream from an esearch request contains an XML
document that looks like this:
19
19
0
1
0ed8yFoq_CFyEEP6hW9aZ9UoTCVrrPm2w343S9MRNaT9MQmwbnjI
The servlet needs to extract the content of the QueryKey and
WebEnv elements in this XML document. It needs to include this
content in a subsequent call to efetch, which will return the
document data for display.
Getting Results
Because efetch results are small, it can be parsed into an
in-memory DOM tree. The servlet parsing the string returned by
esearch, and in doing so, uses a DocumentBuilder to get the
Document object into memory:
// Create DOM parser and parse search result
DocumentBuilderFactory dbf =
DocumentBuilderFactory.newInstance();
DocumentBuilder db = dbf.newDocumentBuilder();
Document esearchDoc = db.parse(is);
// Get WebEnv, Count, and QueryKey from result
// WebEnv - result key
// QueryKey - history index
// Count - result set length
String webenv = getElementString(esearchDoc, "WebEnv");
String count = getElementString(esearchDoc, "Count");
String querykey = getElementString(esearchDoc, "QueryKey");
The getElementString method is a simple convenience function
that finds a node of the given name and returns its first Text
subnode. The servlet extracts the WebEnv and QueryKey values
from the parsed DOM Document.
At this point, the servlet has a result set waiting for it on
the server. The next step is to retrieve and format the data
using efetch.
Specifying Fetch Parameters
Efetch requires just a few parameters to identify the results of
an esearch:
o db. Identifies the database ("PubMed")
o WebEnv. Identifies the session
o query_key. Identifies the query in the session
Additional parameters limit the size, and control the format of
the returned data:
o retstart and retmax tell efetch to return a subset of the result
set, starting at retstart and returning no more than retmax
records. Without these parameters, efetch returns the entire
result set, which can often be multiple megabytes.
o retmode indicates how to format the data (XML, HTML, text, or
ASN.1). The default is ASN.1, PubMed's native storage and
exchange format.
o rettype tells what to return for each record. By default, efetch
returns abstracts.
The servlet creates a Map of request parameters, just as it did
for esearch. It uses the WebEnv and QueryKey strings it retrieved
from esearch, and also includes several parameters received from
the original form. The getParameter method simply gets a
parameter from the request, substituting a default string if the
parameter is not set.
paramMap = new TreeMap();
paramMap.put("WebEnv", webenv);
paramMap.put("query_key", querykey);
paramMap.put("db", "PubMed");
paramMap.put("retstart", getParameter(req, "start", "0"));
paramMap.put("retmax", getParameter(req, "max", "20"));
paramMap.put("retmode",
retmode = getParameter(req, "retmode", "xml"));
paramMap.put("rettype", getParameter(
req, "rettype", "abstract"));
// Create URL and get its content
surl = buildUrl(BASEURL_EFETCH, paramMap);
is = getContent(surl);
The servlet uses the map to build a request URL, and uses
getContent to get an InputStream to the request result.
Transforming the Document
If the data format requested was not XML, or if there was no
valid stylesheet, the servlet simply copies the data returned
by efetch to the browser. This feature can be useful if you are
experimenting with e-utilities directly.
If the data format is XML, and if there is a valid, nonempty
stylesheet, the servlet applies this stylesheet to the data and
returns the result to the browser. The XML returned to the
browser contains quite a bit of data for each record. Here is an
excerpt of the returned data:
The thermal history of human fossils
and the likelihood of successful DNA amplification.
This data is the content on which the stylesheet operates to
produce its output.
There are two ways for a user to specify a stylesheet to apply.
The user form has a radio button called "isFile" that indicates
what stylesheet to use for the transformation. If isFile is 1,
the parameter "stylesheet" contains the name of a stylesheet
file in the Web application archive (WAR file). If isFile is 0,
the parameter sstext contains a stylesheet that the user typed
into a TEXTAREA in the form. You can use this feature to view
formatted reports. You can also use the feature to create new
reports by copying XSL from a text editor directly into the form.
The code that performs the transform receives the following:
o An input stream to read from (the results of efetch)
o An output stream to write to (the servlet's output)
o The isFile parameter
o A string containing either the name of the stylesheet or the
text of the stylesheet itself.
The method builds a Transformer object from the stylesheet, and
then calls the Transformer's transform method, passing the input
and output streams as source and destination.
// Create XSLT transformer for output.
TransformerFactory tf = TransformerFactory.newInstance();
Transformer t = null;
// Use identity transform if no transformer was specified
if (stylesheet == null || stylesheet.equals("")) {
t = tf.newTransformer();
} else {
StreamSource xslsource = null;
if (isFile) {
// Read XSL stylesheet from app archive and wrap it as
// a StreamSource. Then use it to construct
// a transformer.
InputStream xslstream = _config.getServletContext().
getResourceAsStream(stylesheet);
xslsource = new StreamSource(xslstream);
} else {
// Read XSL stylesheet from string
xslsource = new StreamSource(
new StringReader(stylesheet));
}
t = tf.newTransformer(xslsource);
}
// Do transform from input (e-utilities result) to
// output (servlet writer)
StreamSource ss = new StreamSource(is);
StreamResult sr = new StreamResult(os);
t.transform(ss, sr);
The completed transform writes the result HTML to the output
stream, and the server delivers the resulting content to the
browser.
Viewing the Results
The application archive contains two stylesheets:
o titles.xsl displays only the titles of the documents.
o extended.xsl formats each record as a citation in the
standard bibliographic reference format defined by the
National Library of Medicine. In addition, the actual
citation information (journal, publication date, volume,
issue, and page numbers) is formatted as a hyperlink to the
entire abstract at the PubMed site.
You can also define your own styles using the stylesheet embedded
in the input form. The form's stylesheet TEXTAREA provides the
skeleton of a stylesheet. Perform a sample search using the
servlet. Specify no stylesheet. Copy the resulting XML to a file,
and use it as example XML to develop a new stylesheet in a text
editor. Then copy and paste the entire stylesheet into the form.
Click the "Using custom XSL style:" radio button, and select
Search. If your stylesheet is valid, the servlet will use it to
format your search results.
It would be easy to expand this example servlet into something
more useful. For example, you could download and analyze large
data sets from PubMed. Or, you could use the other databases
available from e-utilities (see the einfo utility for more) to
write bioinformatics applications, displaying DNA sequences with
the publications that link to them.
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
USING TRAX FOR XPath
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
The expressions in "match" and "select" attributes of XSL
stylesheets are written in the XML Path Language, or XPath.
(http://www.w3.org/TR/xpath). An XPath expression addresses a
set of nodes in a DOM document tree. XPath is a powerful
expression language for writing effective XSLT stylesheets.
A variety of XPath implementations are available, four of which
are:
o The open-source, portable XPath implementation called Jaxen
is fast, and was included by Sun in the JavaServer Pages
Standard Tag Library (JSTL) and the Java Web Services
Developer Pack.
o The Java 2 Platform, Standard Edition (J2SE) 1.5 (currently
available as a Beta 2 release) offers a new XPath class that
executes XPath searches against a DOM Node. This new
interface is part of Java API for XML Processing (JAXP) 1.3,
(JSR 206)
(http://java.sun.com/j2se/1.5.0/docs/api/javax/xml/xpath/XPath.html)
o Both JDOM and dom4j offer XPath interfaces.
(http://www.dom4j.org/apidocs/org/dom4j/xpath/package-summary.html)
(http://www.jdom.org/docs/apidocs/org/jdom/xpath/package-summary.html)
o Apache's Xalan package includes a package for XPath. The
Xalan package is included in Sun's J2SE runtime (in rt.jar),
so you can use Xalan's XPath API if you're running that
distribution. But that solution isn't portable, because the J2EE
specification doesn't require Xalan to be present in all
distributions.
(http://xml.apache.org/xalan-j/apidocs/org/apache/xpath/package-summary.html)
All of these options are portable and offer reasonable
performance. But in a standard J2EE 1.4 installation, you can't
depend on any of the above to be available. And you can't always
redistribute third-party libraries. Fortunately, even you can't
use the above solutions, there's still a way to get XPath
support: by using TrAX (Transformation API for XML), which is
included as part of the current J2EE specification.
An XPath Stylesheet
The TrAX API defines interfaces for classes that transform XML.
The most common use for the API is to create, use, and manage
XSLT stylesheets. Creating XSLT stylesheets is covered in the
October 15, 2002 Tech Tip titled "Transforming XML With XSL."
XSLT stylesheets are also used in the first tip in this issue
"Using Existing Web Resources."
A TrAX Transformer uses an XPath matcher to match the XPath
patterns in an XSLT stylesheet against the Transformer's input
document. You can't access the Transformer's XPath API because
it isn't standard. But you can write a stylesheet that matches
the pattern you want.The stylesheet then copies the matching
node, and all of its children.
Let's look at an example. Imagine that you wanted to match the
pattern '/html/head/title'. The following XSLT stylesheet
matches that XPath pattern, and copies the matching node and all
of its children to its result.
\n
This stylesheet has two templates:
o. The first template matches the requested XPath, and copies it
and all of its children to the result (that's how
works).
o. The second template overrides XSLT default templates, so that
only data produced by the first template appears in the final
result set. This template is necessary because default XSLT
templates copy all text and nonignorable white space nodes to
the result. This template overrides these default templates,
and instead ignores all nodes not matched by the first template.
You can replace the pattern in the first template with any XPath
pattern. The result will be all nodes in the document that match
the replacement pattern. Keep in mind that this solution trades
performance for portability. This XPath stylesheet approach has
several drawbacks. The stylesheet introduces additional
processing. Also, because it loads the entire document as a DOM
tree, the approach isn't suitable for very large documents. And,
because the code returns clones of nodes from the original DOM,
you can't use the results of the XPath searches to edit the
original tree. However, when performance is not an issue, and
you can't use one of the other solutions, this tip offers a
portable, standards-based workaround.
This tip's sample code creates a stylesheet like the one above,
with a user-defined XPath expression as the "match" attribute of
the first template. It then compiles and executes the stylesheet
against an input document, producing a NodeList of results.
Sample Code
The main method in the sample code class TrAXPath requires at
least two arguments:
o A source for the XML to transform; either a filename or
a URL
o One or more XPath patterns to apply to the source XML
The main method parses the input XML into a DOM. It then creates
a TrAXPath object for each XPath expression, and uses it to get
a list of matching nodes for the expression. Finally, it prints
the nodes that matched:
// Match xpath against document
TrAXPath txp = new TrAXPath(xpath);
NodeList matched = txp.selectNodeList(doc);
// Summarize nodes
p("Match[" + xpath + "]");
for (int q = 0; q < matched.getLength(); q++) {
p("--------------------[" + q + "]--------------------");
printDOM(matched.item(q));
p("");
}
(p is a convenience method for System.out.println.)
The TrAXPath class represents a single XPath expression, against
which multiple XML documents can be matched. Each call to
selectNodeList(Node) returns a list of Nodes that match the
XPath expression in the TrAXPath object.
A TrAXPath object is constructed with a String that contains the
XPath. The constructor builds an XSLT stylesheet in memory, and
then compiles it into a Templates object:
public TrAXPath(String xpath)
throws TransformerConfigurationException {
StringBuffer sb = new StringBuffer();
// Create stylesheet that copies matching nodes
sb.append("\n");
sb.append("");
sb.append("");
sb.append("");
sb.append("");
sb.append("");
sb.append("");
sb.append("");
sb.append("");
sb.append("");
// Construct the stylesheet Templates object.
TransformerFactory tf = TransformerFactory.newInstance();
String stylesheet = sb.toString();
Reader r = new StringReader(stylesheet);
StreamSource ssrc = new StreamSource(r);
// Create templates object
_templates = tf.newTemplates(ssrc);
}
You might be familiar with using a TransformerFactory to create
a Transformer which executes a transform. You can also use a
TransformerFactory to create a javax.xml.transform.Templates
object which represents a compiled stylesheet. If you use a
stylesheet more than once, it's good practice to create
Transformers using a Templates object. In this way the
stylesheet needs to be compiled only once.
The real work in class TrAXPath occurs in method c. The main
method uses selectNodeList to match patterns against its input
XML. The selectNodeList method uses the _templates object to
create a Transformer:
// Return a Node that matches xpath in context.
public NodeList selectNodeList(final Node context)
throws TransformerConfigurationException,
ParserConfigurationException,
TransformerException {
Transformer t = _templates.newTransformer();
The method then creates a DOMResult (required as the output of
the transformer) containing a single DocumentFragment:
// Create result document with top element "result"
DocumentFragment df = DocumentBuilderFactory.
newInstance().
newDocumentBuilder().
newDocument().
createDocumentFragment();
Result result = new DOMResult(df);
The TrAXPath code uses a DocumentFragment instead of a Document
because the result needs to be a list of nodes. A Document can
only have one top-level node. An error will occur if you pass
an empty document to the Transformer, and there is more than one
Node. A DocumentFragment result does not have this limitation.
Finally, the selectNode method uses the Transformer created
using the in-memory stylesheet to transform the source Node (the
Node being searched). The transformer copies all nodes that
match the XPath into the DocumentFragment. Calling the
DocumentFragment's getChildNodes method returns a NodeList of
all of the nodes that matched the XPath expression:
// Transform result into DocumentFragment
t.transform(new DOMSource(context), result);
// Return list of nodes in DocumentFragment
return df.getChildNodes();
}
Experimenting With The Code
The second form on the application's index.html page
communicates with a servlet to search a built-in XML file
(the first act of William Shakespeare's "A Comedy of Errors")
for XPaths that you enter.
For example, to search for the title of the play in the input
file, type the XPath expression "/PLAY/TITLE" into the search
box and hit Search. The servlet produces the following result:
The Comedy of Errors
You can see the entire file by searching for "/", which matches
(and prints) the top node of the document.
You can also download the TrAXPath class, which has its own main
method. Download the class file by clicking the download link on
the form, and save the file to your current directory. Be sure
the current directory is in your CLASSPATH. You can then execute
XPath expressions against any XML file, like this:
$ java com.elucify.tips.jul2004.TrAXPath xmlsource xpath
The parameter xmlsource can be either the local filesystem name
or the URL of an XML file.
Consider the following sample XML:
This is /a/b
This is /a/c/b
This is /a/d/b (first)
This is /a/d/b (second)
This is /a/e/b/b. What will happen?
If you run the TrAXPath program against this XML tree, and
search for the pattern "//b" ("b" anywhere in the tree), it
produces the following results:
Match[//b]
--------------------[0]--------------------
This is /a/b
--------------------[1]--------------------
This is /a/c/b
--------------------[2]--------------------
This is /a/d/b (first)
--------------------[3]--------------------
This is /a/d/b (second)
--------------------[4]--------------------
This is /a/e/b/b. What will happen?
The matcher matched all b nodes--or did it? Why didn't it match
the node inside the other node in match 4?
The matcher didn't find the inside of the other because
of the way the first template works. As soon as it matches ,
the matcher copies that node and all of that node's children to
the output. But it doesn't then check any of the children. So
those child nodes are never seen by the matcher.
If you want to match against all occurrences of -- even
those inside another -- you could modify the first template
slightly, like this:
The new rule (apply-templates) tells the stylesheet processor to
check and process all of the current node's children. Which
behavior you prefer depends on your application requirements.
The sample code for this tip also accepts as the XML source
a URL instead of a file. This makes the TrAXPath program useful
for grabbing chunks of data from the Internet. For example, you
can run the program with an RSS feed:
$ java com.elucify.tips.jul2004.TrAXPath \
http://servlet.java.sun.com/syndication/rss_java_highlights-10.xml \
'//item/title/text()'
Match[//item/title/text()]
--------------------[0]--------------------
Java Live Chat: Java Web Services Developer Pack 1.4.
--------------------[1]--------------------
The JVMPI Transition to JVMTI
--------------------[2]--------------------
What's Next? A Conversation about Web Communication with
XML Pioneer, Tim Bray
--------------------[3]--------------------
Upcoming Java Live Chat: Sun Game Server Technology.
--------------------[4]--------------------
The Utility Model for Online Games: Part Two of a Conversation
--------------------[5]--------------------
Get Ready for SOA
--------------------[6]--------------------
2004 JavaOne: Nokia Platinum Session
--------------------[7]--------------------
Deploying Web Services: Grid Computing
--------------------[8]--------------------
The J2EE 1.4 SDK and Sun Java Application Server Platform Edition 8
--------------------[9]--------------------
The Sun Java Desktop System, Release 2 Arrives
Use this trick to address portable address DOM nodes until
the Java 1.5 XPath class becomes standard for J2EE.
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
RUNNING THE SAMPLE CODE
Download the sample archive for these tips (from
http://java.sun.com/jdc/EJTechTips/download/ttjul2004.ear).
The application's context root is ttjul2004. The downloaded
EAR file also contains the complete source code for the sample.
You can deploy the application archive (ttjul2004.ear) in the
J2EE Reference Implementation using the deploytool program:
$J2EE_HOME/deploytool -deploy ttjul2004.ear localhost
Replace localhost with the name of the host on which the server
is installed. For a standard installation on a single machine,
the hostname typically (and literally) is localhost. You
can access the application at http://localhost:8000/ttjul2004.
For a J2EE-compliant implementation other than the Reference
Implementation, use your J2EE product's deployment tools to
deploy the application on your platform.
See the index.jsp welcome file for instructions on running the
application.
. . . . . . . . . . . . . . . . . . . . . . .
Please read our Terms of Use and Licensing policies:
http://www.sun.com/share/text/termsofuse.html
http://developers.sun.com/dispatcher.jsp?uid=6910008
PRIVACY STATEMENT:
Sun respects your online time and privacy (http://sun.com/privacy).
You have received this based on your e-mail preferences. If you
would prefer not to receive this information, please follow the
steps at the bottom of this message to unsubscribe.
* FEEDBACK
Comments? Send your feedback on the Enterprise Java Technologies
Tech Tips to:
http://developers.sun.com/contact/feedback.jsp?category=sdn
* SUBSCRIBE/UNSUBSCRIBE
Subscribe to other Java developer Tech Tips:
- Core Java Technologies Tech Tips. Get tips on using core
Java technologies and APIs, such as those in the Java 2
Platform, Standard Edition (J2SE).
- Wireless Developer Tech Tips. Get tips on using wireless
Java technologies and APIs, such as those in the Java 2
Platform, Micro Edition (J2ME).
To subscribe to these and other JDC publications:
- Go to the JDC Newsletters and Publications page,
(https://softwarereg.sun.com/registration/developer/en_US/subscriptions),
choose the newsletters you want to subscribe to and click
"Update".
- To unsubscribe, go to the subscriptions page,
(https://softwarereg.sun.com/registration/developer/en_US/subscriptions),
uncheck the appropriate checkbox, and click "Update".
- To use our one-click unsubscribe facility, see the link at
the end of this email:
- ARCHIVES
You'll find the Enterprise Java Technologies Tech Tips archives at:
http://java.sun.com/developer/EJTechTips/index.html
- COPYRIGHT
Copyright 2004 Sun Microsystems, Inc. All rights reserved.
901 San Antonio Road, Palo Alto, California 94303 USA.
This document is protected by copyright. For more information, see:
http://java.sun.com/developer/copyright.html
Enterprise Java Technologies Tech Tips
July 30, 2004
Trademark Information: http://www.sun.com/suntrademarks/
Java, J2SE, J2EE, J2ME, and all Java-based marks are trademarks
or registered trademarks of Sun Microsystems, Inc. in the
United States and other countries.
* The author of this tip, Mark Johnson, is a contract systems
analyst at the National Center for Biotechnology Information
(NCBI). The use of PubMed's interfaces in the tip is not an
endorsement of PubMed by Sun.