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.
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.
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 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.
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.
| Description | Name | Size | Download method |
|---|---|---|---|
| Sample Java code for this article | x-xmlandsoa-code.zip | 6KB | HTTP |
Information about download methods
Learn
-
Enable C++
applications for Web service using XML-RPC (Karthik Subbian and Ramakrishnan Kannan, developerWorks, June 2006): Read a step-by-step guide to exposing
C++methods as services. -
Introduction to RSS: Read more about Web feed formats from Wikipedia, the free encyclopedia.
-
IBM XML certification: Find out how you can become an IBM-Certified Developer in XML and related technologies.
-
XML technical library: See the developerWorks XML Zone for a wide range of technical articles and tips, tutorials, standards, and IBM Redbooks.
-
developerWorks technical events and webcasts: Stay current with technology in these sessions.
- The technology
bookstore: Browse for books on these and other technical topics.
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
- Participate in the discussion forum.
-
XML zone discussion forums: Participate in any of several XML-related discussions.
-
developerWorks blogs: Check out these blogs and get involved in the developerWorks community.
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.




