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

Java & XML 2nd Edition solutions to real world problems phần 8 pps

42 269 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

Tiêu đề Java & XML, 2nd Edition Solutions To Real World Problems Phần 8 Pps
Trường học University of Example
Chuyên ngành Computer Science
Thể loại Bài báo
Năm xuất bản 2025
Thành phố Example City
Định dạng
Số trang 42
Dung lượng 865,18 KB

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

Nội dung

The updated CDAdder class public class CDAdder { public void addURL url, String title, String artist, String label throws SOAPException { System.out.println"Adding CD titled '" +

Trang 1

This program captures the URL of the SOAP server to connect to, as well as information needed to create and add a new CD to the catalog Then, in the add( ) method, the code creates the SOAP Call object, on which all the interesting interaction occurs The target URI

of the SOAP service and the method to invoke are set on the call, and both match up to values from the service's deployment descriptor from Example 12-5 Next, the encoding is set, which should always be the constant Constants.NS_URI_SOAP_ENC unless you have very unique encoding needs

The program creates a new Vector populated with SOAP Parameter objects Each of these represents a parameter to the specified method, and since the addCD( ) method takes two String values, this is pretty simple Supply the name of the parameter (for use in the XML and debugging), the class for the parameter, and the value The fourth argument is an optional encoding, if a single parameter needs a special encoding For no special treatment, the value null suffices The resulting Vector is then added to the Call object

Once your call is set up, use the invoke( ) method on that object The return value from this method is an org.apache.soap.Response instance, which is queried for any problems that resulted This is fairly self-explanatory, so I'll leave it to you to walk through the code Once you've compiled your client and followed the instructions earlier in this chapter for setting up your classpath, run the example as follows:

C:\javaxml2\build>java javaxml2.CDAdder

http://localhost:8080/soap/servlet/rpcrouter

"Riding the Midnight Train" "Doc Watson"

Adding CD titled 'Riding the Midnight Train' by 'Doc Watson'

Successful CD Addition

Example 12-7 is another simple class, CDLister , which lists all current CDs in the catalog I won't go into detail on it, as it's very similar to Example 12-6, and is mainly a reinforcement

of what I've already talked about

Example 12-7 The CDLister class

public class CDLister {

public void list(URL url) throws SOAPException {

System.out.println("Listing current CD catalog.");

// Build the Call object

Call call = new Call( );

call.setTargetObjectURI("urn:cd-catalog");

Trang 2

Parameter returnValue = response.getReturnValue( );

Hashtable catalog = (Hashtable)returnValue.getValue( );

Enumeration e = catalog.keys( );

while (e.hasMoreElements( )) {

String title = (String)e.nextElement( );

String artist = (String)catalog.get(title);

System.out.println(" '" + title + "' by " + artist);

System.out.println("Usage: java javaxml2.CDAdder " +

"[SOAP server URL]");

return;

}

try {

// URL for SOAP server to connect to

URL url = new URL(args[0]);

// List the current CDs

CDLister lister = new CDLister( );

C:\javaxml2\build>java javaxml2.CDLister

http://localhost:8080/soap/servlet/rpcrouter

Listing current CD catalog

'Riding the Midnight Train' by Doc Watson

'Taproot' by Michael Hedges

'Nickel Creek' by Nickel Creek

'Let it Fall' by Sean Watkins

Trang 3

'Aerial Boundaries' by Michael Hedges

That's really all there is to basic RPC functionality in SOAP I'd like to push on a bit, though, and talk about a few more complex topics

12.4 Going Further

Although you can now do everything in SOAP you knew how to do in XML-RPC, there is a lot more to SOAP As I said in the beginning of the chapter, two important things that SOAP brings to the table are the ability to use custom parameters with a minimal amount of effort, and more advanced fault handling In this section, I cover both of these topics

12.4.1 Custom Parameter Types

The most limiting thing with the CD catalog, at least at this point, is that it stores only the title and artist for a given CD It is much more realistic to have an object (or set of objects) that represents a CD with the title, artist, label, track listings, perhaps a genre, and all sorts of other information I'm not going to build this entire structure, but will move from a title and artist to

a CD object with a title, artist, and label This object needs to be passed from the client to the server and back, and demonstrates how SOAP can handle these custom types Example 12-8 shows this new class

Example 12-8 The CD class

package javaxml2;

public class CD {

/** The title of the CD */

private String title;

/** The artist performing on the CD */

private String artist;

/** The label of the CD */

private String label;

Trang 4

public String getArtist( ) {

public String toString( ) {

return "'" + title + "' by " + artist + ", on " +

catalog = new Hashtable( );

// Seed the catalog

addCD(new CD("Nickel Creek", "Nickel Creek", "Sugar Hill"));

addCD(new CD("Let it Fall", "Sean Watkins", "Sugar Hill"));

addCD(new CD("Aerial Boundaries", "Michael Hedges",

throw new IllegalArgumentException(

"The CD object cannot be null.");

Trang 5

// Return the requested CD

</isd:service>

The new element, mappings, specifies how a SOAP server should handle custom parameters such as the CD class First, define a map element for each custom parameter type For the encodingStyle attribute, at least as of Apache SOAP 2.2, you should always supply the value http://schemas.xmlsoap.org/soap/encoding/, the only encoding currently supported You need to supply a namespace for the custom type and then the name of the class, with this namespace prefix, for the type In my case, I used a "dummy" namespace and the simple prefix "x" for this purpose Then, using the javaType attribute, supply the actual Java class name: javaxml2.CD in this case Finally, the magic occurs in the java2XMLClassName and xml2JavaClassName attributes These specify a class to convert from Java to XML and from XML to Java, respectively I've used the incredibly handy BeanSerializer class, also provided with Apache SOAP If your custom parameter is in a JavaBean format, this serializer and deserializer will save you from having to write your own You need to have

a class with a default constructor (remember that I defined an empty, no-args constructor within the CD class), and expose all the data in that class through setXXX and getXXX style methods Since the CD class fits the bill here, the BeanSerializer works perfectly

Trang 6

It's no accident that the CD class follows the JavaBean conventions Most data classes fit easily into this format, and I knew I wanted to avoid writing my own custom serializer and deserializer These are a pain to write (not overly difficult, but easy to mess up), and I recommend you go to great lengths to try and use the Bean conventions

in your own custom parameters In many cases, the Bean conventions only require that a default constructor (with no arguments) is present in your class

Now recreate your service jar file Then, redeploy your service:

(gandalf)/javaxml2/Ch12$ java org.apache.soap.server.ServiceManagerClient http://localhost:8080/soap/servlet/rpcrouter xml/CDCatalogDD.xml

If you have kept your servlet engine running and the service deployed all this time, you'll need to restart the servlet engine to activate the new classes for the SOAP service, and redeploy the service

At this point, all that's left is modifying the client to use the new class and methods Example 12-10 is an updated version of the client class CDAdder The changes from the previous version of the class are highlighted

Example 12-10 The updated CDAdder class

public class CDAdder {

public void add(URL url, String title, String artist, String label)

throws SOAPException {

System.out.println("Adding CD titled '" + title + "' by '" +

artist + "', on the label " + label);

CD cd = new CD(title, artist, label);

// Map this type so SOAP can use it

SOAPMappingRegistry registry = new SOAPMappingRegistry( );

BeanSerializer serializer = new BeanSerializer( );

registry.mapTypes(Constants.NS_URI_SOAP_ENC,

new QName("urn:cd-catalog-demo", "cd"),

CD.class, serializer, serializer);

Trang 7

// Build the Call object

Call call = new Call( );

Vector params = new Vector( );

params.addElement(new Parameter("cd", CD.class, cd, null));

System.out.println("Usage: java javaxml2.CDAdder " +

"[SOAP server URL] " +

"\"[CD Title]\" \"[Artist Name]\" \"[CD Label]\"");

return;

}

try {

// URL for SOAP server to connect to

URL url = new URL(args[0]);

// Get values for new CD

String title = args[1];

String artist = args[2];

String label = args[3];

// Add the CD

CDAdder adder = new CDAdder( );

adder.add(url, title, artist, label);

The only really interesting change is in dealing with the mapping of the CD class:

// Map this type so SOAP can use it

SOAPMappingRegistry registry = new SOAPMappingRegistry( );

BeanSerializer serializer = new BeanSerializer( );

registry.mapTypes(Constants.NS_URI_SOAP_ENC,

new QName("urn:cd-catalog-demo", "cd"),

CD.class, serializer, serializer);

Trang 8

This is how a custom parameter can be encoded and sent across the wire I already discussed how the BeanSerializer class could be used to handle parameters in the JavaBean format, such as the CD class To specify that to the server, I used the deployment descriptor; however, now I need to let the client know to use this serializer and deserializer This is what the SOAPMappingRegistry class allows The mapTypes( ) method takes in an encoding string (again, using the constant NS_URI_SOAP_ENC is the best idea here), and information about the parameter type a special serialization should be used for First, a QName is supplied This is why the odd namespacing was used back in the deployment descriptor; you need to specify the same URN here, as well as the local name of the element (in this case "CD"), then the Java Class object of the class to be serialized (CD.class), and finally the class instance for serialization and deserialization In the case of the BeanSerializer, the same instance works for both Once all this is set up in the registry, let the Call object know about it through the setSOAPMapping-Registry( ) method

You can run this class just as before, adding the CD label, and things should work smoothly:

C:\javaxml2\build>java javaxml2.CDAdder

http://localhost:8080/soap/servlet/rpcrouter

"Tony Rice" "Manzanita" "Sugar Hill"

Adding CD titled 'Tony Rice' by 'Manzanita', on the label Sugar Hill

Successful CD Addition

I'll leave it up to you to modify the CDLister class in the same fashion, and the downloadable samples have this updated class as well

You might think that since the CDLister class doesn't deal directly with

a CD object (the return value of the list( ) method was a Hashtable), you don't need to make any changes However, the returned Hashtable contains instances of CD objects If SOAP doesn't know how to deserialize these, your client is going to give you an error Therefore, you must specify a SOAPMappingRegistry instance on the Call object

to make things work

12.4.2 Better Error Handling

Now that you're tossing around custom objects, making RPC calls, and generally showing up everyone else in the office, let me talk about a less exciting topic: error handling In any network transaction, many things can go wrong The service isn't running, an error occurs on the server, objects can't be found, classes are missing, and a whole lot of other problems can arise Until now, I just used the fault.getString( ) method to report errors But this method isn't always very helpful To see it in action, comment out the following line in the CDCatalog constructor:

public CDCatalog( ) {

//catalog = new Hashtable( );

// Seed the catalog

addCD(new CD("Nickel Creek", "Nickel Creek", "Sugar Hill"));

addCD(new CD("Let it Fall", "Sean Watkins", "Sugar Hill"));

addCD(new CD("Aerial Boundaries", "Michael Hedges",

"Windham Hill"));

Trang 9

addCD(new CD("Taproot", "Michael Hedges", "Windham Hill"));

}

Recompile, restart your server engine, and redeploy The result is that

a NullPointerException occurs when the class constructor tries to add a CD to

an uninitialized Hashtable Running the client will let you know an error has occurred, but not in a very meaningful way:

(gandalf)/javaxml2/build$ java javaxml2.CDLister

http://localhost:8080/soap/servlet/rpcrouter

Listing current CD catalog

Error encountered: Unable to resolve target object: null

This isn't exactly the type of information you need to track down the problem However, the framework is in place to do a better job of error handling; remember the DOMFaultListener you specified as the value of the faultListener element? This is where it comes into play The returned Fault object in the case of a problem (as in this one) contains a DOM org.w3c.dom.Element with detailed error information First, add an import statement for java.util.Iterator to your client source code:

Parameter returnValue = response.getReturnValue( );

Hashtable catalog = (Hashtable)returnValue.getValue( );

Trang 10

Vector entries = fault.getDetailEntries( );

for (Iterator i = entries.iterator(); i.hasNext( ); ) {

org.w3c.dom.Element entry = (org.w3c.dom.Element)i.next( ); System.out.println(entry.getFirstChild().getNodeValue( )); }

}

By using the getDetailEntries( ) method, you get access to the raw data supplied by the SOAP service and server about the problem The code iterates through these (there is generally only a single element, but it pays to be careful) and grabs the DOM Element contained within each entry Essentially, here's the XML you are working through:

<SOAP-ENV:Fault>

<faultcode>SOAP-ENV:Server.BadTargetObjectURI</faultcode>

<faultstring>Unable to resolve target object: null</faultstring>

<stacktrace>Here's what we want!</stackTrace>

</SOAP-ENV:Fault>

In other words, the Fault object gives you access to the portion of the SOAP envelope that deals with errors Additionally, Apache SOAP provides a Java stack trace if errors occur, and that provides the detailed information needed to troubleshoot problems By grabbing the stackTrace element and printing the Text node's value from that Element, your client will now print out the stack trace from the server Compile these changes and rerun the client You should get the following output:

C:\javaxml2\build>java javaxml2.CDLister

http://localhost:8080/soap/servlet/rpcrouter

Listing current CD catalog

Error encountered: Unable to resolve target object: null

12.5 What's Next?

The next chapter is a direct continuation of these topics More than ever, XML is becoming the cornerstone of business-to-business activity, and SOAP is key to that In the next chapter, I'll introduce two important technologies to you, UDDI and WSDL If you have no idea what those are, you're in the right place You'll learn how they all fit together to form the backbone

of web services architectures Get ready to finally find out what the web services, peer-to-peer craze is all about

Trang 11

Chapter 13 Web Services

In the last chapter, I focused on SOAP as a standalone technology; your application was

a SOAP client talking to a SOAP server, based on nothing but Java and a servlet engine While this is a perfectly good solution for applications in which you write all the clients and all the services, it is fairly limited for interoperating with other applications If you've heard anything about SOAP, it's the interoperability aspect that has gotten it such good press lately The last chapter was incomplete; it did not teach you how to do true servicing of other applications using SOAP as a transport mechanism This chapter fills in the rest of the picture, and solves the remaining problems in interoperability

To get you started, I apply some simple definitions to the overused term "web services." Although it's hard to quantify this term right now, since everyone is using it for their own particular flavor of software and architecture, some general principles apply In almost every definition of web services, you'll find that there is a need for an exchange of information with other applications This exchange needs a set of standards, and the two that are the most important (at least right now) are UDDI and WSDL I cover both and show you how they fit

in with SOAP Finally, I'll try and pull all these various acronyms and technologies together into one concrete example to finish off the chapter

13.1 Web Services

Web services seems to have become the next big thing in computing these days, so I've made room for this chapter in the second edition of this book However, trying to define the term is somewhat tricky; from one person's perspective, it may be correct, but from everyone else's it's probably completely off-base I'm left with trying to boil down the hype and differences in implementation to a simple set of concepts that remain true across the board

Web services is about interoperability More and more, applications must communicate with each other But the problems in communication grow, instead of shrink, with every new day

of technology innovation As more languages, increasingly complex data structures, and varied business needs develop, the difference between one system and another (even if they are performing the same business task!) also grows For systems to interoperate, there must be

a common language This isn't a language in the sense that Java is a language; programs not written in Java must have just as much access as those that are in Java Instead, it's a language that anyone with a dictionary can access; even if the words aren't the same, applications have

access to the words, which can be translated into something that can be understood

XML solves the problem of data transfer, and is one piece of that language It is accepted and usable in almost every programming language around: C, Perl, Python, LISP, Java, Pascal, C#, Visual Basic the list goes on and on However, web service frameworks seek to go

quite a bit further The key to interoperability is not just data, but what data What information

can I get from your system? What can you find out from mine? In other words, there must be

a means of broadcasting what services an application makes available And this is where we have, until recently, had a gaping hole

However, recent additions to the web services realm have begun to fill this hole First, UDDI provides a means of discovering other services and registering your services for others to discover Second, WSDL offers a way to provide the needed information about a discovered

Trang 12

service to allow a client to interact with it I've purposely left out the explanation of what UDDI and WSDL stand for and mean for now, because I want to focus on the big picture Figure 13-1 shows how the process flows To begin, a service provider codes up a service (like you did in the last chapter) This service could be as simple as adding CDs to a catalog,

or as complex as storing the VIN (vehicle identification numbers) for all automobiles registered in Massachusetts that are used by the government As long as the service is web-accessible, it's a candidate for a service registry This is all part of the UDDI portion of the picture UDDI also allows a user to search all registered services for a specific service name, like "cd-catalog" or "govt-bin-numbers." The registry returns all the matching services

Figure 13-1 The web services process

Hopefully, the client has found the desired service But interaction takes more than just a name; it requires the URL to connect to and the parameters required, as well as the return value This is accomplished through XML in a WSDL format, which I cover as well And then, your client interacts with the located service, knowing (because of WSDL) you are using the service correctly Life is grand, and all because of web services Of course, I've skimmed over all the hard parts, but I'll delve into some of that complexity now that you have the big picture

13.2 UDDI

With no further suspense, I want to define what UDDI is It stands for Universal Discovery,

Description, and Integration, and is most often associated with the word "registry."

The primary place to learn about UDDI is its web site, http://www.uddi.org/ (shown in Figure 13-2), also the home of the UDDI registry that is so important in registering and locating services This site describes the UDDI project, which seeks to create and define

a complete framework for the exchange of data I've been talking about in this chapter The initiative is supported by both IBM and Microsoft, so it looks like it's around for the long haul

Trang 13

Figure 13-2 The UDDI web site

The core of this is the network of services about which UDDI stores information The ability

to register a new service and search for an existing one is part and parcel of this registry, and

is available online at the UDDI web site All that is required is a simple registration process Neither IBM nor Microsoft require a company or even an individual to pay high fees to make their services publicly available Because of this, there are many, many more services being registered every day than a "for-profit" system would engender

That's all that there really is to UDDI There is little complexity in the use of UDDI; the hard stuff is all in implementation, which you and I aren't really interested as a service provider or consumer There are several UDDI implementations available that can be downloaded and run locally, and I prefer jUDDI over the others You can check out this Java-based open source project at http://www.juddi.org/ Additionally, IBM's web services toolkit (covered in Section 13.3 later in this chapter) includes a trial version of a private UDDI registry I'm not going to cover jUDDI or the IBM UDDI registry here, because they don't aid in understanding how to use UDDI, but rather how to implement it If you have an interest in seeing what drives a UDDI registry, I'd recommend you check out jUDDI If you are just interested in writing web services and making them available to others, though, I wouldn't worry too much about it Finally, I leave out the specifics of registering and searching for services until the final section, in which I walk you through a fairly complex real-world example using SOAP, UDDI, and WSDL

13.3 WSDL

WSDL is the Web Services Description Language The entire specification is online at

http://www.w3.org/TR/wsdl, and describes everything you need to know about a service in order to interact with it Like UDDI, it's a fairly simple piece of technology on its own (really, it's not even technology; it's just markup), but becomes extremely important in the overall web services picture The WSDL file describes several critical pieces of information a service client would need:

Trang 14

• The name of the service, including its URN

• The location the service can be accessed at (usually an HTTP URL address)

• The methods available for invocation

• The input and output parameter types for each method

Each of these pieces of data on their own are fairly useless, but together, they represent the complete client picture of the service Additionally, a WSDL document incorporates elements

of XML Schema, XML-RPC-style parameters, and quite a bit of everything else you've read about so far Example 13-1 is a portion of a WSDL schema for the CD catalog from the last chapter; it only describes the getCD( ) method of the service It's not complete, but it should give you an idea of what a WSDL document looks like

Example 13-1 Portion of a WSDL document

xmlns:cdXSD="http://www.oreilly.com/javaxml2/cd-catalog.xsd" xmlns="http://schemas.xmlsoap.org/wsdl/"

>

<types>

<schema

targetNamespace="http://www.oreilly.com/javaxml2/cd-catalog.xsd" xmlns="http://www.w3.org/2000/10/XMLSchema">

<element name="title" type="string" />

<element name="artist" type="string" />

<element name="label" type="string" />

Trang 15

As you can see, this is a fairly verbose format for describing a service; however, it's also easy

to understand First, any types that must be passed across the wire are described using the types element, and an XML Schema-style syntax

Currently, WSDL specifications are using the 2000 version of the XML Schema specification, and not the finalized April 2001 XML Schema specification You'll need to use the slightly older schema constructs until the WSDL specification is brought completely up to date

Next, the message element is used to define interaction from the client to the server, and the server to the client These are combined in the portType element to define available operations (you would find additional available methods in this section as well) The binding element details how the operations can be accessed and the URN where they are accessible, and the service element brings all of this together Thinking about this process as a hierarchy will help keep everything straight in your head

Trang 16

SOAP's All You Got?

Don't get the idea that a SOAP service is the only type of web service around It's certainly possible to build a program (or programs) that interact with clients through some other means, and represent that interaction through a WSDL file For example,

an XML-RPC service fits the bill pretty nicely; even though it doesn't have an envelope and custom parameter support, it still can easily interact with clients and represent its input and output parameters in WSDL However, almost all the services I've seen (and I've seen a lot!) are SOAP, so it is certainly the overriding trend Still, keep in the back of your mind the ability to use any program as a service, not just SOAP ones

Currently, the Apache SOAP implementation does not directly use WSDL documents In other words, you can't consume a WSDL document and automatically get a client class, for example While some of the other platforms, such as Microsoft, are further along, Apache's Axis project is working on this functionality For now, you'll need to interpret the WSDL document on your own, and then manually code up a client That's more fun anyway

13.4 Putting It All Together

With that fairly basic understanding of WSDL added to the UDDI discussion, you're ready for

a complete web services example In this section, I detail the process of writing a SOAP service (a messaging one, this time), registering it with a UDDI registry, finding it using UDDI, getting the WSDL descriptor, and then interacting with the service via a client

For the example, I add a little more complexity Here's the scenario CDs-R-Us is a new company that wants to provide CDs to distributors around the world Since they are (noticeable) late to market, they seek to gain business by providing a high-tech interface, using web services to make interaction easy They are going to provide the ability to send XML messages requesting CDs through SOAP Their applications will fulfill these orders by looking up the CD on their catalog server (running, of course, a heavy-duty version of the CDCatalog service from last chapter), and then returning an invoice There are actually two SOAP transactions going on: one from the client to CDs-R-Us, which is messaging-based, and one internal to CDs-R-Us, which is RPC-based Figure 13-3 shows the complete process flow They also want to register their messaging service with a UDDI registry so potential clients can find them

Figure 13-3 Process flow for the example application

Trang 17

turn starts an interaction with another business If this still seems odd, ask your home builder

how many subcontractors he employs, and then ask each of them how many subcontractors

they employ; it would probably blow your mind!

First, let's define the purchase order (PO) format that CDs-R-Us requires The XML Schema for the PO document is shown in Example 13-2

Example 13-2 po.xsd XML Schema

<xs:element name="name" type="xs:string"/>

<xs:element name="street" type="xs:string" />

<xs:element name="city" type="xs:string" />

<xs:element name="state" type="xs:string" />

<xs:element name="postalCode" type="xs:short" />

Trang 18

<xs:element name="cd">

<xs:complexType>

<xs:attribute name="artist" type="xs:string" />

<xs:attribute name="title" type="xs:string" />

</xs:complexType>

</xs:element>

</xs:schema>

With that schema in place, a typical PO would look something like Example 13-3

Example 13-3 Example PO for CDs

<cd artist="Brooks Williams" title="Little Lion" />

<cd artist="David Wilcox" title="What You Whispered" />

</order>

</purchaseOrder>

The service should accept an XML document like Example 13-3, figure out what information

is relevant, and then pass that information on to the CD catalog service through RPC Once it gets a response, it formulates some sort of invoice or acknowledgment for the messaging client, and sends that message back I keep things simple for the purpose of this example, but you can easily see where to add additional processing as we walk through the code

Writing a service that accepts XML messages is a bit different from writing one that accepts RPC requests; with messaging, you need to interact more directly with the request and response objects, and your class needs to know about SOAP Remember that in the RPC-style processing, the class receiving requests didn't know a thing about RPC or SOAP, and was therefore encapsulated fairly well With a messaging-style service, all methods that can be interacted with must follow this convention:

public void methodName(SOAPEnvelope env, SOAPContext req, SOAPContext res) throws java.io.IOException, javax.mail.MessagingException;

This should feel somewhat similar to how servlets work; you get a request and response object to interact with, as well as the actual SOAP envelope for the message sent across the wire You can see the expected IOException that may be thrown when network and related errors occur; additionally, a MessagingException (from the JavaMail package) can result from problems with the SOAP message envelope Additionally, the method name must be the same as the name of the root element of the message content! This is easy to forget; in our case, it means that the method receiving XML must be called purchaseOrder, since that is the root element in Example 13-3 With this knowledge, it's possible to set up the skeleton for

a message service This skeleton is shown in Example 13-4; in addition to putting in

Trang 19

the framework for receiving a SOAP message, it also has the logic to make the appropriate call to the CDCatalog service on another machine I've left a comment as a placeholder for the messaging code we'll look at in a moment

Example 13-4 Skeleton for CDs-R-Us messaging service

public class OrderProcessor {

/** Mapping for CD class */

private SOAPMappingRegistry registry;

/** The serializer for the CD class */

private BeanSerializer serializer;

/** The RPC Call object */

private Call call;

/** Parameters for call */

private Vector params;

/** Response from RPC call */

private Response rpcResponse;

/** The URL to connect to */

private URL rpcServerURL;

public void initialize( ) {

// Set up internal URL for SOAP-RPC

try {

rpcServerURL =

new URL("http://localhost:8080/soap/servlet/rpcrouter"); } catch (MalformedURLException neverHappens) {

// ignored

}

Trang 20

// Set up a SOAP mapping to translate CD objects

registry = new SOAPMappingRegistry( );

serializer = new BeanSerializer( );

registry.mapTypes(Constants.NS_URI_SOAP_ENC,

new QName("urn:cd-catalog-demo", "cd"),

CD.class, serializer, serializer);

// Build a Call to the internal SOAP service

call = new Call( );

// Set up SOAP environment

initialize( );

// Set up list of CDs successfully ordered

List orderedCDs = new LinkedList( );

// Set up hashtable of failed orders

Hashtable failedCDs = new Hashtable( );

// Parse incoming message and get list of CDS ordered

// Loop through each ordered CD from the PO request

Trang 21

// Verify it's by the right artist

In this example and in the rest of the chapter, I use the hostname

http://localhost:8080 to represent a SOAP service running on your local

machine Most of you will be testing the example locally, and this will help you avoid putting in fictional hostnames and getting frustrated when things don't work

In a real environment you would expect the client to connect to a

CDs-R-Us machine, like http://www.cds-r-us.com, and the messaging service

to connect to an internal machine running the CD catalog, such as

http://catalog.cds-r-us.com, perhaps behind an external firewall Still,

I'd rather your code work right away than try and put false hostnames in the example code That's why everything uses the local machine as the hostname

I briefly run through what is going on here, and then get to the interesting aspect: the messaging interaction First, the initialize( ) method is used to set up an RPC call for each client This Call object is used and reused, so no resources are wasted on a single client

At the same time, each client gets their own Call object, ensuring that synchronization and threading issues don't surface Next, some storage is set up: a List for successful orders, and

a Hashtable for failed ones The Hashtable has the title of the ordered CD as the key, and error information as the value Then, the SOAP message from the client would be read (here's where I've left a placeholder, for now) For each CD ordered, a looping process begins The

CD title and artist are extracted from the message, and an RPC call is invoked to obtain the requested CD object Depending on the result from the request to the CD catalog, the CD is added to the list of successful or failed orders At the end of the loop, a message would be constructed and sent back to the client

It's worth noting that the CDCatalog is a simple version, and not complete in this context

A real CD catalog service would probably check for a CD in its inventory, ensure copies are available, remove one CD from the inventory, report its SKU, etc In this case, all the CD

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

TỪ KHÓA LIÊN QUAN