Learn all about Web services and how they work in Java SE Credit: Soil Science Java Standard Edition (SE) 6 included support for Web services. This post begins a four-part series on Web services in Java SE by explaining what Web services are and overviewing Java SE’s support for them. Future posts will use this support to build SOAP-based and RESTful-based Web services, and will also cover advanced Web service topics. What are web services? Wikipedia defines Web service as “a software system designed to support interoperable machine-to-machine interaction over a network.” A more detailed definition can be obtained by first defining this term’s parts: Web: An enormous interconnected network of resources, where a resource is a Uniform Resource Identifier (URI)-named data source such as a PDF-based document, a video stream, a Web page, or even an application. These resources can be accessed by using standard Internet protocols such as HyperText Transfer Protocol (HTTP) or Simple Mail Transfer Protocol (SMTP). Service: A server-based application or software component that exposes a resource to clients via an exchange of messages according to a message exchange pattern (MEP). The request-response MEP is typical. Given these definitions, a Web service is a server-based application/software component that exposes a Web-based resource to clients via an exchange of messages. These messages may be formatted according to Extensible Markup Language (XML) or JavaScript Object Notation (JSON). Also, these messages can be thought of as invoking Web service functions and receiving invocation results. Figure 1 illustrates this message exchange. Figure 1. A client accesses a resource by exchanging messages with a Web service Web services can be classified as simple or complex. Simple Web services don’t interact with other Web services (e.g., a standalone server-based application with a single function that returns the current time for a specified time zone). In contrast, complex Web services often interact with other Web services. For example, a generalized social network Web service might interact with Twitter and Facebook Web services to obtain and return to its client all Twitter and all Facebook information for a specific individual. Complex Web services are also known as mashups because they mash (combine) data from multiple Web services. SOAP-based web services A SOAP-based Web service is a widely used Web service category that’s based on SOAP, an XML language for defining messages (abstract function invocations or their responses) that can be understood by both ends of a network connection. An exchange of SOAP messages is called an operation, which corresponds to a function call and its response, and which is depicted in Figure 2. Figure 2. A Web service operation involves input and output messages Related operations are often grouped into an interface, which is conceptually similar to a Java interface. A binding provides concrete details on how an interface is bound to a messaging protocol (particularly SOAP) to communicate commands, error codes, and other items over the wire. The binding and a network address (an IP address and a port) URI is known as an endpoint, and a collection of endpoints is a Web service. Figure 3 presents this architecture. Figure 3. Interfaces of operations are accessible via their endpoints SOAP is often used with Web Services Description Language (WSDL, pronounced whiz-dull), an XML language for defining a Web service’s operations. A WSDL document is a formal contract between a SOAP-based Web service and its clients, providing all details for interacting with the Web service. This document lets you group messages into operations and operations into interfaces. It also lets you define a binding for each interface as well as the endpoint address. As well as supporting WSDL documents, SOAP-based Web services have the following properties: The ability to address complex nonfunctional requirements such as security and transactions: These requirements are made available via various specifications. To promote interoperability among these specifications, the Web Services Interoperability Organization (WS-I) (an industry consortium) was formed. WS-I has established a set of profiles, where a profile is a set of named Web service specifications at specific revision levels, along with a set of implementation and interoperability guidelines recommending how the specifications may be used to develop interoperable Web services. For example, the very first profile, WS-I Basic Profile 1.0, consists of the following set of nonproprietary Web service specifications: SOAP 1.1 WSDL 1.1 Universal Description Discovery and Integration (UDDI) 2.0 XML 1.0 (Second Edition) XML Schema Part 1: Structures XML Schema Part 2: Datatypes RFC2246: The Transport Layer Security Protocol Version 1.0 RFC2459: Internet X.509 Public Key Infrastructure Certificate and CRL Profile RFC2616: HyperText Transfer Protocol 1.1 RFC2818: HTTP over TLS RFC2965: HTTP State Management Mechanism The Secure Sockets Layer Protocol Version 3.0 Additional profile examples include WS-I Basic Security Profile and Simple SOAP Binding Profile. For more information on these and other profiles, visit the WS-I website. Java SE supports the WS-I Basic Profile. The ability to interact with a Web service asynchronously: Web service clients should be able to interact with a Web service in a nonblocking, asynchronous manner. Client-side asynchronous invocation support of Web service operations is provided in Java SE. SOAP-based Web services execute in an environment that includes a service requester (the client), a service provider, and a service broker. This environment is shown in Figure 4. Figure 4. A SOAP-based Web service involves a service requester, a service provider, and a service broker (e.g., UDDI) The service requester, typically a client application (e.g., a Web browser), or perhaps another Web service, first locates the service provider in some manner. For example, the service requester might send a WSDL document to a service broker, which responds with another WSDL document identifying the service provider’s location. The service requester then communicates with the service provider via SOAP messages. Service providers need to be published so that others can locate and use them. In August 2000, an open industry initiative known as Universal Description, Discovery, and Integration (UDDI) was launched to let businesses publish service listings, discover each other, and define how the services or software applications interact over the Internet. However, this platform-independent, XML-based registry wasn’t widely adopted and currently isn’t used. Many developers found UDDI to be overly complicated and lacking in functionality, and opted for alternatives such as publishing the information on a website. For example, Google once made its public Web services (e.g., Google Maps) available at https://code.google.com/more/. The SOAP messages that flow between service requesters and service providers are often unseen, being passed as requests and responses between the SOAP libraries of their Web service protocol stacks. However, it’s possible to access these messages directly, as you will discover later in this series. RESTful web services SOAP-based Web services can be delivered over protocols such as HTTP, SMTP, FTP, and Blocks Extensible Exchange Protocol (BEEP). Delivering SOAP messages over HTTP can be viewed as a special kind of RESTful Web service. A RESTful Web Service is a widely used Web service category that’s based on Representational State Transfer (REST), a software architecture style for distributed hypermedia systems (systems in which images, text, and other resources are located around networks and are accessible via hyperlinks). The hypermedia system of interest in a Web services context is the World Wide Web. The central part of REST is the URI-identifiable resource. REST identifies resources by their Multipurpose Internet Mail Extensions (MIME) types (such as text/xml). Also, resources have states that are captured by their representations. When a client requests a resource from a RESTful Web service, the service sends a MIME-typed representation of the resource to the client. Clients use HTTP’s POST, GET, PUT, and DELETE verbs to retrieve resource representations and to manipulate resources. REST maps these verbs onto the database Create, Read, Update, and Delete (CRUD) operations, as follows: POST: Create new resource based on request data. GET: Read existing resource without producing side effects (don’t modify the resource). PUT: Update existing resource with request data. DELETE: Delete existing resource. Each verb is followed by a URI that identifies the resource. (This immensely simple approach is fundamentally incompatible with SOAP’s approach of sending encoded messages to a single resource.) The URI might refer to a collection, such as http://javajeff.ca/library, or to an element of the collection, such as http://javajeff.ca/library/9781484219157 — these URIs are only illustrations. For POST and PUT requests, XML-based resource data is passed as the body of the request. For example, you could interpret POST http://javajeff.ca/library HTTP/ 1.1 (where HTTP/ 1.1 describes the requester’s HTTP version) as a request to insert POST‘s XML data into the http://javajeff.ca/library collection resource. For GET and DELETE requests, the data is typically passed as query strings, where a query string is that portion of a URI beginning with a ? character. For example, where GET http://javajeff.ca/library might return a list of identifiers for all books in a library resource, GET http://javajeff.ca/library?isbn=9781484219157 would probably return a representation of the book resource whose query string identifies International Standard Book Number (ISBN) 9781484219157. REST also relies on HTTP’s standard response codes, such as 404 (requested resource not found) and 200 (resource operation successful), along with MIME types (when resource representations are being retrieved). Web service support in Java SE Before Java SE 6, Java-based Web services were developed exclusively with the Java Enterprise Edition (EE) SDK. Although Java EE is preferred for developing Web services from a production perspective, because Java EE-based servers provide a very high degree of scalability, a security infrastructure, monitoring facilities, and so on, the repeated deployment of a Web service to a Java EE container has often been time consuming, slowing down development. Java SE 6 simplified and accelerated Web services development by adding APIs, annotations, tools, and a lightweight HTTP server (for deploying Web services to a simple Web server and testing them in this environment) into its core. APIs Java SE provides several APIs that support Web services. Along with various JAXP APIs (SAX, DOM, StAX, and so on) that I discuss in Java XML and JSON, Java SE provides the JAX-WS, JAXB, and SAAJ APIs: Java API for XML Web Services (JAX-WS): The main API for building Web services and clients (in Java) that communicate via XML. JAX-WS replaces the older Java API for Remote Procedure Call Web Services (JAX-RPC) API, and is assigned package javax.xml.ws and various subpackages. Java Architecture for XML Binding (JAXB): The API for mapping XML Schema-based data types to Java objects and vice-versa. JAX-WS delegates data-binding tasks to JAXB. This API is assigned package javax.xml.bind and various subpackages. Soap with Attachments API for Java (SAAJ): The API for creating, sending, and receiving SOAP messages with/without attachments. JAX-WS’s dependency on SAAJ for SOAP messages was removed in the reference implementation of JAX-WS 2.1.3 (known as Metro). This API is assigned the javax.xml.soap package. I will explore JAX-WS and SAAJ in this series, but (for brevity) won’t be exploring JAXB. If you want a detailed tutorial on JAXB, I recommend that you check out Lesson: Introduction to JAXB at The Java Tutorials. Annotations Java SE 6 introduced several Web service annotation types that facilitate Web service development, by letting you describe Web services declaratively via metadata. You can still develop Web services without these annotation types, but you’ll soon appreciate their convenience if you decide not to use them. Most Web service annotation types are either part of the Web Services MetaData API, which is assigned packages javax.jws and javax.jws.soap, or belong to the javax.xml.ws package. The javax.jws package provides the following annotation types: HandlerChain: Associate the Web service with an externally defined handler chain. I’ll discuss handler chains from the client perspective later in this series. Oneway: Indicate that a given @WebMethod annotation has only an input message and no output message. WebMethod: Customize a method that’s exposed as a Web service operation. WebParam: Customize the mapping of an individual parameter to a WSDL message element’s part element. WebResult: Customize the mapping of the return value to a WSDL message element’s part element. WebService: Mark a Java class as implementing a Web service, or a Java interface as defining a service endpoint interface. The following annotation types (three of which are deprecated in favor of using the HandlerChain annotation type) belong to the javax.jws.soap package: InitParam: Describe an initialization parameter (a name/value pair passed to the handler during initialization). This annotation type is deprecated. SOAPBinding: Specify the mapping of the Web service onto the SOAP protocol. SOAPMessageHandler: Specify a single SOAP message handler that runs before and after the Web service’s business methods. This handler is called in response to SOAP messages targeting the service. This annotation type is deprecated. SOAPMessageHandlers: Specify a list of SOAP protocol handlers that run before and after the Web service’s business methods. These handlers are called in response to SOAP messages targeting the service. This annotation type is deprecated. Finally, javax.xml.ws‘s most important annotation types from a RESTful Web service perspective are WebServiceProvider and BindingType. I’ll discuss these annotation types later in this series. Tools Java provides four command-line-based tools that facilitate Web service development. Two of these tools are used to convert between XML Schema-based schemas and Java classes, and the other pair of tools is used in the context of WSDL documents: schemagen: WSDL documents use XML Schema data types to describe Web service function return and parameter types. This tool generates a schema (often stored in a file with a .xsd extension) from Java classes — one schema file is created for each referenced namespace. After the schema has been created, XML instance documents (XML documents that adhere to their schemas) can be converted to and from Java objects via JAXB. The classes contain all of the information needed by JAXB to parse the XML for marshaling (converting Java objects to XML) and unmarshaling (converting XML to Java objects) — the application doesn’t perform XML parsing. wsgen: This tool reads a compiled Web service endpoint interface and generates JAX-WS portable artifacts for Web service deployment and invocation. It can alternatively generate a WSDL file and corresponding XML Schema document (when its -wsdl option is specified). This tool isn’t required when publishing a Web service via Endpoint.publish(), which automatically generates the artifacts and WSDL/schema. You’ll learn about Endpoint.publish() later in this series. wsimport: This tool generates client-support Java classes (artifacts) from a given WSDL document. These classes facilitate writing a client against the service. xjc: This tool generates Java classes from a schema. The generated classes contain properties mapped to the XML elements and attributes defined in the schema. For brevity, I demonstrate only wsimport in this series. For demonstrations of schemagen and xjc, check out Using JAXB schemagen tooling to generate an XML schema file from a Java class and Java Architecture for XML Binding (JAXB), respectively. Lightweight HTTP Server The Java SE reference implementation includes a lightweight HTTP server for deploying and testing Web services. The server implementation supports the HTTP and Hypertext Transfer Protocol Secure (HTTPS) protocols. Furthermore, its associated API can be used to create a customized Web server to enhance your Web service testing or for other purposes. Exploring the Lightweight HTTP Server API The Lightweight HTTP Server API is distributed in the following pair of packages where the first package contains the main API and the second package allows new lightweight HTTP server implementations to be installed: com.sun.net.httpserver: This package provides a high-level HTTP server API for building embedded HTTP servers. com.sun.net.httpserver.spi: This package provides a pluggable service provider API for installing HTTP server replacement implementations. The com.sun.net.httpserver package contains an HttpHandler interface, which you must implement to handle HTTP request-response exchanges. This package also declares several classes, including the following key classes: HttpServer: Implement a simple HTTP server bound to an IP address/port number, and listen for incoming TCP connections from clients. One or more associated HttpHandlers process requests and create responses. HttpsServer: An HttpServer subclass that supports HTTPS. It must be associated with an HttpsConfigurator object to configure the HTTPS parameters for each incoming Secure Sockets Layer (SSL) connection. HttpContext: Describe a mapping between a root URI path and an HttpHandler implementation that’s invoked to handle those requests targeting the path. HttpExchange: Encapsulate an HTTP request and its response. An instance of this class is passed to an HttpHandler instance to handle the request and generate a response. This interface and these classes provide various methods that you’ll use when implementing a lightweight HTTP server. Creating this implementation will involve the following tasks: Create a handler class that implements HttpHandler. The overriding void handle(HttpExchange exchange) method will access its exchange argument and invoke various HttpExchange methods, such as the following: Headers getRequestHeaders(): Return an immutable map of an HTTP request’s headers. void sendResponseHeaders(int rCode, long responseLength): Begin to send a response back to the client using the current set of response headers and rCode‘s numeric code. For example, 200 indicates success. OutputStream getResponseBody(): Return an output stream to which the response’s body is output. This method must be called after calling sendResponseHeaders(). Create the server. The abstract HttpServer class provides an HttpServer create(InetSocketAddress addr, int backlog) class method for creating a server that handles the HTTP protocol. This method’s addr argument specifies a java.net.InetSocketAddress object containing an IP address and port number for the server’s listening socket. The backlog argument specifies the maximum number of TCP connections that can be queued while waiting for acceptance by the server; a value less than or equal to zero causes a system default value to be used. Alternatively, you can pass null to addr or invoke HttpServer‘s HttpServer create() class method to create a server not bound to an address/port. If you choose this alternative, you will need to invoke HttpServer‘s void bind(InetSocketAddress addr, int backlog) method before you can use the server. Create a context. After creating the server, you need to create at least one context (an instance of a subclass of the abstract HttpContext class) that maps a root URI path to an implementation of HTTPHandler. Contexts help you organize the applications run by the server (via HTTP handlers). (The HttpServer Java documentation shows how incoming request URIs are mapped to HttpContext paths.) You create a context by invoking HttpServer‘s HttpContext createContext(String path, HttpHandler handler) method, where path specifies the root URI path, and handler specifies the HttpHandler implementation that handles all requests that target this path. If you prefer, you can invoke HttpContext createContext(String path) without specifying an initial handler. You would later specify the handler by calling HttpContext‘s void setHandler(HttpHandler h) method. Start the server. After you have created the server and at least one context (including a suitable handler), the final task is to start the server. Accomplish this task by calling HttpServer‘s void start() method. Before invoking start(), you can specify a java.util.concurrent.Executor instance that handles all HTTP requests. Accomplish this task by calling HttpServer‘s void setExecutor(Executor executor) method. You can also call Executor getExecutor() to return the current executor (the return value is null when no executor has been set). If you don’t call setExecutor() before starting the server, or if you pass null to this method, a default implementation based on the thread created by start() is used. You can stop a started server by invoking HttpServer‘s void stop(int delay) method, which closes the listening socket and prevents any queued exchanges from being processed. It then blocks until all current exchange handlers have finished or delay seconds have elapsed (whichever comes first). A java.lang.IllegalArgumentException object is thrown when delay is less than zero. Continuing, all open TCP connections are closed, and the thread created by the start() method finishes. A stopped HttpServer instance cannot be restarted. Demonstrating the Lightweight HTTP Server API I’ve created a minimal HTTP server application that demonstrates the LightWeight HTTP Server API along with the aforementioned tasks. This application’s source code appears in Listing 1. Listing 1. A minimal HTTP server implementation import java.io.IOException; import java.io.OutputStream; import java.net.InetSocketAddress; import java.util.List; import java.util.Map; import java.util.Set; import com.sun.net.httpserver.Headers; import com.sun.net.httpserver.HttpExchange; import com.sun.net.httpserver.HttpHandler; import com.sun.net.httpserver.HttpServer; public final class MinimalHTTPServer { public static void main(String[] args) throws IOException { HttpServer server = HttpServer.create(new InetSocketAddress(8000), 0); server.createContext("/echo", new Handler()); server.start(); } } class Handler implements HttpHandler { @Override public void handle(HttpExchange xchg) throws IOException { Headers headers = xchg.getRequestHeaders(); Set<Map.Entry<String, List<String>>> entries = headers.entrySet(); StringBuffer response = new StringBuffer(); for (Map.Entry<String, List<String>> entry: entries) response.append(entry.toString() + "n"); xchg.sendResponseHeaders(200, response.length()); OutputStream os = xchg.getResponseBody(); os.write(response.toString().getBytes()); os.close(); } } Listing 1’s handler echos an incoming request’s headers back to the client. Compile Listing 1 as follows: javac MinimalHTTPServer.java Run the resulting application as follows: java MinimalHTTPServer This application runs continously without displaying anything on the screen. Start a Web browser and enter http://localhost:8000/echo. Don’t forget that placing any path items before echo results in a 404 Not Found page. Figure 5 shows the echoed headers. Figure 5. Echoing an incoming request’s headers back to the client Conclusion Now that you have a basic understanding of Web services and the support that Java offers for developing them, it’s time to get practical. Part 2 of this series shows you how to build your own SOAP-based Web services in Java SE. download Download the source Get the source code for this post’s applications. Created by Jeff Friesen for JavaWorld The following software was used to develop the post’s code: 64-bit JDK 9ea+154 The post’s code was tested on the following platform(s): JVM on 64-bit Windows 8.1 JavaWeb DevelopmentDevelopment Tools