Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:

Professional Java.JDK.5.Edition (Wrox)

.pdf
Скачиваний:
31
Добавлен:
29.02.2016
Размер:
12.07 Mб
Скачать

Chapter 11

is to use the AXIS bean serializer. The AXIS bean serializer takes a JavaBean and defines an XML mapping for it. This mapping is included when AXIS generates WSDL for the service, making third-party developers writing client programs to use the Web service not have to write any custom code — the WSDL generated allows them to auto-generate stubs, which then allow them to use the service transparently in their code. The <beanMapping> tag in the deployment descriptor identifies your JavaBean, and tells AXIS what XML namespace to use when serializing the type.

Note how, in the <service> tag, the provider is defined as java:RPC. There are essentially three main types of Web services. Each of these three services is encoded differently and possesses different attributes:

Remote Procedure Call Services. The weather example seen so far in this chapter is an example of an RPC-based Web service. Though other styles of Web services can be similar to RPC-based services in the sense that all normally follow a request-response paradigm, services designated as RPC use the SOAP encoding of types rather than XML schema. A huge emphasis on interoperability has made RPC-based services generally the most interoperable out of the box of the three.

Document-Based Services. Document-based Web services use XML schema to define the data types passed in SOAP messages. This support is useful when you want to pass XML data itself (and not simply encode in XML data that is not normally stored in XML). When you have existing XML schemas for certain XML file types, this format makes the most sense. This format has been gaining ground in terms of support and is almost as interoperable as RPC. In-depth knowledge of WSDL and XML schema is required to create and deploy document-based Web services.

Message-Style Services. Message services are the most generic of the three types. They give the developers complete control over the incoming XML. Message style services are less of a type of Web service as they are a method for implementing them. Message-style services are AXIS specific, but since the developer is given complete control over the XML, they can be used to implement document-based services. Implementing services in AXIS using the message-style is the most complex, but the most control possible is given to the developer. Message-style services are necessary when implementing advanced features such as session management, transactions, security, and other functionality on top of normal Web services.

RPC makes the most sense for your weather Web service for interoperability and simplicity’s sake. This method getWeather() is simple, and is not transporting a predefined XML data type, so there is no need for using document-based Web services (or its more complex sibling, message-style).

To actually deploy your Web service, the Java classes, book.Weather and book.WeatherGetter, must be in the classpath of the AXIS Web application. To do so, put the class files under the

<TOMCAT_HOME>/webapps/axis/WEB-INF/classes directory.

The last step to deploying your service is running the AXIS admin tool. This can be done as an ANT task. Here is the build.xml file to use to deploy the service:

<project name=”weatherService” default=”deploy” basedir=”.”> <path id=”axis.classpath”>

<fileset dir=”${axis.home}/build/lib”>

<include name=”**/*.jar” /> </fileset>

</path>

536

Communicating between Java Components and Components of Other Platforms

<taskdef resource=”axis-tasks.properties” classpathref=”axis.classpath” />

<target name=”deploy”> <axis-admin

port=”8080”

hostname=”localhost”

failonerror=”true”

servletpath=”/axis/services/AdminService”

debug=”true”

xmlfile=”deploy.wsdd”

/>

</target>

</project>

Deploy.wsdd and build.xml need to be in the same directory, and then ant can be run normally to deploy the service.

The service is now deployed to the URL:

http://localhost:8080/axis/services/Weather

WSDL for this service is found simply by appending ?wsdl to the URL:

http://localhost:8080/axis/services/Weather?wsdl

Now Web service clients can programmatically access the weather forecasts from random-weather.org.

Writing a Web Service Client

Writing a Web services client when you have the WSDL handy for the Web service is quick and simple. Since WSDL defines the interface and data types in a particular Web service (or multiple Web services), classes to use the Web service can be auto-generated. AXIS provides a tool, WSDL2Java, that does just that. This tool can be run as an ant task as well, and the build.xml file to create the client classes necessary to communicate with your weather Web service looks like this:

<project name=”weatherServiceClient” default=”wsdl” basedir=”.”> <path id=”axis.classpath”>

<fileset dir=”${axis.home}/build/lib”> <include name=”**/*.jar” />

</fileset>

</path>

<taskdef resource=”axis-tasks.properties” classpathref=”axis.classpath” />

<target name=”wsdl”> <axis-wsdl2java

output=”output”

testcase=”true”

verbose=”true”

537

Chapter 11

url=”http://localhost:8080/axis/services/Weather?wsdl” >

</axis-wsdl2java>

</target>

</project>

After creating the output directory (that is specified in the <axis-wsdl2java> tag), in this case, called output, running ant generates the following classes:

localhost.axis.services.Weather.WeatherGetter

localhost.axis.services.Weather.WeatherGetterService

localhost.axis.services.Weather.WeatherGetterServiceLocator

localhost.axis.services.Weather.WeatherGetterSoapBindingStub

org.randomweather.Weather

These generated classes depend on the jar files in the <AXIS_HOME>/build/lib directory to build a simple client application that accesses the Web service. Only three lines of code are required to access the Web service. It really is too easy:

int zipcode;

URL endpoint = new URL(“http://localhost:8080/axis/services/Weather”);

WeatherGetterService serviceLocator = new WeatherGetterServiceLocator(); WeatherGetter wg = serviceLocator.getWeather(endpoint);

Weather weather = wg.getWeather(zipcode);

The WeatherGetterServiceLocator class is used to bind a URL endpoint to the service. After that, the service can be accessed. The strength of Web services is in their simplicity, and as you can see, there really is not a whole lot to using a Web service. The complete code listing for the simple client application looks like the following code:

package book;

import java.net.URL;

import org.randomweather.Weather;

import localhost.axis.services.Weather.WeatherGetter; import localhost.axis.services.Weather.WeatherGetterService;

import localhost.axis.services.Weather.WeatherGetterServiceLocator;

public class WeatherClient {

public static void main(String[] args) throws Exception { int zipcode = 12345;

URL endpoint = null;

if (args.length >= 1) {

zipcode = Integer.parseInt(args[0]); if (args.length >= 2) {

endpoint = new URL(args[1]);

538

Communicating between Java Components and Components of Other Platforms

}

}

if (endpoint == null)

endpoint = new URL(“http://localhost:8080/axis/services/Weather”);

WeatherGetterService serviceLocator = new WeatherGetterServiceLocator(); WeatherGetter wg = serviceLocator.getWeather(endpoint);

Weather weather = wg.getWeather(zipcode);

System.out.println(“Weather for “ + zipcode); System.out.println(“\tDescription:\t\t” + weather.getDescription()); System.out.println(“\tHigh Temperature:\t” + weather.getHighTemp()); System.out.println(“\tLow Temperature:\t” + weather.getLowTemp()); System.out.println(“\tBarmometer:\t\t” + weather.getBarometer() + “ and “

+ weather.getBarometerDescription());

}

}

To see what gets sent and received over the HTTP connection, the Apache TCPMon application can again be used. You will set it to listen on port 8079 (and forward to port 8080), and run your client application as follows (assuming your CLASSPATH environment variable includes all the jars in the

<AXIS_HOME>/build/lib directory):

java book.WeatherClient 12345 http://localhost:8079/axis/services/Weather

The output follows:

Weather for 12345

 

Description:

Partly Sunny, Chance of snow

High Temperature:

91

Low Temperature:

24

Barmoter:

27.007242 and Rising

 

 

Looking at the TCPMon screenshot in Figure 11-17, you can see the SOAP message sent and the reply received. TCPMon is useful for debugging document-based and message-style Web services (since you have more control over the XML passed).

Client-Side Possibilities

There are more things you could do with your random-weather.org Web service than simply write a program that prints the information out. In Windows, you could write an application using the .NET framework that runs in the system tray. It would check the weather every hour or so, and update the information for the zip code of your choice. If someone ever wanted to write a larger client-side application that included the current random weather forecast, it could be easily integrated, no matter what language the application was being developed with, or what platform on which it ran. Other Web sites that wanted to include the weather could connect to your Web service and then display the results on their page. Because the data for your weather Web site is structured, it can now be used in a variety of places besides the Web browser.

539

Chapter 11

Figure 11-17

The Future

The future of Web services is unknown. There are many standards floating around, some by the W3C, some by OASIS. Standards for implementing secure Web services, transactional Web services, and reliable Web services are all being written and implemented. Once the major vendor implementations of Web services, such as Sun’s Java Web Services Developer Pack and Microsoft’s .NET framework, support these features out of the box, they may be practical to implement. Right now, there is minimal support for transactions and reliable messaging, and if your application needs those features today, Web services probably are not the best choice. Web services are moving away from simply enabling existing Web sites’ dynamic data to be accessed by a new generation of rich client-side applications, to enabling the same securely and transactionally.

540

Communicating between Java Components and Components of Other Platforms

Summar y

In this chapter, you have learned some possible ways to enable Java components in your application to communicate with external components in other applications or systems that could have been written in a variety of languages. Sockets provide the building blocks for all other technologies discussed in this chapter. With TCP/IP, they provide a reliable byte stream over a network that any language with a socket API can use. This is the lowest level of interprocess communication. Sockets are, however, not in themselves a guarantee of communication between two different components, a common protocol must also be spoken. In this chapter you implemented a small portion of the HTTP specification to gain an understanding of the immense undertaking it can be. RMI, CORBA, and Web services are all built on top of sockets and TCP/IP. RMI and CORBA implement complex protocols allowing them to provide such features as reliability, sessions, and transactions. They are cornerstone technologies for many enterprise systems. J2EE makes extensive use of RMI, as RMI combined with JNDI allows for the objects of a system to be transparently spread across multiple machines without any changes in the application’s code. RMI and CORBA have become intertwined to some degree since support for CORBA’s IIOP protocol was added to RMI. Now RMI and CORBA have basic interoperability, and this makes it easier for developers to integrate legacy CORBA systems into their modern J2EE equivalents.

Web services are the latest craze in distributed computing, and enable the evolution of the current World Wide Web of unstructured information to one of structured information. Web services are not as advanced technologically as RMI or CORBA, but there is power in their simplicity. Web services require minimal development effort to implement and, because all of their underlying protocols are human readable, are easy to debug. Web services have been prophesized to enable the next generation of applications that can better make use of the vast wealth of information found on the Internet.

None of the technologies used in this chapter is inherently better than any other. The right tool is needed for the right job. Sockets provide a low-level API that allows for the optimization and creation of new protocols. Some projects may require this — the remote control of external hardware, such as robotic devices, can usually be done best starting with sockets, and then building a more developer-friendly API layered on top. RMI and CORBA provide great foundations for distributed systems, and an understanding of them is necessary to utilize the full power of J2EE. The network latency implications of remote method calls must also be considered in any distributed system. Web services complement existing Web portals. They will be the simple mechanism by which information on the World Wide Web is shared for use by machines, not just by human eyes. Distributed applications and systems will probably make use of more than one component-to-component technology. As the integration of systems and information becomes easier with more platform-agnostic APIs and technologies, a whole new breed of informationcentric applications can arise.

541

Distributed Processing with JMS and JMX

This chapter shows you how to build distributed processing applications using two standard Java APIs. You can use this application as a starting point for CPU intensive processing tasks that require scaling beyond a single computer. In addition to scaling, the application discussed in this chapter can be managed very easily. It can be configured, deployed, even changed completely at run time using a standard Web browser.

Tough software problems often require large amounts of processing power. In some cases it is necessary to distribute this processing across several servers to meet the required demand. These systems are susceptible to bottlenecks and are difficult to manage. The two technologies discussed in this chapter — JMS and JMX — reduce the inherent complexities of this problem.

Java Message System (JMS) is the Java standard API for developing Message Oriented Middleware (MOM). JMS is one of the APIs that make up the J2EE architecture. JMS provides a robust message capability allowing you to send and process messages across several servers within a network.

Java Management Extensions (JMX) is also a Java standard API. JMX defines a way to provide manageable resources to other applications, provided they comply with the same architectural standard. This allows you to configure and manage applications at run time through standard management tools.

The first section, “Basic Concepts,” will explore the fundamentals of both JMS and JMX. It will not be an extensive laundry list of every method in the APIs; instead, it will be about the basics that you need to understand to be able to build a usable application. The focus of this chapter will be to expose you to a high value percentage of capabilities of these technologies that you can put to use in similar processing architecture problems. The second section, “Building a Distributed Application,” will show you how to build a usable example application. This application example will show how to model a generic business process. The third section, “Deploying the

Chapter 12

Application,” will show you how to leverage JMX technology to deploy and manage an application remotely at run time.

The code in this chapter can then be extended to support any business process that might meet your needs. You will also be able to download the complete example from the publishers Web site. The Web site will give you the specific details on configuring and running the application.

Again, this chapter will not cover every detail regarding JMS and JMX. The intent is to understand enough of the two APIs to guide the design decision-making process, and then allow you to test out and extend the example application. The example will also help you navigate the standard API documentation with confidence after becoming familiar with the core capabilities of these two technologies.

Basic Concepts

This first section of the chapter discusses the fundamental concepts of both JMS and JMX API. With JMS, you will look at the object model required to send and receive messages using the JMS architecture. The second section introduces the JMX architecture for deploying standard manageable application components.

JMS Fundamentals

Messaging systems are made up of application components that do not communicate directly with each other. All communication goes through an intermediary, called a destination. In JMS terms, a destination is either a queue or a topic. The first thing to understand when building a message system is the difference between these two concepts.

The difference between a queue and a topic involves how messages are delivered. It is critical to understand the two delivery models when selecting the correct destination type for the problem at hand. The best way to illustrate the difference between the two is to use two analogies.

Everything you want to learn about a queue you can observe with a visit to a bank on a Friday at 5:00 p.m. The line, or queue, is long. There are too many customers and not enough tellers. Each customer represents a Message or work the system needs to perform, while each teller represents a Message Receiver or a processing node of the system. As you add tellers, each teller processes fewer customers effectively distributing the processing load of the system. The key takeaway from this is that a queue allows you to scale processing.

A topic solves a completely different problem. An analogy that describes a topic well would be a newspaper delivery route. A Subscription List defines who gets a copy of the newspaper. The newspaper represents the message of the system. Unlike the queue delivery model, the adding of subscribers does not distribute the processing; it is for notification. It increases the total work the system must perform.

A rough guideline used to determine the destination type is to look at the purpose of the message being sent. If the purpose is to do something with the message, then use a queue. If the purpose is to inform or notify the component, then use a topic. Now you ought to understand the conceptual difference between a queue and a topic. The next section will provide an overview of the classes used in sending and receiving a message from a JMS destination.

544

Distributed Processing with JMS and JMX

Sending and Receiving a JMS Message

In this section, you will learn how to send and receive messages from a message destination in Java. A JMS application is a contract between a messaging system and a client API that processes messages. The message system is a server that manages the destinations, listens for client connections, and manages transactions. A JMS messaging system is provided commercially or through the open source vendor. The first part of this section is an overview of the client API that interacts with a messaging system. The second section will show how to send and receive messages using the client API.

The following table contains the classes used to communicate with a JMS messaging system. These are interfaces defined in the javax.jms.* package. As of JMS 1.1, the object model for handling both the queue and topic destination type is identical.

Class

Purpose

 

 

ConnectionFactory

Defines the behavior for creating a Connection to a JMS server. Con-

 

nectionFactory is an administered object bound to the JNDI context.

 

The messaging system will exhibit different behavior depending on

 

what type of ConnectionFactory is bound to the context. This behav-

 

ior is related to message delivery, message persistence, and transac-

 

tion support.

Destination

An object representing the queue or topic. Logically, it is where mes-

 

sages are stored between processing steps.

Connection

The Connection provides a unique link between the JMS server and

 

your client-messaging component. It is also responsible for address-

 

ing security and permission issues.

Session

The Session object coordinates the Message Traffic between the JMS

 

server and the client and is associated to a specific Connection object.

 

It also makes sure the communication between the server and client

 

are thread-safe.

MessagePublisher

Message publisher is able to send messages to a destination object.

MessageConsumer

A Message consumer has the ability to take messages from a destina-

 

tion, either synchronously or asynchronously.

MessageListener

Implementing the Message listener interface allows a client compo-

 

nent to register to receive messages asynchronously when they are

 

available.

Message

Last, but not least, the Message object represents the information

 

moving through the system.

 

 

Now that you understand the purpose of the JMS interfaces that you will be working with, the next step is to look at the code required to send and receive messages. There are four important steps to sending a message:

1.

2.

Create a connection to the Message system.

Establish a JMS session.

545

Соседние файлы в предмете [НЕСОРТИРОВАННОЕ]