 | Level: Introductory Stephen B Morris (stephenbjm@yahoo.com), CTO, Omey Communications
11 Sep 2007 A Service-Oriented Architecture (SOA) typically exports a range of services. For XML
service modelling and subsequent consumption of those services by users (people, machines,
or other services), Java™ technology provides powerful mechanisms to handle XML data,
which in turn provides a key foundation for using SOA concepts. Dive into the practical
aspects of SOA using XML and Java technology, and discover clear examples of why this
seemingly complex technology is so popular.
SOA provides a range of services, some of which are consumed by users, others by
machines. The latter are in fact often other services, which makes SOA a kind of
recursive structure. This article describes a simple way to define services for use
in the context of Internet service providers (ISPs). I use this type of provider,
because most people are familiar with it. However, the ideas aren't restricted to
communications providers: They apply to all types of service providers—banks,
stock brokers, utility companies, and so on.
For this article, assume an ISP that has implemented all or part of its infrastructure
as an SOA. One of the services that this provider exports is a Web-based facility with
which users can modify their service profiles.
Why read this article?
At the time of this writing, SOA is still unfolding, and many of the big software
vendors are still developing their SOA offerings. As a result, the SOA area is
currently a complex soup of technologies that includes Java Business
Integration (JBI), Intelligent Event Processing, and Business Process Execution
Language (BPEL) servers. It's entirely likely that user organizations that intend
to reap the benefits of SOA will have to invest heavily before converging on a
solution. By making SOA so complex, the industry might well inadvertently pave the way for vendor lock-in, even though one of the promises of SOA is
standards-based, component-oriented, vendor-independent computing. Is it possible
for user organizations to gain some useful operational SOA experience before
the expensive migration process?
In answer to this question, this article demonstrates a few important SOA
principles with straightforward XML and some Java code. It doesn't attempt to
cover everything in the SOA universe; instead, the coverage is restricted to a few
key areas. For example, you can conceivably use RSS to
distribute XML service definitions. However, for this article's example, the transport mechanism uses
Java facilities.
The merit of such a focused approach is that Java developers in user
organizations can use the ideas to build their own simple pilot SOA. Such pilot
schemes can help the organization realize the business benefits of SOA. Included in
the latter are modelling business services as computational services, user
self-service, greater automation, and more responsive services. You can implement
a migration like the one described as a stand-alone pilot that operates in parallel
to existing business processes.
The latter might occur without requiring a large investment by the user
organization. By this means, the organization-specific SOA requirements can then
be stated in isolation from any vendor implementation. Indeed, some smaller user
organizations can continue with their pilot SOA scheme and only later
migrate to the large-scale commercial-grade solutions from the software
vendors.
The trend toward self-service
As with most service providers, self-service features are a growing trend—particularly with cash-strapped ISPs. So, if you need more
bandwidth (to perform downloads or play online games), you can log on to the
provider's Web site and use a Web page to automatically upgrade your connection to
the provider. Let's look at a concrete example: Listing 1
shows a simple XML-based user service profile.
Listing 1. A simple XML-based service description
<ServiceInstance>
<Customer>Josephine Bloggs</Customer>
<Package>Internet</Package>
<Bandwidth>1mbps</Bandwidth>
<DownloadLimit>1Gbyte</DownloadLimit>
<Uptime>95</Uptime>
</ServiceInstance>
|
This code illustrates the user XML service model. This model contains:
- A service instance
- A customer name
- A service package name
- The deployed bandwidth amount
- The monthly allowed download limit
- The provider uptime guarantee
Clearly, service definitions can be much more complex than what you see here. Other
details might include customer address, billing details, round-trip delays,
encryption, and service credit details. The point is, more and more providers
offer Web access to details such as those in Listing 1. Partly,
this is an attempt to reduce the cost and incidence of support calls. Interestingly,
such Web-based services help give the impression of a more cutting-edge provider!
It's a win-win situation, because customers get greater access to their
service data, while providers can sell a more hands-off package. Authorized users
are allowed to modify some of the service parameters shown
in Listing 1
—for example, the deployed bandwidth. The
user's monthly subscription charge is then modified (up or down) in line with the change.
So, the code in Listing 1 forms the basis of your XML-based service model. A user
can simply interact with an online form to modify the writable service elements
(for example, the bandwidth). Changes made through the online form are recorded,
then reflected in the back-end services that the user's profile influences. This
is a pretty standard way to implement self-service.
However, you're about to learn another, more loosely coupled possibility for
self-service—one in which a user can modify data by transferring the
XML content in Listing 1 across the network. In this scenario, the transferred XML
data is modified locally by a Java client running on a desktop computer, a laptop
computer, or even a resource-constrained device such as a mobile phone, then sent
back to the network service provider. Such a mechanism transcends the basic HTML
page model and embraces the SOA philosophy.
Transfer a service
definition XML document to a client with Java technology
 |
Java technology and XML
Java technology and XML have almost become synonymous. Indeed, I wrote this article
entirely in XML using IBM tools. In spite of the obvious and overwhelming
success of XML, it's important to remember that XML is a fairly bulky technology.
For example, the <start> and
<end> tags can add a lot of bandwidth and
processing overhead when data is transferred over networks. Regardless of its bulky
nature, however, XML does provide some powerful processing tools. These tools, two
of which are discussed in this article, essentially solve the problem of data
representation and parsing. (The latter is traditionally a difficult and awkward
problem.) Nowadays, thanks to XML tools, programmers of all skill levels can
implement professional, standard parsing.
|
|
Java technology provides some really powerful tools to manipulate XML data (see
the sidebar, Java technology and XML). If you think
of Listing 1 as an XML-based rendering of a given data set,
you can render it in other ways. The raw data that forms the basis of Listing 1 is typically stored in a database. So, how might you package the data as
XML?
Listing 2 is an excerpt from one of the supplied Java files
called encodeXML.java. (This and other, related files are available for
download from Download.) The
encodeXML.java class instantiates an object of the
XMLEncoder class. As you can see, this object then
creates a file called xmldata.xml in the current directory. The next step
is to insert XML data values into this file, which you do through a series of calls
to the writeObject() method (also illustrated in Listing
2). Clearly, in a production environment, the hard-coded text strings in Listing 2
will come from a persistent store such as a database. In any case, you can see the
ease with which an XML data file is created.
Listing 2. Encoding data in XML format
XMLEncoder e = new XMLEncoder(
new BufferedOutputStream(
new FileOutputStream("xmldata.xml")));
e.writeObject("Josephine Bloggs");
e.writeObject("Internet");
e.writeObject("1mbps");
e.writeObject("Gbyte");
e.writeObject("295");
e.close();
|
After executing the program in Listing 2, a file called xmldata.xml appears
in the program's execution directory. Listing 3 illustrates
the contents of that newly created file.
Listing 3. The generated XML data
<?xml version="1.0" encoding="UTF-8"?>
<java version="1.5.0_06" class="java.beans.XMLDecoder">
<string>Josephine Bloggs</string>
<string>Internet</string>
<string>1mbps</string>
<string>Gbyte</string>
<string>295</string>
</java>
|
You now transfer the file in Listing 3 across the network to a waiting
client—a simple matter with Java technology. Listing 4
shows a simple example.
Listing 4. Transferring a file across a network
byte[] bytes = new byte[BUFFER_SIZE];
FileInputStream inputFile = null;
try
{
File file = new File("xmldata.xml");
if (file.exists())
{
inputFile = new FileInputStream(file);
int ch = inputFile.read(bytes, 0, BUFFER_SIZE);
while (ch != -1)
{
output.write(bytes, 0, ch);
ch = inputFile.read(bytes, 0, BUFFER_SIZE);
}
}
|
The code in Listing 4 creates a buffer of length BUFFER_SIZE.
The constant BUFFER_SIZE can have the value
1024 or higher. The contents of the input file (xmldata.xml) are read into
the buffer through the call to the inputFile.read()
method. Once buffered, the file data is written through the
output.write() method into the socket of the
OutputStream object. This last step sends the data over the network to a waiting client. Such power contained in so little
code!
Next, you must get the client to process the incoming XML data.
A receiving Java client gets the
XML content (not an XML file)
How does a client receive the XML data? Again, with Java technology, this is a
straightforward matter. The data is received through a socket object.
Listing 5 shows code that receives the incoming data and
pushes it into an object of the ArrayList class.
The client must now resolve two important problems related to the number of data
items received. Because this is a loosely coupled scenario, you must assume
that the client doesn't know how many XML data items are contained in the service
profile (that is, the code in Listing 1). So, you must
identify some means to receive and process the exact number of data items.
The next (less difficult) problem is how to store the processed data. As you'll
see, Listing 5 solves both problems.
Listing 5. Extracting the embedded XML data
XMLDecoder d = new XMLDecoder(input);
try
{
while (true)
ArrayList<Object[]> rowList = new ArrayList<Object[]>();
{
String dataItem = (String)d.readObject();
System.out.println("XML decoded data: " + dataItem);
rowList.add(dataItem);
}
}
}
catch (Exception exc)
{
if (exc instanceof ArrayIndexOutOfBoundsException)
{
// No more records to process
System.out.println("Parsed all XML records - " +
"threw exception. Number of rows: " + rowList.size());
}
}
d.close();
|
You can determine how many incoming data items to expect with an infinite loop, while (true). This code loops until
the last data item is received, at which point an exception
(ArrayIndexOutOfBoundsException) is thrown. You must use
this exception mechanism unless the client already knows how many data items to expect.
XML data retrieved from the InputStream object is stored
in an object of the ArrayList class. This class is really
useful for such applications. When defined, an object of ArrayList
has a specific capacity that always matches the size of the underlying list. As you
add elements, the capacity of the ArrayList object expands
automatically. So, you don't have to worry about exceeding the boundary of an array,
because it's handled for you.
At this point, the client has a copy of the data in Listing 1.
The client can now modify the bandwidth element to the required value, then the
file-transfer process occurs in reverse, from the client back to the server. By
moving an XML file from the server to the client, the client has in effect consumed
the service. The updated data is sent back to the server to complete the
transaction. Of course, the service provider must then validate the incoming data
and provision the required bandwidth change.
The scheme described here starts with an XML file and a file transfer across the
network. The client receives the file data as a stream, which it parses into a
memory-resident object. The client then makes changes to the latter object and
reverses the procedure, sending the object back to the server.
A further service possibility exists in which the XML data file is transferred
intact from the server to the client. Here, the client uses some form
of file-transfer protocol such as FTP to get a complete copy of the file. Because
file transfer is standard technology, I won't go into detail except to say that
the client downloads a file copy of the service profile data in Listing 1. At this
point, the client has to parse and modify the file for transmission back to the
server. How might this type of scheme work?
How about an XML file-based Java mechanism?
The client now has a disk copy of the service profile. This file must be parsed to
extract the XML data. Surprisingly, that can be something of a challenge,
particularly if the file is large. The key is to use the appropriate parsing
tools. The tool you'll use here is dom4j, which
allows you to parse XML data into a Java object. You can use a Simple API for XML
(SAX)-based parser instead, but SAX is a lower-level technology. The dom4j tool
requires little effort, as you'll now see. Listing 6, an
excerpt from the supplied file ProcessEventXml.java, shows the main elements
required for using dom4j to parse a file.
Listing 6. dom4j processing the XML data
try
{
handler.treeWalk(handler.parse(new File(argv[0])));
}
catch (Throwable t)
{
t.printStackTrace();
}
}
public Document parse(File url)
throws DocumentException
{
SAXReader reader = new SAXReader();
Document document = reader.read(url);
return document;
}
public void treeWalk(Document document)
throws Exception
{
treeWalk(document.getRootElement());
}
|
Basically, two methods are required: parse() and
treeWalk(). When I run the compiled version of this
class, I get the output shown in Listing 7. If you want to
run this code yourself, be sure to download, install, and add to your CLASSPATH
a copy of dom4j. (The latter step consists simply of adding the appropriate JAR file to your CLASSPATH variable.) Then, compile the
ProcessEventXml.java file and run the program with the command:
java ProcessEventXml ServiceDefinition.xml
|
Listing 7. Using dom4j to process the XML file
java ProcessEventXml ServiceDefinition.xml
Josephine Bloggs Internet 1mbps 1Gbyte 95
|
As you can see, the XML data is neatly presented with little effort. The grunt work
is handled by dom4j. In fact, the bulk of the work is done in the
treeWalk() method, which is a recursive method that
isn't called until the end of the file is reached. Here, you see one of the
features of dom4j: in-memory processing. It's worth noting that it might be inappropriate to use this technique for particularly large XML files,
especially if your Java device is small. However, in the current instance, the XML
data set is small, so you shouldn't have any problems.
Your file-based client has now successfully accessed the XML data. The client can
change the data as required and write a new XML file. You can then transfer the
latter back to the server for processing. As before, the client has consumed the
service.
Conclusion
Java technology provides tailor-made solutions to the problems of SOA design and
implementation. Using a simple XML file-based service profile, you can easily move
client data around a network. Clients can view and modify this data, which is then
used to update a service. The service in this case is that of an ISP, but any
provider can use this approach.
An important element of such client service access is workflow. The commercial SOA
offerings tend toward BPEL for this functionality. A pilot SOA scheme might
use a simple messaging scheme instead—for example, the Java Message
Service (JMS) application program interface (API). As I mentioned in the
introduction, the merit of this approach is that an organization can get some
operational SOA experience before it makes the substantial investment required
to migrate to a commercial SOA solution.
Aside from workflow support, another important issue I didn't consider in this
article is security. If client users modify their service profiles, it might
be important to protect the underlying data. Again, Java technology provides a
range of options to do so.
You can also adopt a more coarse-grained approach whereby XML service profile data
is presented as files. Clients then use some scheme to transfer these files
into local storage, and you can use dom4j to parse and modify the file data. Again,
Java technology provides tools that blend simplicity with power. Using these
approaches, Java clients of any size and capability can fully participate in SOA
implementations.
Download | Description | Name | Size | Download method |
|---|
| Sample Java code for this article | x-xmlandsoa-code.zip | 6KB | HTTP |
|---|
Resources Learn
Get products and technologies
-
dom4j: Download the tool, an open source library to work with XML, XPath and XSLT on the Java platform and with full support for DOM, SAX and JAXP.
-
IBM trial software: Build your next development project with trial software available for download directly from developerWorks.
Discuss
About the author  | |  | Stephen Morris is the CTO of Omey Communications in Ireland. For the past 20 years, Stephen has worked for some of the world's largest networking companies on a wide range of software projects, including J2EE/J2SE-based network management systems, billing applications, porting and developing SNMP entities, network device technologies, and GSM mobile networking applications. He is the author of Network Management, MIBs and MPLS: Principles, Design and Implementation (Prentice Hall PTR, 2003) as well as several articles on network management and other topics for InformIT and OnJava.com. You can reach Stephen at stephenbjm@yahoo.com. |
Rate this page
|  |