Oracle® Application Server Web Services Developer's Guide 10g (10.1.3.1.0) Part Number B28974-01 |
|
|
View PDF |
This chapter describes how Oracle Application Server Web Services supports the generation and use of REST Web Services. This chapter contains the following sections:
REST (Representational State Transfer) Web services architecture conforms to the Web architecture defined by the World Wide Web Consortium (W3C), and uses its architectural principles. It employs the semantics of HTTP whenever possible. REST Web services use XML documents, not SOAP envelopes, for sending messages. Unlike SOAP Web Services, REST is a "style" and has no standards or tools support from vendors.
When you use Oracle Application Server Web Services to expose an endpoint by using REST, that endpoint is also exposed as a SOAP port. OracleAS Web Services limits the support of HTTP commands to GET and POST. REST Web services deploy like any other OracleAS Web Services.
Note: OracleAS Web Services can assemble REST Web services only where the use, or encoding mechanism, is literal (use=literal ). It does not support REST Web services where the message format is encoded. |
Web service management features, such as security and reliability, are not available with REST Web service invocations (either REST or SOAP). This is because SOAP headers, which are typically used to carry this information, cannot be used with REST Web service invocations.
This section contains the following subsections:
You can use WebServicesAssembler to add REST Web service capabilities to any Web application that can use HTTP as a protocol. This includes Web service applications built on Java classes, EJBs, and database resources. WebServicesAssembler provides a boolean restSupport
argument that will allow any of the following commands to assemble a REST Web service.
An optional boolean restSupport
attribute can be applied to the Oracle proprietary @Deployment
annotation. If the value of the attribute is true
, then the port to which the annotation is applied will support REST-style GET
and POST
requests and responses.
See Also: "Oracle Additions to J2SE 5.0 JDK Annotations" for more information on the |
This section contains the following subsections:
The following steps illustrate assembling a REST Web service from a WSDL. This example provides only an outline of the steps required for top down Web service assembly.
See Also: Chapter 6, "Assembling a Web Service from WSDL" for a detailed description of each of the steps for assembling a Web service from a WSDL (top down). |
Provide a WSDL from which the Web service will be generated as input to the WebServicesAssembler genInterface
command.
The WSDL used in this example is illustrated in Example 12-1. The following is a sample genInterface
command.
java -jar wsa.jar -genInterface -output build/src/service -wsdl wsdl/MovieFacility.wsdl -unwrapParameters false
In this command:
genInterface
—Creates a service endpoint interface for each port type and a Java value type class (beans) for any complex type defined in a WSDL. It also creates a JAX-RPC mapping file that describes the mapping between the XML schema types and the Java value type classes. See "genInterface".
output
—Specifies the directory where generated files will be stored. If the directory does not exist, it will be created. See"output".
wsdl
—Specifies the absolute file path, relative file path, or URL to a WSDL document. See "wsdl".
unwrapParameters
—This argument can be set only for document-literal operations and will be ignored for other message formats. When set to false
the generated service endpoint interface will be generated with wrappers around the input parameter and the return type. See "unwrapParameters".
Compile the generated interface and type classes.
Implement the Java service endpoint for the Web service you want to provide.
Compile the Java service endpoint.
Generate the service by running the WebServicesAssembler tool with the topDownAssemble
command.
Set the restSupport
argument to true
. For example:
java -jar wsa.jar -topDownAssemble
-wsdl ./wsdl/MovieFacility.wsdl
-unwrapParameters false
-className oracle.webservices.examples.rest.RpcLitMovieImpl
-input build/classes/service
-output build
-ear dist/rpclit_topdown.ear
-restSupport true
In this command:
topDownAssemble
—Creates the required classes and deployment descriptors for a Web service based on a WSDL description. The files can be stored in either an EAR file, a WAR file, or a directory. See "topDownAssemble".
wsdl
—Specifies the absolute file path, relative file path, or URL to a WSDL document. See "wsdl".
unwrapParameters
—This argument can be set only for document-literal operations and will be ignored for other message formats. When set to false
the generated service endpoint interface will be generated with wrappers around the input parameter and the return type. See "unwrapParameters".
className
—Specifies the name of the class (including the package name) that is the implementation class for the Web service. See "className".
input
—Specifies the directory or JAR containing the classes that should be copied to WEB-INF/classes
. This argument will be added to the classpath used by the WebServicesAssembler. See "input".
output
—Specifies the directory where generated files will be stored. If the directory does not exist, it will be created. See "output".
ear
—Specifies the name and location of the generated EAR. See "ear".
restSupport
—Specifies whether REST (Representational State Transfer) support will be enabled for this Web service. See "restSupport".
Deploy the service.
Deploy the EAR file in the standard manner into a running instance of OC4J. For more information on deploying EAR files, see the Oracle Containers for J2EE Deployment Guide.
(Optional) Check that deployment succeeded.
OracleAS Web Services provides a Web Service Test Page for each deployed Web service. The Test Page enables you to generate and invoke any REST POST or GET requests. See "How to Use the Web Services Test Page" for information on accessing and using the Web Service Test Page.
Note: REST Web services do not use J2EE or J2SE clients. However, since every REST endpoint is also a SOAP endpoint, you can assemble J2SE or J2EE clients for those endpoints. For examples of how to create GET or POST REST messages, use the Web Services Test Page. |
Example 12-1 illustrates a fragment of the WSDL used to assemble the RPC-literal service in "Steps to Assemble a REST Web Service Top Down".
Example 12-1 WSDL Fragment for an RPC-Literal Web Service
<definitions xmlns="http://schemas.xmlsoap.org/wsdl/" xmlns:tns0="http://www.oracle.com/rest/doc/types" xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:mime="http://schemas.xmlsoap.org/wsdl/mime/" xmlns:tns="http://www.oracle.com/rest" name="rest-service" targetNamespace="http://www.oracle.com/rest" xmlns:http="http://schemas.xmlsoap.org/wsdl/http/"> <types> <schema xmlns="http://www.w3.org/2001/XMLSchema" xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:soap11-enc="http://schemas.xmlsoap.org/soap/encoding/" xmlns:tns="http://www.oracle.com/rest/doc/types" elementFormDefault="qualified" targetNamespace="http://www.oracle.com/rest/doc/types"> <complexType name="Movie"> <sequence> <element name="Title" type="xsd:string"/> <element name="Director" type="xsd:string"/> <element name="Year" type="xsd:int" /> </sequence> </complexType> <complexType name="ArrayOfMovie"> <sequence> <element name="Movie" type="tns:Movie" maxOccurs="unbounded" /> </sequence> </complexType> </schema> </types> <message name="FindMoviesRequest"> <part name="TitleWords" type="xsd:string" /> <part name="Year" type="xsd:int" /> </message> <message name="FindMoviesResponse"> <part name="Movies" type="tns0:ArrayOfMovie" /> </message> <message name="AddMovieRequest"> <part name="Movie" type="tns0:Movie" /> </message> <message name="AddMovieResponse"> <part name="Added" type="xsd:boolean" /> </message> <portType name="MovieDB"> <operation name="findMovies"> <input message="tns:FindMoviesRequest" /> <output message="tns:FindMoviesResponse" /> </operation> <operation name="addMovie"> <input message="tns:AddMovieRequest" /> <output message="tns:AddMovieResponse" /> </operation> </portType> <binding name="HttpSoap11Binding" type="tns:MovieDB"> <soap:binding style="rpc" transport="http://schemas.xmlsoap.org/soap/http"/> <operation name="findMovies"> <soap:operation soapAction="http://www.oracle.com/rest/findMovies"/> <input> <soap:body use="literal" parts="TitleWords Year" namespace="http://www.oracle.com/rest"/> </input> <output> <soap:body use="literal" parts="Movies" namespace="http://www.oracle.com/rest"/> </output> </operation> <operation name="addMovie"> <soap:operation soapAction="http://www.oracle.com/rest/addMovie"/> <input> <soap:body use="literal" parts="Movie" namespace="http://www.oracle.com/rest"/> </input> <output> <soap:body use="literal" parts="Added" namespace="http://www.oracle.com/rest"/> </output> </operation> </binding> <service name="rest-service"> <port name="HttpSoap11" binding="tns:HttpSoap11Binding"> <soap:address location="http://localhost:8888/webservice/webservice/"/> </port> </service> </definitions>
Using the preceding WSDL, the procedure described in "Steps to Assemble a REST Web Service Top Down" produces the following generated interface:
interface MovieDb { public Movie[] findMovies (String titleWords, int year); public boolean addMovie (Movie movie); }
The first method in the generated interface has only simple parameters. This method can be invoked with an HTTP GET. For example:
http://{yourhost}/{context-path}/{service-url}/findMovies?TitleWords=Star+Wars&Year=1977
This query string returns the following XML response:
<ns0:findMoviesResponse xmlns:ns0="http://www.oracle.com/rest"> <Movies> <ns1:Movie xmlns:ns1="http://www.oracle.com/rest/doc/types"> <ns1:Title>tim</ns1:Title> <ns1:Director>tim</ns1:Director> <ns1:Year>1978</ns1:Year> </ns1:Movie> </Movies> </ns0:findMoviesResponse>
The addMovie
method in the generated interface takes a complex parameter; it can only be invoked with an HTTP POST. For example, you can POST the following XML message to the URL of your Web service, http://{
yourhost
}/{
context-path
}/{
service-url
}
.
<ns0:addMovie xmlns:ns0="http://www.oracle.com/rest"> <Movies> <ns1:Movie xmlns:ns1="http://www.oracle.com/rest/doc/types"> <ns1:Title>tim</ns1:Title> <ns1:Director>tim</ns1:Director> <ns1:Year>1978</ns1:Year> </ns1:Movie> </Movies> </ns0:addMovie>
The following steps illustrate assembling a REST Web service from Java classes. This example provides only an outline of the steps required for bottom up Web service assembly.
See Also: Chapter 7, "Assembling a Web Service with Java Classes" for a detailed description of each of the steps for assembling a Web service with Java classes. |
Provide the compiled Java class that you want to expose as a Web service and its compiled interface.
Example 12-2 illustrates the StringTools
interface that is used in this example.
Generate the service artifacts by specifying the assemble
command with the restSupport
argument to true
.
java -jar wsa.jar -assemble
-appName tools
-serviceName StringTools
-interfaceName oracle.webservices.examples.rest.StringTools
-className oracle.webservices.examples.StringToolsImpl
-input ./build/classes/service
-output build
-use literal
-ear dist/tools.ear
-uri StringToolsService
-restSupport true
In this command:
assemble
—Generates a Web service from Java files bottom up. The command creates all of the files required to create a deployable archive. See "assemble".
appName
—Specifies the name of an application. Usually, this name is used as a base value for other arguments like context
and uri
. See "appName".
serviceName
—Specifies the service name. See "serviceName".
interfaceName
—Specifies the name of a Java class (including the package name) that contains the service endpoint interface (SEI). See "interfaceName".
className
—Specifies the name of the class (including the package name) that is the implementation class for the Web service. See "className".
input
—Specifies the directory or JAR containing the classes that should be copied to WEB-INF/classes
. This argument will be added to the classpath used by the WebServicesAssembler. See "input".
output
—Specifies the directory where generated files will be stored. If the directory does not exist, it will be created. See "output".
use
—For bottom up Web service assembly, this argument specifies the use
attribute of the message format in the generated WSDL. See "use".
ear
—Specifies the name and location of the generated EAR. See "ear".
uri
—Specifies the URI to use for the Web service. See "uri".
restSupport
—Specifies whether REST (Representational State Transfer) support will be enabled for this Web service. See "restSupport".
Deploy the service and bind the application.
Deploy EAR files in the standard manner into a running instance of OC4J. For more information on deploying EAR files, see the Oracle Containers for J2EE Deployment Guide.
(Optional) Check that deployment succeeded. OracleAS Web Services provides a Web Service Test Page for each deployed Web service.
The Test Page enables you to generate and invoke any REST POST or GET requests. See "How to Use the Web Services Test Page" for information on accessing and using the Web Service Test Page.
Note: REST Web services do not use J2EE or J2SE clients. However, since every REST endpoint is also a SOAP endpoint, you can assemble J2SE or J2EE clients for those endpoints. For examples of how to create GET or POST REST messages, use the Web Services Test Page. |
Example 12-2 illustrates the StringTools
interface that is used to assemble the REST Web service in Step 2 described earlier.
Example 12-2 Interface Used to Assemble REST Web Services
interface StringTools { package oracle.webservices.examples.rest; import java.rmi.Remote; import java.rmi.RemoteException; public interface StringTools extends Remote{ public String appendStrings (String a, String b) throws RemoteException; public String toUpperCase (String c) throws RemoteException; public String concatArrayOfStrings (String s[]) throws RemoteException;
The first two methods in the interface, appendStrings
and toUpperCase
, use atomic parameters. As REST Web service operations, these operations can be accessed with HTTP GET. The following example illustrates a call to the appendStrings
operation, if document
style is specified at assembly time:
http://{yourserver}/{context-path}/{service-URL}/appendStrings?String_1=Hello+&String_2=World
This query string would return the following XML response:
<appendStringsResponseElement xmlns="http://oracle.webservices.examples.rest/"> <result>Hello World</result> </appendStringsResponseElement>
The third method in the interface, concatArrayOfStrings
takes a non-atomic parameter. As a REST Web service operation, it cannot be called using HTTP GET. It can only be called with HTTP POST. For example:
<ns1:concatArrayOfStringsElement xmlns:ns1="http://oracle.webservices.examples.rest/"> <ns1:arrayOfString_1>a,</ns1:arrayOfString_1> <ns1:arrayOfString_1>b.</ns1:arrayOfString_1> </ns1:concatArrayOfStringsElement> <concatArrayOfStringsRequest xmlns="http://oracle.webservices.examples.rest/">
This request string would return the following XML code:
<ns0:concatArrayOfStringsResponseElement xmlns:ns0="http://oracle.webservices.examples.rest/"> <ns0:result>a,b.</ns0:result> </ns0:concatArrayOfStringsResponseElement>
You can use the Web Services Test Page to test whether REST Web services deployed successfully.
See Also: "Invoking the Test for a REST Web Service" for more information on using the Web Services Test Page. |
If REST support is enabled for a Web service, then an optional boolean <rest-support>
subelement is added to the <port-component>
element of the oracle-webservices.xml
deployment descriptor. If <rest-support>
is set to true
, then the port to which the subelement is applied will support REST-style GET
and POST
requests and responses. The default value is false
.
The following sections describe how REST Web service requests are formed on the client side and how they are processed on the server side.
Suppose a SOAP endpoint is deployed at the following URL:
http://example.com/my-app/my-service
If this endpoint is REST enabled, then HTTP GET requests will be accepted at the following URL:
http://example.com/my-app/my-service/{operationName}?{param1}={value1}&{param2}={value2}
In this example, {
operationName
}
is one of the operation names in the WSDL for the service. For RPC-literal operations, {
param1
}
, {
param2
}
, and so on, are the part names defined in the operation's input wsdl:message
. Note that these must be simpleTypes
(xsd:int
, and so on).
Note: Some browsers limit the size of the HTTP GET URL (typically less than 2000 characters). Try to keep the size of the URL small by using a limited number of parameters and short parameter names and values. |
For document-literal operations, messages have only a single parameter. To simulate multiple parameters, the WSDL specifies a single parameter that is defined in the schema as a sequence
. Each member of the sequence is considered a parameter. In this case, {
param1
}
, {
param2
}
, and so on, will be the members of the sequence type, instead of message
parts. As with RPC, these must be simpleTypes
.
Example 12-3 illustrates the request message defined for an operation named addNumbers
.
Example 12-3 GET Request on an Operation
<wsdl:message name="AddNumbersRequest"> <wsdl:part name="a" type="xsd:int" /> <wsdl:part name="b" type="xsd:int" /> </wsdl:Message>
This request can be invoked by using a GET with the following URL:
http://{yourhost}/{context-path}/{service-url}/addNumbers?a=23&b=24
Example 12-4 illustrates the SOAP envelope that the OracleAS Web Services platform will create on the server side from the GET request. This message will be processed like any other incoming SOAP request.
Example 12-4 SOAP Envelope Created from a GET Request
<soap:Envelope> <soap:Body> <ns:addNumbers> <ns:a>23</ns:a> <ns:b>24</ns:b> </ns:addNumbers> <soap:Body> <soap:Envelope>
Example 12-5 illustrates the request message sent for the addNumbers
service when it is defined as a document-literal operation.
Example 12-5 Sample GET Request on an Document-Literal Wrapped Operation
<wsdl:message name="AddNumbersRequest"> <wsdl:part name="params" type="tns:AddNumbersRequstObject" /> </wsdl:Message>
Example 12-6 illustrates the definition of the AddNumbersRequestObject
as it would be defined in the schema.
Example 12-6 XML Definition of a Document-Literal Wrapped Operation
<xsd:complexType name="AddNumbersRequestObject"> <xsd:complexContent> <xsd:sequence> <xsd:element name="a" type="xsd:int"/> <xsd:element name="b" type="xsd:int"/> </xsd:sequence> </xsd:complexContent> </xsd:complexType>
This operation can be invoked by a GET request with the following URL. Note that this is the same URL that is used for the RPC-literal request in Example 12-3.
http://{yourhost}/{context-path}/{service-url}/addNumbers?a=23&b=24
REST Web services support HTTP POST requests that are simple XML messages—not SOAP envelopes. REST requests do not support messages with attachments. Since the service also supports SOAP requests, the implementation must determine if a given request is meant to be SOAP or REST.
When a SOAP service receives a POST request, it looks for a SOAPAction
header. If it exists, the implementation will assume that it is a SOAP request. If it does not, it will find the QName
of the root element of the request. If it is the SOAP Envelope QName
, it will process the message as a SOAP request. Otherwise it will process it as a REST request.
REST requests will be processed by wrapping the request document in a SOAP envelope. The HTTP headers will be passed through as received, except for the Content-Type header in a SOAP 1.2 request. This Content-Type header will be changed to the proper content type for SOAP 1.2, application/soap+xml
.
For example, the following REST request illustrated in Example 12-7 will be wrapped in the SOAP envelope illustrated in Example 12-8.
The request illustrated in Example 12-8 will be processed as a normal SOAP request.
For any request (either GET or POST) that was processed as a REST request, the response must also be in REST style. The OracleAS Web Services platform will transform the SOAP response on the server into a REST response before sending it to the client. The REST response will be an XML document whose root Element is the first child Element of the SOAP Body. For example, assume that the SOAP envelope illustrated in Example 12-9 exists on the server.
Example 12-9 SOAP Response
<soap:Envelope> <soap:Body> <ns0:result xmlns:nso="…"> <ns:title>How to Win at Poker</ns:title> <ns:author>John Doe</ns:author> </ns0:result> </soap:Body> </soap:Envelope>
Example 12-10 illustrates the response sent back to the client. Note that the Content-Type will always be text/xml
. Any SOAP Headers or attachments will not be sent back to the client.
The Create Java Web Service wizard in Oracle JDeveloper provides an option for enabling REST functionality for a Web service. For more information on using Oracle JDeveloper to enable REST functionality in a Web Service, see the Oracle JDeveloper on-line help.
For more information on:
assembling a Web service from a WSDL, see Chapter 6, "Assembling a Web Service from WSDL".
assembling a Web service from Java classes, see Chapter 7, "Assembling a Web Service with Java Classes".
assembling a Web service from EJBs, see Chapter 8, "Assembling a Web Service with EJBs".
assembling a Web service from database resources, see Chapter 10, "Assembling Database Web Services".
testing REST Web services, see Chapter 13, "Testing Web Service Deployment".