Skip Headers
Oracle® Application Server Web Services Developer's Guide
10g Release 3 (10.1.3)
B14434-01
  Go To Documentation Library
Home
Go To Product List
Solution Area
Go To Table Of Contents
Contents
Go To Index
Index

Previous
Previous
Next
Next
 

11 Assembling REST Web Services

REST (Representational State Transfer) Web services architecture conforms to the Web architecture defined by the World Wide Web Consortium (W3C), and leverages its architectural principles. It uses 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 support, 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 services. This is because SOAP headers, which are typically used to carry this information, cannot be used with REST Web service invocations.

Assembling REST Web Services

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.

How to Assemble a REST Web Service Top Down

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. For a detailed description of each of the steps, see Chapter 5, "Assembling a Web Service from a WSDL"

  1. Provide a WSDL from which the Web service will be generated as input to the WebServicesAssembler genInterface command. Example 11-1 illustrates the WSDL used in this example.

    java -jar wsa.jar -genInterface 
                      -output build/src/service  
                      -wsdl wsdl/MovieFacility.wsdl 
                      -unwrapParameters false 
    
    
  2. Compile the generated interface and type classes.

  3. Implement the Java service endpoint for the Web service you want to provide.

  4. Compile the Java service endpoint.

  5. 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
    
    
  6. 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.

  7. (Optional) Check that deployment succeeded. OracleAS Web Services provides a Web Service Home Page for each deployed Web service. The Home Page enables you to generate and invoke any REST POST or GET requests. See "Using the Web Services Home Page" for information on accessing and using the Web Service Home 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 a J2SE or J2EE clients for those endpoints. For examples of how to create GET or POST REST messages, use the Web Services Home Page.

Accessing REST Web Service Operations

Example 11-1 illustrates a fragment of the WSDL used to assemble the RPC-Literal service in "How to Assemble a REST Web Service Top Down".

Example 11-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 "How 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}/findMovie?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:addMovieResponse xmlns:ns0="http://www.oracle.com/rest">
   <Added>true</Added>
</ns0:addMovieResponse>

How to Assemble a REST Web Service Bottom Up

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. For a detailed description of each of the steps, Chapter 6, "Assembling a Web Service with Java Classes".

  1. Provide the compiled Java class that you want to expose as a Web service and its compiled interface. Example 11-2 illustrates the StringTools interface that is used in this example.

  2. Generate the service artifacts by running the WebServicesAssembler tool with the assemble command. Set 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
    
    
  3. 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.

  4. (Optional) Check that deployment succeeded. OracleAS Web Services provides a Web Service Home Page for each deployed Web service. The Home Page enables you to generate and invoke any REST POST or GET requests. See "Using the Web Services Home Page" for information on accessing and using the Web Service Home 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 Home Page.

Accessing REST Web Service Operations

Example 11-2 illustrates the StringTools interface that is used to assemble the REST Web service in Step 2 above.

Example 11-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="{yournamespace}">
     <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="{yournamespace}">

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>

REST Additions to Deployment Descriptors

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. For more information on this subelement, see "<port-component> Element".

Using J2SE 5.0 Annotations to Assemble REST Web Services

An optional Boolean restSupport attribute can be applied to the @Deployment tag in J2SE 5.0 annotations. Its value indicates whether the service is a REST Web service. If true, the port to which the annotation is applied will support REST-style GET and POST requests and responses. For more information on this attribute and the Deploy tag, see "Oracle Additions to J2SE Annotations".

Testing REST Web Services

You can use the Web Services Home Page to test whether REST Web services deployed successfully. See "Using the Web Services Home Page for REST Services" for more information.

Building Requests and Responses

The following sections describe how REST Web service requests are formed on the client side and how they are processed on the server side.

HTTP GET Requests

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. Try to keep the size of the URL small by using a limited number of parameters and short parameter 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 11-3 illustrates the request message defined for an operation named addNumbers.

Example 11-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 11-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 11-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 11-5 illustrates the request message sent for the addNumbers service when it is defined as a document-literal operation.

Example 11-5 Sample GET Request on an Document-Literal Wrapped Operation

<wsdl:message name="AddNumbersRequest"> 
     <wsdl:part name="params" type="tns:AddNumbersRequstObject" />
</wsdl:Message>

Example 11-6 illustrates the definition of the AddNumbersRequestObject as it would be defined in the schema.

Example 11-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 11-3.

http://{yourhost}/{context-path}/{service-url}/addNumbers?a=23&b+24

HTTP POST Requests

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 11-7 will be wrapped in the SOAP envelope illustrated in Example 11-8.

Example 11-7 REST Request

<ns:addNumbers> 
    <ns:a>23</ns:a> 
    <ns:b>24</ns:b> 
</ns:addNumbers>

The request illustrated in Example 11-8 will be processed as a normal SOAP request.

Example 11-8 SOAP Envelope Wrapping the REST Request

<soap:Envelope> 
       <soap:Body> 
               <ns:addNumbers> 
                       <ns:a>23</ns:a> 
                       <ns:b>24</ns:b> 
               </ns:addNumbers> 
           </soap:Body> 
</soap:Envelope>

REST Responses

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 11-9 exists on the server.

Example 11-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 11-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.

Example 11-10 REST Response

<ns0:result xmlns:ns0="…"> 
       <ns:title>How to Win at Poker</ns:title> 
       <ns:author>John Doe</ns:author> 
</ns0:result>

Tool Support for REST Web Services

The Create Java Web Service wizard in JDeveloper provides an option for enabling REST functionality for a Web service. For more information on using JDeveloper to enable REST functionality in a Web Service, see the JDeveloper on-line help.

Limitations

See "Assembling REST Web Services".

Additional Information

For more information on: