Creating Web Services with JAX-WS - Writing Internet Applications - Sams Teach Yourself Java in 24 Hours, 7th Edition (2014)

Sams Teach Yourself Java in 24 Hours, 7th Edition (2014)

Part VI: Writing Internet Applications

Hour 22. Creating Web Services with JAX-WS

THIS HOUR’S TO-DO LIST:

Image Define a Java interface for a web service.

Image Apply this interface to a Java class.

Image Deploy a web service on the Internet.

Image View a web service contract.

Image Create a web service client.

Now that the Internet is everywhere, driving billions of desktop computers, web servers, phones, videogame consoles, and other devices, the desire to connect them all together has given rise to web services, software that communicates with other software over HTTP, the protocol of the Web.

An innovative way to make some of these connections is by using the Java API for XML Web Services (JAX-WS). JAX-WS is a set of packages and classes that create clients that make requests of web services and services that take those requests.

JAX-WS supports web services that are implemented using the Simple Object Access Protocol (SOAP) and Representational State Transfer (REST). JAX-WS greatly simplifies the task of supporting these protocols. As a programmer, you create Java objects and call methods to use web services, and the rest is taken care of behind the scenes.

Defining a Service Endpoint Interface

The first step in the creation of a JAX-WS web service is to create a Service Endpoint Interface, a Java interface that defines the methods that clients can call when they’re using the web service.

The SquareRootServer web service you are developing this hour is a service that can handle two simple tasks:

Image Calculating the square root of a number

Image Displaying the current date and time

An interface is a set of methods that provides names, arguments, and return types but does not contain code that implements the methods. The interface serves as a contract between objects: If an object implements an interface, other objects know they can call all the interface’s methods on that object.

In Hour 15, “Responding to User Input,” you had to implement the ActionListener interface in any Java class that needed to receive action events when a button was clicked.

For this project, you’re handling the other side of the contract. The SquareRootServer interface defines two methods that must be present in a class that implements the web service: squareRoot(double) and getTime().

The following statements define the interface:

public interface SquareRootServer {
double getSquareRoot(double input);
String getTime();
}

The method definitions in an interface are followed by a semicolon rather than { and } characters around a block statement. Interfaces don’t define the behavior of methods. That’s handled by classes that implement the interface.

Because these methods can be called as a JAX-WS web service, an extra modifier must be added in front of each one, the annotation @WebMethod:

public interface SquareRootServer {
@WebMethod double getSquareRoot(double input);
@WebMethod String getTime();
}

Using Annotations to Simplify Java Code

Annotations are a smarter form of comments that can be understood by the Java interpreter, compiler, and programming tools. They provide a way to define information about a program that’s not part of the program itself but that can trigger actions when the program is compiled or run.

Annotations begin with an @ sign followed by the name of the annotation.

One of the most common annotations is @Override, which indicates a method overrides a superclass method. Here’s an example:

@Override
public void paintComponent(Graphics comp) {
// definition of method here
}

If you’ve made an error and it does not override a method—which would happen if you used the wrong type, wrong method name, or number of parameters—the compiler can catch the error. (The compiler would not be able to detect this problem without the annotation.)

The @WebMethod annotation indicates that a method can be called as a web service. The SquareRootServer interface also uses an @WebService annotation that indicates the interface defines a service endpoint interface.

Annotations can take parameters that provide further customization. SquareRootServer includes one final annotation:

@SOAPBinding(style = Style.RPC)

This annotation helps define the contract between the web service and the client programs that call the service. You learn more about this later in the hour.

For now, it’s time to begin coding the web service. Create a new Java file in NetBeans with the class name SquareRootServer and the package name com.java24hours.ws. Enter the contents of Listing 22.1 into the file.

LISTING 22.1 The Full Text of SquareRootServer.java


1: package com.java24hours.ws;
2:
3: import javax.jws.*;
4: import javax.jws.soap.*;
5: import javax.jws.soap.SOAPBinding.*;
6:
7: @WebService
8:
9: @SOAPBinding(style = Style.RPC)
10:
11: public interface SquareRootServer {
12: // get the square root of a number
13: @WebMethod double getSquareRoot(double input);
14:
15: // get the current time and date as a string
16: @WebMethod String getTime();
17:
18: }


This class has been placed in the com.java24hours.ws package, a design decision that makes it easier for the web service to be deployed for other software to access over the Internet.

Now that you’ve finished defining this interface, you’re ready to write the code that implements its two methods: getSquareRoot() and getTime().

Creating a Service Implementation Bean

The Java class that implements the Service Endpoint Interface is called the Service Implementation Bean. (Learning odd new bits of jargon is an unavoidable part of JAX-WS.)

The SquareRootServerImpl class implements the SquareRootServer interface, as stated in the class declaration:

public class SquareRootServerImpl implements SquareRootServer {

This means the class you’re creating must contain all the methods in the interface, each with the proper parameters.

The getSquareRoot(double) and getTime() methods are implemented using techniques you’ve learned previously.

The only new aspect of the class is the following annotation, which appears before the class statement:

@WebService(endpointInterface = "com.java24hours.ws.SquareRootServer")

This annotation indicates the class is a Service Implementation Bean for a Service Endpoint Interface named com.java24hours.ws.SquareRootServer. You must use the full class name, including the name of its package.

Take note of the fact that annotations are not followed by semicolons, unlike statements.

Start coding this class: Create a new Java file named SquareRootServerImpl in the package com.java24hours.ws, and then fill it with the contents of Listing 22.2.


Caution

The name Service Implementation Bean refers to JavaBeans, special Java classes designed to function as reusable software components in the Java Enterprise Edition. However, the reference to beans is a bit of a misnomer when it comes to JAX-WS. Any Java object can be a Service Implementation Bean as long as it follows the rules for web service methods and has been created with the proper annotations.


LISTING 22.2 The Full Text of SquareRootServerImpl.java


1: package com.java24hours.ws;
2:
3: import java.util.*;
4: import javax.jws.*;
5:
6: @WebService(endpointInterface = "com.java24hours.ws.SquareRootServer")
7:
8: public class SquareRootServerImpl implements SquareRootServer {
9:
10: public double getSquareRoot(double input) {
11: return Math.sqrt(input);
12: }
13:
14: public String getTime() {
15: Date now = new Date();
16: return now.toString();
17: }
18: }


With the two classes you’ve created, you’re ready to launch the web service so it can be called by other software.

Publishing the Web Service

JAX-WS web services can be deployed by Java application servers such as BEA WebLogic, GlassFish, JBoss, and Jetty. If you had created the SquareRootServer web service in a development environment that supported those servers, you’d be ready at this point to launch it.

You also can write your own Java application that loads a web service and makes it available over the Internet.

The SquareRootServerPublisher application handles this task, which requires only two steps:

Image Load the class that implements the web service

Image Publish that object at an address accessible to the Internet

The EndPoint class in the javax.xml.ws package has a class method, publish(String, Object), that deploys a web service.

This method’s first argument is the web address where the service can be accessed, which for this project is http://127.0.0.1:5335/service. This web address begins with a host name, 127.0.0.1, that’s called the localhost because it’s the local computer you’re using to create and run your Java programs.

The second part of the address is the port number on the localhost where the web service waits for connections. The port 5335 has been chosen arbitrarily because it’s not likely to be in use by other Internet-aware programs on your computer.

The final part of the address, /service, is the path. Every web service must have a unique path. If you run any other web services on your computer, they can’t have the same path as SquareRootServer.

To deploy the web service, create a Java file called SquareRootServerPublisher in the com.java24hours.ws package. Enter the text of Listing 22.3 in this file.

LISTING 22.3 The Full Text of SquareRootServerPublisher.java


1: package com.java24hours.ws;
2:
3: import javax.xml.ws.*;
4:
5: public class SquareRootServerPublisher {
6: public static void main(String[] arguments) {
7: SquareRootServerImpl srsi = new SquareRootServerImpl();
8: Endpoint.publish(
9: "http://127.0.0.1:5335/service",
10: srsi
11: );
12: }
13: }


When you run the application, it waits for connections on port 5335 of your computer. You can call the methods of the web service from any program that supports SOAP- or REST-based web services, whether the program is written in Java or another language. As long as your web service is on the Internet, any other Internet-connected software can call the methods.

Using Web Service Definition Language Files

Before trying out this web service, you can test the availability of the SquareRootServerPublisher application with any web browser.

Open a browser and load the address http://127.0.0.1:5335/service?wsdl. The browser displays the XML file shown in Listing 22.4. This file is being served by the application that you just created.

This file is a service contract that’s written in Web Services Description Language (WSDL), an XML dialect for spelling out exactly how a web service functions so that servers and clients can make full use of it.

You don’t have to understand WSDL to create JAX-WS services and clients to access those services. It’s worthwhile to take a cursory look at the contents to get a picture for how SOAP- and REST-based web services operate.

LISTING 22.4 A Web Service Description Language Contract


1: <?xml version="1.0" encoding="UTF-8"?>
2: <!-- Published by JAX-WS RI at http://jax-ws.dev.java.net. RI's version
3: is JAX-WS RI 2.2.2 in JDK 7. -->
4: <!-- Generated by JAX-WS RI at http://jax-ws.dev.java.net. RI's version
5: is JAX-WS RI 2.2.2 in JDK 7. -->
6: <definitions xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/"
7: xmlns:tns="http://ws.java24hours.com/"
8: xmlns:xsd="http://www.w3.org/2001/XMLSchema"
9: xmlns="http://schemas.xmlsoap.org/wsdl/"
10: targetNamespace="http://ws.java24hours.com/"
11: name="SquareRootServerImplService">
12: <types></types>
13: <message name="getSquareRoot">
14: <part name="arg0" type="xsd:double"></part>
15: </message>
16: <message name="getSquareRootResponse">
17: <part name="return" type="xsd:double"></part>
18: </message>
19: <message name="getTime"></message>
20: <message name="getTimeResponse">
21: <part name="return" type="xsd:string"></part>
22: </message>
23: <portType name="SquareRootServer">
24: <operation name="getSquareRoot" parameterOrder="arg0">
25: <input message="tns:getSquareRoot"></input>
26: <output message="tns:getSquareRootResponse"></output>
27: </operation>
28: <operation name="getTime" parameterOrder="">
29: <input message="tns:getTime"></input>
30: <output message="tns:getTimeResponse"></output>
31: </operation>
32: </portType>
33: <binding name="SquareRootServerImplPortBinding"
34: type="tns:SquareRootServer">
35: <soap:binding transport="http://schemas.xmlsoap.org/soap/http"
36: style="rpc"></soap:binding>
37: <operation name="getSquareRoot">
38: <soap:operation soapAction=""></soap:operation>
39: <input>
40: <soap:body use="literal"
41: namespace="http://ws.java24hours.com/"></soap:body>
42: </input>
43: <output>
44: <soap:body use="literal"
45: namespace="http://ws.java24hours.com/"></soap:body>
46: </output>
47: </operation>
48: <operation name="getTime">
49: <soap:operation soapAction=""></soap:operation>
50: <input>
51: <soap:body use="literal"
52: namespace="http://ws.java24hours.com/"></soap:body>
53: </input>
54: <output>
55: <soap:body use="literal"
56: namespace="http://ws.java24hours.com/"></soap:body>
57: </output>
58: </operation>
59: </binding>
60: <service name="SquareRootServerImplService">
61: <port name="SquareRootServerImplPort"
62: binding="tns:SquareRootServerImplPortBinding">
63: <soap:address location="http://127.0.0.1:5335/service"></soap:address>
64: </port>
65: </service>
66: </definitions>


A WSDL file is called a service contract because it stipulates how a web service can be reached, the messages that can be exchanged with the service, and the data types of the information being transferred.

Lines 13–22 of the WSDL contract define the web service’s methods, the parameters of those methods, and the data returned in response. Take a look over those lines to see if you can determine where it states that the getSquareRoot() method takes a double parameter and returns a double value.

The data types referenced in the contract are not Java data types. They’re data types that are generalized for use by any programming language that supports SOAP. (There’s nothing about web services that’s tailored specifically to Java.)


Note

Because a WSDL contract defines a web service in such specific detail, you can use it to automate much of the process of programming web services. The Java Development Kit (JDK) includes a command-line tool, wsimport, that takes a WSDL file as input and writes Java classes to access the web service.


Creating a Web Service Client

In this section, you create SquareRootClient, a Java application that can call the methods of the web service you just created. The service must, of course, be running for the client to connect to it.

Because web service technology like the JAX-WS library supports standards such as SOAP, REST, HTTP, and XML, you don’t have to use a Java program to connect to the square root web service. Perl, Python, Ruby, and other languages all have libraries that support web services.

The JAX-WS library offers the Service class in the javax.xml.ws package, a factory that creates objects that can call a web service.


Caution

As stated, a URI does not have to be a working web address. Although http://ws.java24hours.com looks like one, it’s used here simply as a unique identifier. I own the domain name java24hours.com and control how its subdomains are used. So when I designatehttp://ws.java24hours.com as a URI, I can be reasonably assured that no other web service provider would take that identification.


The class method Service.create(URL, QName) creates the factory. The arguments are a URL object from java.net and a QName from javax.xml.namespace.

The URL must be the address of the web service’s WSDL contract:

URL url = new URL("http://127.0.0.1:5335/service?wsdl");

The QName is a qualified name, an XML identifier that’s associated with the provider of the web service. A qualified name consists of a namespace URI and a local identifier.

Namespace URIs are similar to URLs but do not necessarily work as a web address. Because the package name of the square root web service is com.java24hours.ws, which by convention in Java associates it with the Internet host name ws.java24hours.com, the namespace URI for this web service is http://ws.java24hours.com.

The local identifier for the web service is the name of the Service Implementation Bean with the word Service appended. Here’s the statement that creates the qualified name:

QName qname = new QName(
"http://ws.java24hours.com/",
"SquareRootServerImplService"
);

With the URL and qualified name, you can create the web service client factory:

Service service = Service.create(url, qname);

The factory has a getPort(Class) method that creates an object of the specified class. To identify a Java class for use as a method argument, use a class variable of the class named class. Confusing? It makes more sense when you see it in a Java statement:

SquareRootServer srs = service.getPort(SquareRootServer.class);

The call to getPort() with SquareRootServer.class as the argument causes the factory to create a SquareRootServer object. This object is stored in the srs variable.

Call the methods of the SquareRootServer object as you would any other object in Java:

System.out.println(srs.getTime());
System.out.println(srs.getSquareRoot(625D));

The JAX-WS library packages these method calls as SOAP messages, sends them over the Internet to the web service, and transmits the calls.

When the service responds to the calls, it packages the responses as SOAP messages, sends them back over the Internet, and they’re converted back to Java data types.

Put all these together by creating a Java file named SquareRootClient and entering the text from Listing 22.5 in the file.

LISTING 22.5 The Full Text of SquareRootClient.java


1: package com.java24hours.ws;
2:
3: import java.net.*;
4: import javax.xml.namespace.*;
5: import javax.xml.ws.*;
6:
7: public class SquareRootClient {
8: public static void main(String[] arguments) throws Exception {
9: URL url = new URL("http://127.0.0.1:5335/service?wsdl");
10: QName qname = new QName(
11: "http://ws.java24hours.com/",
12: "SquareRootServerImplService"
13: );
14: Service service = Service.create(url, qname);
15: SquareRootServer srs = service.getPort(SquareRootServer.class);
16:
17: System.out.println(srs.getTime());
18: System.out.println(srs.getSquareRoot(625D));
19: }
20: }


When you run the client application, you see the output shown in Figure 22.1 if the SquareRootPublisher application is running.

Image

FIGURE 22.1 Calling a web service and displaying the response.

Summary

The JAX-WS set of packages and classes is the successor to the Java API for XML-based RPC (JAX-RPC), a technology for making remote procedure calls from one Java object to another over the Internet. Another API, JAX-RS, supports web services in Java that use REST.

The ability to call other software, regardless of its location and the programming language in which it’s written, is one of the building blocks of a software development trend that became popularized under the name Web 2.0.

The selling point behind Web 2.0 was to enable software to take as much advantage of the Internet’s ubiquitous connectivity as humans have enjoyed since the Web became popular in the mid-1990s.

This hour covered all four steps of creating and using a web service using JAX-WS. You can create an interface for the service (a Service Endpoint Interface), implement the service (a Service Implementation Bean), publish the service on the Internet, and create a client to access it.

Many programming tools, including NetBeans and the JDK, make it possible to create code automatically to simplify the job of creating and accessing web services.

Workshop

Q&A

Q. How does XML-RPC fit in with SOAP web services?

A. XML-RPC is a protocol for calling methods and receiving data in an XML format over HTTP, the protocol of the Web. SOAP is all those things as well, and in fact the two web service protocols share a common origin.

XML-RPC was created from a draft version of the protocol that eventually became SOAP. Because XML-RPC was out first and is simpler to implement, it developed its own following and remains popular today. The Apache XML-RPC Java library, available fromhttp://ws.apache.org/xmlrpc, supports the creation of web services and clients that employ XML-RPC.

SOAP’s a more sophisticated web service protocol that supports a wider range of client/service interactions.

Q. I’m not clear on why a package named com.java24hours.ws is associated with the Internet host ws.java24hours.com. How does that work?

A. Java package names are chosen by the programmers who developed the package. Oracle starts the names of Java packages from the Java Class Library with either java or javax, such as java.util and javax.swing. When other programmers create a package, they follow a convention that prevents two entities from choosing the same package name and being confused with each other.

The convention is to choose a package name that’s based on something the entity owns—a domain name—and reverse it so the last part comes first. As the owner of the domain name cadenhead.org, I’ve created Java classes with package names that begin withorg.cadenhead, such as org.cadenhead.web. The Apache Software Foundation, which owns apache.org, calls its XML-RPC package org.apache.xmlrpc.

Q. What was the first website on the Internet?

A. The first site was http://info.cern.ch, which is still online today. Tim Berners-Lee, a British physicist at the European Organization for Nuclear Research (CERN), used the site to describe his new invention, the World Wide Web.

The first web page was at http://info.cern.ch/hypertext/WWW/TheProject.html and was updated daily as the Web attracted users, publishers, and software developers.

The site defined the Web as a “a wide-area hypermedia information retrieval initiative aiming to give universal access to a large universe of documents.”

Quiz

See how many facts about web services have filled your bean by answering the following questions.

1. What is a Service Implementation Bean?

A. An interface that identifies the methods reachable over a web service

B. A class that implements a web service

C. A service contract between a web service and clients that call the service

2. When text such as @WebMethod or @Override appears in a method declaration, what is it called?

A. An annotation

B. An assertion

C. An aggravation

3. What does WSDL stand for?

A. Web Services Deployment Language

B. Web Services Description Language

C. Lucy in the Sky with Diamonds

Answers

1. B. Answer A. refers to a Service Endpoint Interface.

2. A. Although I guess answer C is also potentially true, depending on how much trouble you had in that section of the hour.

3. B. It’s often mistakenly called Web Services Definition Language.

Activities

To further service your knowledge of this hour’s topic, do the following activities:

Image Add a method to the square root web service that multiplies a number by 10 and modify the SquareRootClient application to call that method.

Image Create a new web service that reads a location’s high temperature, low temperature, and weather conditions from a properties file, as covered in Hour 21, “Reading and Writing Files,” and sends this data to clients that call the web service.

To see Java programs that implement these activities, visit the book’s website at www.java24hours.com.