21. XML and Web Services

ONCE upon a time, not so long ago, Web services were going to be the next big thing. Web services referred to specific methods of making Web server functionality available to other applications, and everyone fully expected an interoperable nirvana of communicating systems. The air was pungent with the smell of unwieldy acronyms like WS-I, XML-RPC, WSDL, and UDDI, and everyone had to make sure that their products and technologies were going to work with the coming wave of Web services. Collectively, this approach is known as WS-*, and it is more about a distributed computing scheme (think CORBA or DCOM) than anything specific to the World Wide Web.

Web services did turn out to be one of the next big things. As usual, things didn’t turn out quite how everyone planned. While the cool kids like Google and Flickr are exposing their functionality to developers, and Web 2.0 seems well underway, the emphasis has faded from WS-*. A different, lighter approach called Representational State Transfer (REST) is a popular way to make Web services available to client applications.

The Extensible Markup Language (XML) is here to stay, regardless of the fate of its various Web services’ cousins.

Java ME got caught up in the WS-* hype, and the result was JSR 172, which defines an XML parsing (JAXP) API and a JAX-RPC API for consuming WS-* services. The XML parsing API will probably be useful well into the future, but the JAX-RPC API will most likely appeal only to developers who must connect a MIDlet to some existing SOAP service. Developers of entirely new systems should strongly consider a RESTful approach.

This chapter describes how to use the XML parsing API, how to call WS-* Web services using the JAX-RPC API, and how to work with RESTful Web services. Examples will show how to parse a Rich Site Summary (RSS) feed, how to invoke a WS-* Web service, and how to write a RESTful client for the Flickr photo-sharing service.

21.1. Parsing XML

Regardless of the future of Web services, XML is an important part of the computing world. JSR 172’s JAXP API is useful in a wide variety of applications.

Several different flavors of XML parsers are available in the desktop world. The JAXP API conforms to the Simple API for XML (SAX) standard, defined here:

http://www.saxproject.org/

The SAX parts of the API live in org.xml.sax, while the rest of the JAXP API is in javax.xml.parsers.

A SAX parser is a push parser, which means it runs through an entire document, spitting out events as it goes. In your application, you supply a handler (a listener) that gets notified whenever the parser finds something in the document.

The parser itself is jaxp.xml.parsers.SAXParser. You can get one from a SAXParserFactory, like this:

Image

You can use methods in SAXParserFactory to change the options on the parser returned by newSAXParser(). For example, you can specify whether or not you want a validating parser.

21.2. Creating a Handler

Once you’ve got a parser, you need to supply a handler and give it a document. Your handler should be a subclass of DefaultHandler (in org.xml.sax. helpers), and the document to be parsed is represented by an InputStream or an InputSource.

Image

Your DefaultHandler subclass is where most of the action happens. DefaultHandler has empty methods that get called by the parser. To do something interesting, override some or all of these methods in your handler subclass.

Here is a class, CheapHandler, which overrides three of DefaultHandler’s methods. It uses the startElement() and endElement() methods to keep track of the current element hierarchy. In addition, it overrides characters() to find out when character data is parsed.

Image

Image

CheapHandler is a simplified handler for XML parsing. I use it in the rest of the examples in this chapter. You can create a simple subclass of CheapHandler and override the processCharacters() method or processStart() method. Each method is passed a tree argument, which represents the parser’s current position in the document hierarchy. Nested tags are separated by a pipe character.

21.3. Parsing RSS

RSS is a simple XML format used for summaries of blogs, news Web sites, and other content. RSS files are placed in known locations at a Web site and updated to reflect updates to the main content of the Web site. RSS files are often called feeds.

This section presents a MIDlet that retrieves an RSS feed that contains the top ten songs sold in the iTunes music store. You could easily modify this MIDlet to retrieve other types of RSS feeds.

Image

Image

Image

You can see the network connection and XML parsing happens in run(), performed in a separate thread.

The SAX handler is TopTenHandler, a simple subclass of CheapHandler. Whenever characters are encountered that are part of a title element, they are appended to the main form.

One of the nice features of TopTenMIDlet is that information is placed on the screen as soon as it is parsed (see Figure 21.1). This capability is especially important on wireless devices that are likely to have relatively slow network connections.

Figure 21.1. Information is displayed as it is parsed

Image

21.4. Parsing XML without JSR 172

Not many current devices have support for either of the JSR 172 APIs. However, if you just want to parse XML in a MIDlet, you can embed a small parser in your application. kXML 2 is an excellent choice:

http://kxml.sourceforge.net/

For a dated look at the world of XML parsers in Java ME, try this article:

http://developers.sun.com/techtopics/mobility/midp/articles/parsingxml/

The size of the XML parser adds directly to your MIDlet suite JAR file size, but if that’s not a problem, you can fairly easily incorporate XML parsing in your application without requiring JSR 172 support on your target devices.

The kXML 2 JAR file is only 43 KB, and if you use an obfuscator, the impact on your MIDlet suite JAR can be much smaller.

The example code for this chapter includes a rewritten TopTenMIDlet that uses kXML. You can run this version of the application on any MIDP 2.0 device without worrying about JSR 172 support. Look in the kb-ch21-kxml project for the rewritten TopTenMIDlet and a rewritten CheapHandler helper class. The obfuscated JAR file size for this project, including another MIDlet from later in this chapter, is just 16 KB!

Using the kXML parser, org.kxml2.io.KXmlParser, is fabulously easy. Create one and point it at a Reader using the setInput() method:

Image

Then sit in a loop and call the parser’s next() method, which parses the next thing in the document. Call methods on the parser to find out what was just read. Here is an example that parses through the document until it reaches the end:

Image

For example, if the event type is KXmlParser.START_TAG, you can find out the name of the tag with getName(). If the event type is KXmlParser.TEXT, you can retrieve the text with getText().

21.5. Using WS-* Web Services

WS-* Web services are a kind of distributed computing. To use a WS-* Web service, you have to generate stub classes (during development) that represent the Web service. At runtime, you call methods on the stub class to invoke methods on the Web service. In the Java platform, this is very similar to Remote Method Invocation (RMI).

WS-* Web services are described by a Web Service Description Language (WSDL) file. To use a Web service in your application, you first must generate stub classes based on the WSDL description. Your development tool should be able to do this for you. In the Sun Java Wireless Toolkit, choose File > Utilities…, then launch the Stub Generator utility.

In NetBeans Mobility Pack, right-click on your project and choose Properties. Select Platform in the left pane, then click on Manage Emulators… on the right side. Click on the Tools & Extensions tab, then click Open Utilities. Finally, launch the Stub Generator.

You have to specify the location of the WSDL file, the destination for the generated stub classes, and to which package you would like the stubs to belong.

Once you have stubs, using them is pretty easy. Suppose you want to use a Web service that returns speeches from Shakespeare’s plays:

http://www.xmlme.com/WSShakespeare.asmx

First, generate the service stubs. Here is how to invoke the service:

Image

First, create a ShakespeareSoap object that represents the Web service. Then you can call methods, like getSpeech(). Methods called on remote objects can throw RemoteException if something goes wrong with the network communication.

Following is the complete MIDlet example, BillMIDlet. It assumes that the Shakespeare Web service stubs are generated in the bill package. The code example downloads for this chapter include the stub package and classes.

The Shakespeare Web service returns results as very simple XML documents, so BillMIDlet uses the JAXP API to parse the results and present them on the screen. BillHandler is a simple CheapHandler subclass that takes care of the details. (See Figure 21.2 on page 307.)

Figure 21.2. Web services and William Shakespeare

Image

Image

Image

Image

To run BillMIDlet, enter a few words from a speech and choose the Go command.

21.6. Harness the World

The Web services programming model that is spanking traditional WS-* Web services is Representational State Transfer, or REST. REST is an awful name, and it’s hard to understand exactly what it means. Like the Pirate Code, it is more of a set of guidelines than a specification or definition.

The main principles of REST are as follows:

  • Simple URLs. Clients can retrieve information and make things happen by constructing URLs. This means that it’s easy to make things happen, and it’s also easy to change the implementation on the server side if the need arises.
  • XML responses. Information passes from the server to the client as XML, which means it’s well-structured and reliable to read. Responses usually include whatever information the client needs to retrieve more information or perform actions on the server side.
  • Good documentation. A key feature of a RESTful Web service is clear, definitive documentation. This is useful for clients, because it tells them exactly how to use the Web service. It is also useful for the Web service implementers, because it tells them exactly how the Web service must appear to the rest of the world.

In general, REST Web services are lighter and more flexible than WS-* Web services. For an allegorical look at the Web services debate, try Elliotte Harold’s essay here:

http://cafe.elharo.com/web/rest-vs-soap-a-parable/

The Java platform community seems to be catching up with the REST philosophy, as evidenced by the recent appearance of JSR 311:

http://jcp.org/en/jsr/detail?id=311

21.7. A Mobile Client for Flickr

The Flickr photo sharing service is a great example of a RESTful Web service. The API for Flickr is documented here:

http://www.flickr.com/services/api/

To use this API, and to run this example, you need to get a developer key from Flickr. For experimentation, it is easy and free, but if you’re going to create commercial applications, you must follow a more rigorous application process. Consult Flickr’s Web site for complete details.

FlickrMIDlet loads the developer key from an application property. To successfully run this example, you must place your developer key in the flickr-apikey application property.

FlickrMIDlet makes three calls into the Flickr API.

  1. flickr.people.findByUsername returns an identification number (NSID) that corresponds to a Flickr user name. An example URL for this method is here, split across multiple lines for readability:

    Image

    This method returns a very brief XML document that associates the user name to an NSID. Here is an example response:

    Image

  2. flickr.people.getPublicPhotos returns a list of information about the public photos for a given NSID. Here is an example request URL:

    Image

    The response, again, is a simple XML document, something like this:

    Image

  3. The photos themselves are retrieved by creating URLs based on the information returned from flickr.people.getPublicPhotos. In particular, the id, secret, server, and farm attributes are used. The URL scheme is described in the Flickr API documentation. FlickrMIDlet uses a special designation to retrieve thumbnail photos, which are at most 100 pixels on a side, great for little mobile screens. Here is the image URL corresponding to the first item in the list above.

    http://farm1.static.flickr.com/154/390271118_7676416608_t.jpg

In FlickrMIDlet, two handler classes (FlickrUserHandler and FlickrPhotoListHandler) extract the important parts of each XML reply.

The photos themselves are returned as a byte stream of JPEG image data. Many MIDP implementations can decode JPEG data, and MSA requires this capability.

Here is the source code for FlickrMIDlet, which runs the whole show. The network connections are implemented in lookupUser(), lookupPictures(), and lookupPicture(), all of which are called from run(), which lives in a separate application thread. The MIDlet keeps track of the current user name so that it doesn’t perform any unnecessary network work.

Image

Image

Image

Image

Image

Both parser handler classes inherit from CheapHandler, which you’ve already seen. Here is the handler that extracts an NSID from a user name query response.

Image

The handler for a user’s public photo list is a little more complicated. As it reads the document, it creates an URL for retrieving each photo.

Image

To run FlickrMIDlet, just enter a Flickr user name and select the Next command. FlickrMIDlet retrieves the user’s NSID, photo list, and the first photo in the list (see Figure 21.3).

Figure 21.3. Flickr pictures on your phone!

Image

Keep choosing Next to see the rest of the photos in the user’s list.

In the source code download, the kb-ch21-kxml project contains a rewritten version of FlickrMIDlet that uses the kXML 2 parser instead of the JSR 172 API. You can run this version of FlickrMIDlet on any MIDP 2.0 device.

FlickrMIDlet is a nice toy and a great example of infusing a MIDlet with the massive power of the Internet. If you’d like to explore this example further, here are some ideas for improvements:

  • Error handling could be better. For example, if you enter a user name that does not exist, FlickrMIDlet quietly reverts to the previous user name without telling you why. What about valid user names that have no public photos?

  • It would be wise for FlickrMIDlet to keep a cache of the current user’s images. Network access is expensive in terms of time (and sometimes money), so caching loaded images would enable repeated viewing of a single user’s images.

  • FlickrMIDlet would benefit from a custom Canvas user interface for easier browsing and a prettier look.

  • It would be nice to save the current user name in a record store so it pops up automatically next time you start FlickrMIDlet. A fancier approach would be to keep a list of favorite user names for quick browsing.

21.8. Summary

XML is a great format for structured data. The JSR 172 JAXP API provides basic tools for parsing XML documents. Most of the work is in a DefaultHandler subclass, which gets notified about interesting events as the parser works through a document. XML is used as the basis for Web services, whether they are the heavy WS-* Web services or lighter RESTful Web services. The JSR 172 JAX-RPC API provides stub-based access to WS-* Web services. RESTful Web services can be invoked with specially constructed URLs, while XML results can be parsed using JAXP.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
3.146.37.250