Chapter 14. Creating Web Services with Java

The Java Web Services Developer Pack is a toolkit provided by Sun to demonstrate how to build Web services solutions using Java. The toolkit is meant for teaching purposes, not production use. Sun is in the process of rolling many of this pack’s API’s and features into an upcoming release of the J2EE toolkit. It is useful to see how Sun’s toolset works as many of the other vendor’s tools build on the principles found in this tool suite. In this hour, you will see

  • What is included in the Java Web services Developer Pack

  • How to build Web services solutions by utilizing the Java Web Services Developer Pack

  • How to deploy and register your service with the provided Tomcat server so that it can be used by clients

  • How to write a simple client that can interact with your new service

What’s Included in the Java Web Services Developer Pack

As you’ve seen in previous hours, Web services can be built using a variety of languages on both the server side where the service resides and on the client side. In an effort to help jump-start the adoption of Web services, Sun has created the Java Web Services Developer Pack. This toolkit provides everything needed to build and deploy Java-based Web services solutions. It is meant to serve as the reference implementation for all other Java-based Web services. As such, it is not meant to replace a full-on commercial implementation, only to provide a basis for learning and a pure implementation of the Web services specifications.

Note

What’s Included in the Java Web Services Developer Pack

See Appendix B, “Installing the Java Web Services Developer Pack,” for information on how to download and install the Java Web services Developer Pack.

The Java Web Services Developer Pack contains a number of tools for building Web services. These include the Apache Tomcat servlet engine (upon which your Web service will run) and the Jakarta-ant tool (which is a tool similar to the Unix “make” tool). Because ant is packaged, we’ll use that to handle all of the build and deployment process in this hour.

The toolkit also packages together a number of Java extension libraries that are used to process various pieces of the Web services suite. It’s not really important to know too much about these APIs because the tools found in the toolkit will abstract away much of their use. Instead, just know that they’re there, and what they do at a high level. These APIs include

  • Java API for XML Processing (JAXP)—Provides a standardized interface for different types of XML parsers. By writing to this API, the underlying XML parser can be switched out for ones with different performance and memory characteristics without forcing a change in user code.

  • Java API for XML-based RPC (JAX-RPC)—Gives developers the hooks needed to build Web applications and Web services incorporating XML-based RPC functionality according to the Simple Object Access Protocol (SOAP) 1.1 specification. Typically, this is the API that you’ll use the most for building Web services.

  • The Java API for XML Messaging (JAXM)—Provides much of the underlying code needed to create SOAP messages and perform the communication between systems.

  • The SOAP with Attachments API for Java (SAAJ)—Enables developers to produce and consume messages conforming to the SOAP 1.1 specification and SOAP with Attachments note.

  • The Java API for XML Registries (JAXR)—Gives a standard Java API for accessing different kinds of XML registries. We’ll use this API when communicating with a UDDI or an ebXML registry.

  • The Java Architecture for XML Binding (JAXB)—Makes XML easy to use by compiling an XML schema into one or more Java classes.

In addition to these APIs, the toolkit includes the Java servlet and Java Server Pages (JSP) APIs. These are not directly needed for building Web services, but are supported by the Tomcat engine.

Note

The Java Architecture for XML Binding (JAXB)—

If you’d like to dig deeper into the Java Web Services Developer Pack, a tutorial is available at http://java.sun.com/webservices/docs/1.0/tutorial/index.html.

The Java Web Services Developer Pack also includes several support tools that are used to help with the creation of the interface code. Sun refers to these pieces of code as ties (the Service side module) and stubs (the client side modules). Figure 14.1 shows how the system is structured.

The Java Web Services Developer Pack structure for JAX-RPC service communications.

Figure 14.1. The Java Web Services Developer Pack structure for JAX-RPC service communications.

The Java Web Services Developer Pack structure for JAX-RPC service communications.

The ties and stubs are generated by a packaged set of tools called wsdeploy and wscompile, respectively. wsdeploy examines the methods found in your service and creates a series of classes that handle the unmarshaling of the passed in SOAP message, and the marshaling of the return data. The WSDL file is created by this tool as well. It also builds a wrapper servlet that your service runs within. This servlet, along with your service code, composes a Web Application Archive (WAR) file that will be deployed to the Tomcat server.

The wscompile tool works by looking at the WSDL file for the specified service. It examines the XML descriptors in that file to generate a set of proxy classes that will handle the communications to the service and the marshaling of all method calls. In essence, wsdeploy and wscompile are conjugates of each other. Together, these tools take a lot of the manual labor out of building the Web service interconnects. Without them, you’d have to write all the code to build up the XML SOAP envelopes, consume them, and convert the data to and from Java objects. This would require much more intimate knowledge of the API’s included in the pack and adds a lot more complexity to the development process.

The pack directly supports arguments of the data types shown in Table 14.1.

Table 14.1. Supported Types

Group of Types

Types That Are Supported

Primitives

Boolean, Byte, Double, Float, Int, Long, Short.

Class versions of the primitives

Boolean, Byte, Double, Float, Integer, Long, Short, String, BigDecimal, BigInteger, Calendar, Date.

Collections

ArrayList, LinkedList, Stack, Vector, HashMap, HashTable, Properties, TreeMap, HashSet, TreeSet.

User-created classes as long as they conform to the following rules

It must have a public default constructor.

It must not implement (either directly or indirectly) the java.rmi.Remote interface.

 

Its fields must be supported JAX-RPC types.

 

The class can contain public, private, or protected fields.

 

For its value to be passed (or returned) during a remote call, a field must meet these requirements:

 

A public field cannot be final or transient.

 

A nonpublic field must have corresponding getter and setter methods.

JavaBeans

Must conform to the same rules as user classes. Must also have getter and setter methods for every bean property, and the properties must be supported types from the previous lists.

Arrays of any of the preceding types

Single or multidimensional.

Now that you’ve seen what’s included in the pack, let’s start looking at how to build a Web service with it.

Building a Simple Web Service

Building a Web service with the Java Web Services Developer Pack is actually quite easy. Only two files must be built. The first is an interface that lists the methods that can be called by clients. The second is a class that implements that interface.

We’ll use the following example to demonstrate the procedure involved. Let’s say that you want to write a service that will process credit card approvals. To keep things simple, we’ll say that any credit card ending in an even number is considered valid and any card with an odd number is invalid. (This obviously isn’t true in real life; we’re just simplifying the problem for demonstration purposes.) In order to process the card, we’ll need to know the card number. We’ll send back a true if it’s valid—false if it’s invalid. In such a system, our interface class would look like Listing 14.1.

Example 14.1. Credit Card Validation Web Service Interface

package ch14;

import java.rmi.Remote;
import java.rmi.RemoteException;

public interface CreditValidatorInterface extends Remote
{
  public boolean validateCard(String cardnumber)
         throws RemoteException;
}

You might notice that we make use of the RMI packages. This is actually fairly typical in Java systems that perform remote method calls—regardless of the underlying communication protocols.

You’ll also notice that our method has to throw a RemoteException. This (or a subclass of it) must be used in order to communicate problems back to the client.

Once we’re done building the interface, we then need to build a class that implements the interface. We’ll do that using the code in Listing 14.2.

Example 14.2. Credit Card Validation Web Service Implementation Class

package ch14;

import java.rmi.Remote;
import java.rmi.RemoteException;

public class CreditValidator implements CreditValidatorInterface
{
  public boolean validateCard(String cardnumber)
         throws RemoteException
  {
     long cardnum = (new Long(cardnumber)).longValue();
     if(cardnum %2 ==0)
        return true;
     else
        return false;
  }
}

As you can see, we kept the Web service’s code very simple. We read in the card number, divide it by 2, and see if there’s any remainder. If there isn’t, it’s valid.

To compile this code and build the directory structure we need for the project, open a command prompt and navigate to the ch14 directory. Then run the following command:

ant compile-server

Provided that there are no compile errors, the code will be turned into Java .class bytecode files and placed into the build/shared subdirectory.

Now that we have our service, we need to make use of the tool that comes with the pack to create tie classes that will perform the conversion to and from SOAP for us.

Deploying and Registering the Service

Now that we have the code for our service, we next need to package and deploy it so that it can be used by clients. In order to do this, we must provide a couple of additional files and place our compiled code into a package.

First, we’ll need to create the following directory structure inside our ch14 directory:

WEB-INF
       classes
              ch14

Don’t bother doing this yet because we have an ant command to take care of this for us, which we’ll use in a moment.

Next, we need to create two files that will describe how to find and work with our service. Both of these files will need to be placed into the WEB-INF directory.

First, create a file called web.xml. This file is used by the container to identify the service and set up some properties such as the session timeout information. This file mainly is used by the servlet container for application management. The web.xml file can be seen in Listing 14.3.

Example 14.3. The Web.xml File

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE web-app PUBLIC
"-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN"
    "http://java.sun.com/j2ee/dtds/web-app_2_3.dtd">
<web-app>
   <display-name>Credit Card Validation Application</display-name>
   <description>A web application containing a simple
JAX-RPC endpoint</description>
   <session-config>
      <session-timeout>60</session-timeout>
   </session-config>
</web-app>

The second file we need to create is specific to the Java Web Services Development Pack. This file details which file contains the interface and which is the implementation. It links this data to the Web service that we described in the web.xml file. You can see the jaxrpc-ri.xml file in Listing 14.4.

Example 14.4. The Jaxrpc-ri.xml File Links the Class Files to the Service

<?xml version="1.0" encoding="UTF-8"?>
<webServices
    xmlns="http://java.sun.com/xml/ns/jax-rpc/ri/dd"
    version="1.0"
    targetNamespaceBase="http://com.test/wsdl"
    typeNamespaceBase="http://com.test/types"
    urlPatternBase="/ws">

    <endpoint
        name="MyCreditValidator"
        displayName="Credit Card Validator"
        description="A simple web service"
        interface="ch14.CreditValidatorInterface"
        implementation="ch14.CreditValidator"/>

    <endpointMapping
        endpointName="MyCreditValidator"
        urlPattern="/creditcard"/>

</webServices>

The important lines are the interface and implementation ones. Notice that we listed the fully qualified names of our interface and service implementation classes here.

You’ll notice that we named the endpoint value "MyCreditValidator". It is very important that you don’t try to name it CreditValidator. Doing that will cause problems because when the ties and proxy classes are created by the automated tools later, they will be named the same as our class files, which will confuse the system. For the sake of simplicity, we’ll just put “My” at the front of our endpoint names. You can really call the endpoint anything that you want. As long as the endpoint isn’t the same as the name of an existing class, you’ll be safe. If you don’t, you’ll end up with two .class files with the same name, which will confuse the Java runtime engine.

To build the directory structure and get the two .xml files into the correct spot, run the following command:

ant setup-web-inf

This will build the directory structure and copy in the compiled bytecode files, as well as the web.xml and jaxrpc-ri.xml files, into the proper places.

Now that we have all the files that compose our Web service, we next need to package it into a WAR file. To do this, we execute the following command from the ch14 directory:

ant package

This will create a new file named credit-portable.war that contains our server code and the two XML files and places it into the dist subdirectory.

Now that we have our service, we need to create the WSDL listing that will explain to clients how to communicate with it. To simplify this process, Sun has provided a tool called wsdeploy. This tool reads the information in the javarpc-ri.xml file. wsdeploy examines information in the javarpc-ri.xml file and generates the needed interfaces and tie classes. The following ant command will call wsdeploy, which creates the ties and places them, as well as the contents of our WAR file, into a new WAR file (which is the one we will eventually deploy). To perform this step, type the following:

ant process-war

After running this command, you will find that a new file named credit-deployable.war has been created in the dist directory. If you open that file using a tool such as WinZip, you’ll see that a large number of other files have been created and added to the archive, including a CreditValidator.wsdl file. These files are the tie interface files.

Now that we have a deployable WAR file, we can go ahead and deploy it and confirm that it’s correct. Make sure that you have Tomcat running. Then use the following command:

ant deploy

This will copy the credit-deployable.war file to the <jwsdp_home>workStandard Enginelocalhost directory (where <jwsdp_home> is the directory in which the Java Web Services Developer Pack is installed) and will register the new service with the Tomcat server.

Let’s confirm that everything is good so far. Start up the Tomcat Application server. (On Windows machines, this can be done through the Start menu.) Once Tomcat is running, open a new browser window and point it to

http://localhost:8080/credit-deployable/creditcard

If everything is working correctly, you should get a screen that looks like the one in Figure 14.2.

The deployed Credit Card Web service.

Figure 14.2. The deployed Credit Card Web service.

Creating a Client to Attach to the Service

Now that we have built what we need for the service, let’s concern ourselves with the client side. Before we can do that though, we need to build the necessary stubs so that we can communicate with the service in the expected manner. We’ll need one more XML file to do this. In the ch14 directory, create a new file named config.xml. It needs to look like Listing 14.5.

Example 14.5. The Config.xml File Details Where the Wscompile Tool Can Find the WSDL File

<?xml version="1.0" encoding="UTF-8"?>
<configuration
     xmlns="http://java.sun.com/xml/ns/jax-rpc/ri/config">
  <wsdl location="http://localhost:8080/credit-deployable/creditcard?WSDL"
     packageName="ch14"/>
</configuration>

Now that we’ve got the config file, we’ll make use of another tool provided for us called wscompile. Again, we have this process automated for us in the ant build script.

ant generate-stubs

You’ll notice that a number of new .class files are now created in the buildclientch14 directory. These are the stubs generated by the wscompile program. Wscompile used the WSDL file specified in the config.xml file to determine what interface classes would be needed and created them. We can now use those in our client program to perform the communication for us. If we were building a client to talk to some other service, we’d need to list it in the config.xml file and perform a similar action to get the stubs to talk to that service.

Next we’ll build a simple client that will take a credit card number, pass it to the service, and then report the results from the service. In a real system, you’d probably make this part of a shopping cart transaction system, but for simplicity’s sake, we’ll just hard code a number in. Listing 14.6 shows the client.

Example 14.6. A Client That Uses the Credit Card Processing Service

package ch14;
import javax.xml.rpc.Stub;

public class ShoppingClient
{
   public static void main(String[] args)
   {
      try
      {
        String cardnumber = "123456";
        Stub stub = createProxy();
        CreditValidatorInterface cardvalidator =
            (CreditValidatorInterface) stub;
        boolean results = cardvalidator.validateCard(cardnumber);
        if(results)
          System.out.println("Card was valid...");
        else
          System.out.println("Card was rejected!");
      }
      catch (Exception ex)
      {
        ex.printStackTrace();
      }
   }

   private static Stub createProxy()
   {
      return (Stub)(new
       MyCreditValidator_Impl().getCreditValidatorInterfacePort());
   }
}

Before we compile this example, let’s discuss the structure of the code a bit.

import javax.xml.rpc.Stub;

This line tells the java compiler that we’re going to be using a class called Stub from the RPC package.

Stub stub = createProxy()

This line calls a private method responsible for setting up the linkage between our client and the stub that will handle communication to the server for us. The guts of that method are shown here:

return (Stub)(new MyCreditValidator_Impl().getCreditValidatorInterfacePort());

Here we create a new Stub called MyCreditValidator_Impl (which the wscompile tool built for us) and tell it to make a linkage to the server. How this works really isn’t important. Just follow the template in your own code, replacing CreditValidator and CreditValidatorInterface with the names of your own implementation class and interface.

Back in the main() of our client, we then see

CreditValidatorInterface cardvalidator = (CreditValidatorInterface) stub;

This line takes the stub and converts it into a reference for a CardValidatorInterface so that we can work with it pretty much as though it were a local class. Finally, we make our method call to the service to find out whether the card is valid:

boolean results = cardvalidator.validateCard(cardnumber);

As you can see, this looks no different than it would if we were referencing a local object and making a call to it. That’s the beauty of Web services. With just a little extra work, we get a distributed system!

To compile this code, run the following ant command from the ch14 root directory:

ant compile-client

We then need to package the client into a usable (and easier to distribute) package. Type the following command:

ant jar-client

If everything worked correctly, you’ll find a new jar file in the dist directory called ch14-client.jar.

Okay, now is the time to try out our client. Make sure that you have Tomcat running, and you might want to reconfirm that your service is deployed (see earlier in this hour on how to do that). To run the code, just type

ant run

You should get the following output if everything worked correctly:

[echo] Running the ch14.ShoppingClient program...
[java] Card was valid...

There you are! You’ve just built and deployed a Web service and hooked into it. You’ll notice that it took what seemed like a long period of time (several seconds) for our simple little test to run even though both the client and the server were on the same machine. Although the CardValidator object might appear to be local to the client, it still had to go through the XML conversion process, a network connection, and so on. These steps take time.

Summary

This hour walks you through the Java Web Services Developer Pack. We examined what Java packages are in the pack and briefly discussed their purposes.

Next we stepped through a simple Web service example that validated credit card numbers. We saw how the Web Services Developer Pack takes care of building the tie and stubs for you, leaving you to worry more about the business logic. We then deployed our service to the Tomcat App Server that came packaged in the pack.

Finally, we built a client to interface with our service. We saw that with very few changes, we can reference a remote class as though it were local. We also saw that there are performance considerations when accessing remote objects through Web services.

Q&A

Q

Does the Java Web Service Developer Pack support message mode SOAP calls?

A

Yes, but it requires the direct manipulation of the SOAP envelope and familiarity of the JAXM API. With the JAXM API, the developer must manually build up the SOAP envelope request, make connections, and handle exceptions. This can be a powerful capability, but also requires much more work on the developer’s part. In general, if you can use the RPC format, do so, and take advantage of the tools provided in the kit for building ties, stubs, and WSDL.

Q

Is a UDDI server provided in the pack?

A

There is a demonstration UDDI server in the pack. It is referred to as the Registry Server. You can write clients that will query this registry server by using the JAXR API. The included registry is not meant for production scale use though.

Workshop

This section is designed to help you anticipate possible questions, review what you’ve learned, and begin learning how to put your knowledge into practice.

Quiz

1.

What tool builds the WSDL file for you?

2.

What is your Web service run within on the Tomcat server?

3.

What WSDP-specific file is used by the wsdeploy tool to generate the ties and WSDL file?

4.

What type of exception must all service methods throw?

5.

What is contained in the Java Web Services Developer Pack?

6.

What’s the difference between a stub and a tie?

Quiz Answers

1.

Wsdeploy.

2.

A servlet generated during the wsdeploy process.

3.

Javarpc-ri.xml.

4.

RemoteException or a subclass of it.

5.

A number of API libraries used to work with XML and create SOAP messages, as well as Tomcat, ant, and several other tools for the creation of WSDL files and stubs and ties.

6.

A stub is the client-side component that is built from the service’s WSDL. A tie is the server-side interface that accepts SOAP messages and converts them for use by the service.

Activity

1.

Modify the Web service we built in this hour to make a more realistic credit card transaction processing engine. Make the service track the transactions in a file. Make the client pass not only the card number, but also the cardholder’s name and the expiration date. Be sure to verify that the date is past the current date on the server.

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

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