Chapter 13. Web Services

The term web service refers to a web-accessible application that performs some action based on a request from a client. For these entities to communicate, an agreed upon language, or communication protocol, must be used. The first web services used the Simple Object Access Protocol (SOAP), which is an XML-based messaging protocol. Although SOAP is effective, it is often perceived as being a heavy-weight and difficult to use.

The Representational State Transfer (REST) architecture, created by Roy Fielding in 2000, is a specification for building web services that is much simpler than SOAP. Both concepts have their pros and cons, but REST is emerging as the more popular of the two—as evidenced by its adoption by Yahoo, Facebook, and others. In addition, REST has become an integral component of Java starting with Java 6.

In APEX 4.0, you now have wizards for creating web service references for both SOAP and REST-based web services. Prior versions of APEX supported only SOAP web services. It is important to note that the APEX wizards build web service clients, not the actual web services. You either need a WSDL file to access a SOAP web service or knowledge of the input requirements for a RESTful web service.

In this chapter, we will work with both SOAP and RESTful web services, some of which are publicly available and some we will build on our own. We'll also explore the many APEX objects that can be based on web services, including Forms, Reports, and Processes.

Creating a Native Database Web Service

We will first take a look at SOAP web services from both the client and service perspective. The Oracle Database itself is a great resource for learning about web services since you can easily expose a stored procedure or function as a SOAP web service. Oracle calls this ability to expose stored procedures Native Database Web Services. The XML DB feature of the database can be used to store and manipulate native XML data, but it also allows you to expose procedures and functions as web services and lets you call them using HTTP. Actually, the XML DB feature is used to implement the Embedded PL/SQL Gateway used to access APEX. After we create our web service in the database, we'll use APEX to create a web service reference to consume it.

We could have just chosen to demonstrate how APEX works using an Amazon or Yahoo web service, but then you would only see how APEX is used to build a client. Without some understanding of web services in general, you may not understand what is happening in APEX. You will learn a great deal more by building your own web service as opposed to just using an existing one. When we're finished with these examples, you should feel comfortable utilizing any web service whether SOAP- or REST-based.

Before we start coding, we need to enable Native Database Web Services in the 11g database. The first order of business is to enable the HTTP listener that is built in to the database. The script in Listing 13-1 shows how to evaluate the current HTTP port setting and then how to set it. The HTTP port is considered disabled if it is set to zero. You can choose any port number you like, but using 8080 is recommended as it is universally recognized as a non-production, HTTP port. Some operating systems like Linux / Unix will restrict the use of port numbers below 1024.

Example 13-1. Set the XML Database HTTP Listener Port

SQL> CONN sys/password@db11g AS SYSDBA

SQL> SELECT dbms_xdb.gethttpport FROM dual;

GETHTTPPORT
-----------
          0

SQL> EXEC dbms_xdb.sethttpport(8080);

PL/SQL procedure successfully completed.

SQL>

At this point, you can access database resources via browser at the port you set for the XDB HTTP listener. Use the URL shown in Listing 13-2 to access the XML Database root replacing the <host:port> label with your values.

Example 13-2. Access the XDB Root Directory

http://<host:port>/

Index of /

Name                    Last modified                       Size

_______________________ ___________________________________ ______

OLAP_XDS/               Mon, 03 Jan 2011 17:23:21 GMT       -

images/                 Sat, 15 Aug 2009 00:49:30 GMT       -

olap_data_security/     Sat, 15 Aug 2009 00:35:56 GMT       -

public/                 Sat, 15 Aug 2009 00:30:14 GMT       -

sys/                    Sat, 15 Aug 2009 00:31:15 GMT       -

xdbconfig.xml           Sun, 10 Apr 2011 20:05:55 GMT       0

xds/                    Sat, 15 Aug 2009 00:35:56 GMT       -

Note

The XML Database HTTP listener is actually controlled by the database listener. If you forget to start the database listener, you will not have access to the HTTP port of the XML Database.

The script in Listing 13-3 is used to create a servlet in the database, called orawsv, which enables database-stored procedures and functions to be called via HTTP. When you call a database resource via this servlet, it will create a Web Services Description Language (WSDL) file for the object you are calling. The WSDL file is used by the web service client to identify how the web service is to be used. In short, the WSDL file shows the inputs required to use the web service and the output it will generate. The format of the WSDL file is based on a W3C standard, so automating its creation is pretty easy. When you use APEX to consume a web service, however, you may never see the WSDL file as it is used behind the scenes.

Example 13-3. Create the orawsv Servlet

CONN sys/password@db11g AS SYSDBA

DECLARE
  l_servlet_name VARCHAR2(32) := 'orawsv';
BEGIN
  DBMS_XDB.deleteServletMapping(l_servlet_name);

  DBMS_XDB.deleteServlet(l_servlet_name);

  DBMS_XDB.addServlet(
    name     => l_servlet_name,
    language => 'C',
    dispname => 'Oracle Query Web Service',
    descript => 'Servlet for issuing queries as a Web Service',
    schema   => 'XDB'),

  DBMS_XDB.addServletSecRole(
    servname => l_servlet_name,
    rolename => 'XDB_WEBSERVICES',
    rolelink => 'XDB_WEBSERVICES'),

  DBMS_XDB.addServletMapping(
    pattern => '/orawsv/*',
    name    => l_servlet_name);
END;
/

After creating the servlet in Listing 13-3, you can verify that it was done correctly using the script shown in Listing 13-4. The Result Sequence, the output of the XQuery script, is used to show that the servlet was created correctly and which role is required to execute it.

Example 13-4. Verify Creation of the orawsv Servlet

SET LONG 10000
XQUERY declare default element namespace "http://xmlns.oracle.com/xdb/xdbconfig.xsd"; (: :)
       (: This path is split over two lines for documentation purposes only.
          The path should actually be a single long line. :)
       for $doc in fn:doc("/xdbconfig.xml")/xdbconfig/sysconfig/protocolconfig/httpconfig/
        webappconfig/servletconfig/servlet-list/servlet[servlet-name='orawsv']
       return $doc
/

Result Sequenc
--------------------------------------------------------------------------------
<servlet xmlns="http://xmlns.oracle.com/xdb/xdbconfig.xsd">
  <servlet-name>orawsv</servlet-name>
  <servlet-language>C</servlet-language>
  <display-name>Oracle Query Web Service</display-name>
  <description>Servlet for issuing queries as a Web Service</description>
  <servlet-schema>XDB</servlet-schema>
  <security-role-ref>
    <description/>
    <role-name>XDB_WEBSERVICES</role-name>
    <role-link>XDB_WEBSERVICES</role-link>
  </security-role-ref>
</servlet>

Now that we have an HTTP listener and a servlet, we can call a stored procedure or function as a web service. Using the Buglist table, we'll create a simple package / function that will return the number of bugs based on the priority. While such a function may not be the best functional example of a web service, creating and invoking it will illustrate the process and give you a simple base from which to build. Listing 13-5 shows the creation of the BUGTYPE package and package body.

Example 13-5. BUGTYPE Package

create or replace
package bugType as
  function bugTypeCount(bugType in out varchar2) return number;
end bugType;
/

create or replace
package body bugType as
  function bugTypeCount(bugType in out varchar2)
  return number
  is
    bugCount number;
  begin
    select count(bugid) into bugCount
    from   buglist
    where  priority = bugType;
return bugCount;
  end;
end bugType;
/

The last step related to the creation of the Native Database Web Service is to grant the appropriate roles to the user who owns the web service resource, as shown in Listing 13-6. Granting the role XDB_WEBSERVICES_WITH_PUBLIC is optional as this allows the user to access any PUBLIC database object via web service. For testing, it doesn't really matter which schema(s) you use, but when you start implementing XML Database web services in production, you may want to limit the number of web service object owners so you can more easily manage security.

Example 13-6. Grant Appropriate Roles to Web Service Object Owner

SQL> CONN SYS AS SYSDBA
SQL> GRANT XDB_WEBSERVICES TO apexdemo;
SQL> GRANT XDB_WEBSERVICES_OVER_HTTP TO apexdemo;
SQL> GRANT XDB_WEBSERVICES_WITH_PUBLIC TO apexdemo;

To test the configuration, you can now turn to your browser. As discussed previously, the orawsv servlet will create a WSDL file for you automatically. You can generate the WSDL file in your browser by going to one of the following URLs:

For packaged procedures or functions:

http://<host:port>/orawsv/<USER>/<PACKAGE>/<PROC or FUNC>?wsdl

For regular procedures or functions:

http://<host:port>/orawsv/<USER>/<PROC or FUNC>?wsdl

Note that your user name, package name, and procedure or function name must be in uppercase in the URL. If you forget this detail, you will get back a generic error message with no explanation as to the issue. If you get the URL right and the configuration is all correct, your browser will display the WSDL file, which looks like the one in Listing 13-7.

Example 13-7. WSDL File Generated by orawsv Servlet

- <definitions name="BUGTYPECOUNT"
targetNamespace="http://xmlns.oracle.com/orawsv/INSTRUCTOR/BUGTYPE/BUGTYPECOUNT"
xmlns="http://schemas.xmlsoap.org/wsdl/"
xmlns:tns="http://xmlns.oracle.com/orawsv/INSTRUCTOR/BUGTYPE/BUGTYPECOUNT"
xmlns:xsd="http://www.w3.org/2001/XMLSchema"
xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/">
- <types>
- <xsd:schema targetNamespace="http://xmlns.oracle.com/orawsv/INSTRUCTOR/BUGTYPE/BUGTYPECOUNT"
elementFormDefault="qualified">
- <xsd:element name="SNUMBER-BUGTYPECOUNTInput">

- <xsd:complexType>
- <xsd:sequence>
<xsd:element name="BUGTYPE-VARCHAR2-INOUT" type="xsd:string" />
  </xsd:sequence>
  </xsd:complexType>
  </xsd:element>

- <xsd:element name="BUGTYPECOUNTOutput">

- <xsd:complexType>

- <xsd:sequence>
  <xsd:element name="RETURN" type="xsd:double" />
  <xsd:element name="BUGTYPE" type="xsd:string" />
  </xsd:sequence>
  </xsd:complexType>
  </xsd:element>
  </xsd:schema>
  </types>

- <message name="BUGTYPECOUNTInputMessage">
  <part name="parameters" element="tns:SNUMBER-BUGTYPECOUNTInput" />
  </message>

- <message name="BUGTYPECOUNTOutputMessage">
  <part name="parameters" element="tns:BUGTYPECOUNTOutput" />
  </message>

- <portType name="BUGTYPECOUNTPortType">

- <operation name="BUGTYPECOUNT">
  <input message="tns:BUGTYPECOUNTInputMessage" />
  <output message="tns:BUGTYPECOUNTOutputMessage" />
  </operation>
  </portType>

- <binding name="BUGTYPECOUNTBinding" type="tns:BUGTYPECOUNTPortType">
  <soap:binding style="document" transport="http://schemas.xmlsoap.org/soap/http" />

- <operation name="BUGTYPECOUNT">
  <soap:operation soapAction="BUGTYPECOUNT" />

- <input>
  <soap:body parts="parameters" use="literal" />
  </input>

- <output>
  <soap:body parts="parameters" use="literal" />
  </output>
  </operation>
  </binding>
- <service name="BUGTYPECOUNTService">
  <documentation>Oracle Web Service</documentation>
- <port name="BUGTYPECOUNTPort" binding="tns:BUGTYPECOUNTBinding">
<soap:address location="http://oim:8080/orawsv/INSTRUCTOR/BUGTYPE/BUGTYPECOUNT" />
  </port>
  </service>
  </definitions>

We won't go into much detail about what is in the WSDL file other than to say that it follows the W3C standards for WSDL 1.1 documents. The important things to note are the inputs and outputs (highlighted in Listing 13-7). The nice thing about WSDL-based web services is that the WSDL file is generated automatically and most web service development tools will automatically build the code necessary to call the web service. APEX is no exception. You don't really need to see the WSDL file in order to use the web service in APEX.

Creating a WSDL-based Web Service Reference in APEX

Having verified that our Native Database Web Service exists, we can now use that resource in an APEX application. You start the process by accessing the Web Service References menu in Shared Components, which brings up the Web Service References home page shown in Figure 13-1.

Web service reference home page

Figure 13.1. Web service reference home page

When you click the Create button you will be presented with three options for creating a web service: REST, Based on WSDL, and Manual. Since we will first use our Native Database Web Service, which is WSDL-based, choose "Based on WSDL" and click Next.

Web service type selection

Figure 13.2. Web service type selection

You now have the option to search the Universal Description, Discovery and Integration Registry (UDDI) to find a WSDL file. A UDDI registry is a directory service that allows organizations to register their identities and search for other registered businesses. Not only can you locate information about companies in a UDDI, but also the web services they choose to make public. Since we created our own web service, we will not use the UDDI registry and so the radio button shown in Figure 13-3 can be set to No.

Bypass the UDDI registry search

Figure 13.3. Bypass the UDDI registry search

Previously, we viewed the WSDL file for our web service, which was generated automatically by the database. We will use that same syntax to identify the web service we want to use in APEX, as shown in Figure 13-4. APEX uses the information is the WSDL file to build the input to the web service automatically. You may never actually see the SOAP request unless you build the Web Service Reference manually. If you choose to do the work yourself, the SOAP request must be formatted as follows:

<?xml version="1.0" encoding="UTF-8"?>
<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/"
xmlns:tns="http://oim:8080/APEXDEMO/BUGTYPECOUNT"
xmlns:xs="http://www.w3.org/2001/XMLSchema">
   <soap:Body>
      <tns:BUGTYPECOUNT>
         <tns:bugType>#ZIP#</tns:bugType>
      </tns:BUGTYPECOUNT>
   </soap:Body>
</soap:Envelope>

Note

The main difference between WSDL-based web services and RESTful web services are that RESTful web services do not require a SOAP request. Input parameters are provided to a RESTful web service directly in the URL.

Identify the WSDL file

Figure 13.4. Identify the WSDL file

The username and password fields must be populated using the web service owner's database credentials. While it is possible to allow anonymous HTTP access to the database via the XML DB listener, Native Database Web Services require authentication. If you omit the username and password, APEX will display the error message shown in Figure 13-5, which does not accurately describe the issue. It should notify you that the username and password are required for this web service, but it doesn't, which can leave you scratching your head and searching for a solution. If you do supply an invalid username and/or password, the error message will report the issue correctly.

Error message if username and password are blank

Figure 13.5. Error message if username and password are blank

If you provide the correct inputs, the last step is to verify the settings and select whether or not the web service requires basic authentication. In the case of Native Database Web Services, basic authentication is required. What this means is that the username and password must be included in the SOAP request to this web service. APEX will help you with this also, as we will see shortly. The verification page should look like Figure 13-6.

Web service verification page

Figure 13.6. Web service verification page

When you click the Create Reference button, the web service reference is saved and a new wizard is started (see Figure 13-7), which assists you in using the new object on an APEX page. The best way to test your web service is to select the option that creates a form and a report on the web service. This will generate one page with a Form region containing the input items and a Report region that will display the output from the web service.

Web service page creation wizard

Figure 13.7. Web service page creation wizard

The first step in the new wizard, shown in Figure 13-8, allows you to select a web service reference to use in your new page. In our case, there is only one web service reference: the one we just created. Once you select the service, the remaining steps in the wizard guide you through the familiar process of building regions, items, and a report.

Web service reference selection for new page

Figure 13.8. Web service reference selection for new page

Following the selection of the web service reference, Figure 13-9 shows that you can select any operation that is included in the web service. In our example, there is only one operation available, but we could have added more by basing the web service on a package and adding multiple functions.

Selection of the web service reference operation

Figure 13.9. Selection of the web service reference operation

The wizard will now create a new page to house the web service reference. You can change the characteristics of the page, as shown in Figure 13-10, to suit your needs. As you can see from the workflow steps on the left side of the page, this is a relatively lengthy process with a few steps that you don't normally see during page creation. We intentionally left Breadcrumbs and Tabs out of this page to keep it simple.

New web service reference page settings

Figure 13.10. New web service reference page settings

The wizard next creates a page item that will be used to pass the input value to the web service. In web service lingo, this item is used to populate the input value in the SOAP envelope. Of course you won't see the SOAP envelope, which is one of the benefits of the web service architecture. Since APEX is enabling the web service behind the scenes, it uses web service lingo to name the input field. You can see how APEX sets the item name and label and how we changed it to make it more user-friendly in the following:

Default Item Name                  Default Item Label
---------------------------------- ----------------------------
P46_BUGTYPE-VARCHAR2-INOUT         Bugtype-Varchar2-Inout

Our Item Name                      Our Item Label
---------------------------------- ----------------------------
P46_WS_INPUT                       Priority

We changed the item name to show what functions as the input to the web service. For the item label, we set it to show that the input value must be the priority that you want to count. When the page is built, your user will appreciate these changes. Figure 13-11 shows the page that you set these values. There is also a "create" field that can be set to either "yes" or "no." In this example, we have only one input value so you must set this value to "yes." If you have a web service with multiple input values, you may want to set some or all of the "create" attributes to no and display them programmatically.

Naming the web service input item

Figure 13.11. Naming the web service input item

Since Native Database Web Services require authentication, the next step of the process allows you to define item names and labels for the web service authentication parameters. In Figure 13-12, notice that we used the settings for the authentication items that APEX generated for us.

Defining the web service authentication items

Figure 13.12. Defining the web service authentication items

Next, we are required to define an APEX Collection, as shown in Figure 13-13, in which to store the results of the web service. Collections are used since a web service may return more than one value and you will need access to all of them. In addition, the report that is created as part of this process will use the collection as its data source. You must also select the "Result Tree to Report On." What this refers to is the component of the web service output that you want to include in the report. Since we are returning a single value, the wizard shows only one radio button (which is required) for the BUGTYPECOUNTOutput tag in the WSDL file.

Identifying the collection to store the web service output

Figure 13.13. Identifying the collection to store the web service output

We are now at the point where the report is defined. Remember way back at the beginning of this process we elected to create a Form and a Report? The report will display the output of our web service. The Form definition is basically done and now we have to decide what to display on the report. Figure 13-14 shows the available report parameters based on what APEX found in the WSDL file. The RETURN item is the return value from the web service while the BUGTYPE item is the value that you sent to the web service. For this example, we would recommend selecting both items so you can see the value of the Priority along with the number of bugs with this designation.

Note

The position of the buttons partially atop the "Result Parameters to Display" titlebar is not a misprint. That is exactly how this page is rendered by APEX no matter how wide you make the page.

Setting web service report parameters

Figure 13.14. Setting web service report parameters

As stated earlier, we omitted Breadcrumbs and Tabs to keep the page simple. The last step, then, is to confirm the settings of the Form and Report built on your web service, as shown in Figure 13-15. If everything is correct, click the "Create Form and Report" button to take the next step towards seeing your web service in action.

Setting web service report parameters

Figure 13.15. Setting web service report parameters

In the final step of this wizard (finally), APEX builds the page for you, tells you that everything was created successfully, and provides a "Run Page" button that takes you directly to the page so that you can test it. Figure 13-16 shows the new page as it is initially displayed. You will have to supply a valid user ID and password along with a priority (Critical, for example). Earlier we granted access to our web service to the database user apexdemo, so this is the only user who can exercise this web service.

Setting web service report parameters

Figure 13.16. Setting web service report parameters

When you enter a valid value for the priority and press the Submit button, the web service is called and the fruits of all our labor are revealed. In Figure 13-17, you see that the report region is populated showing the value we sent to the web service and returned value.

Web service results

Figure 13.17. Web service results

If you need to make changes to the configuration of the web service, we recommend that you delete it and re-create it. You need to edit the web service reference you just created to understand why this is true. If you go back to the Web Services Reference section of Shared Components, you will now see an icon for your web service reference. When you click on the icon, you will see a single page like the one shown in Figure 13-18. There is no wizard to assist you in changing the settings of the web service reference. If, for example, you need to change the username and password for the web service, you will have to delete and re-add the web service reference.

You can, however, make changes to anything else about the page in the normal fashion. You can do things like change the order of the fields in the results report, modify labels, add other objects, and so forth. The web service configuration is really only tied to the action triggered by the Submit button. Now that you have a web service saved in the system, you can also go to the home of any application and add a form based on the web service and APEX will present you with the same wizard we just used in this example.

Web serivce results

Figure 13.18. Web serivce results

Creating a RESTful Web Service

As discussed in the opening paragraphs of this chapter, RESTful web services are gaining in popularity since they are simpler to implement and use than their WSDL-based counterparts. The REST architecture operates very much like a standard HTML page in that a call is made to a RESTful web service using HTTP with one of four specific verbs : GET, POST, PUT, or DELETE. You probably recognize the first two as being the same methods you would use in an HTML form. The last two, PUT and DELETE, are not normally used in HTML forms.

To understand the REST concept and how these HTTP verbs are used, think of a standard APEX form that supports Create, Retrieve, Update, and Delete activities (commonly called a CRUD form). The REST architecture maps CRUD operations to HTTP verbs in the following manner:

  • REST Create - HTTP POST

  • REST Retrieve - HTTP GET

  • REST Update - HTTP PUT

  • REST Delete - HTTP DELETE

If you wanted to update a record via a RESTful web service, you would call the service at its URL, or endpoint, which would look something like this:

http://<server:port>/<service>

The RESTful web service would need to know how and where to perform its operation. The "how" is represented by the HTTP verb sent to the service. In an update, the verb passed to the web service would be PUT. To define "where" this operation should take place, the ID of the record to be updated would be sent in the URL like this:

http://<server:port>/<service>/<id>

Just by looking at the URL, you can't infer the purpose of this web service call since the HTTP verb cannot be seen. The RESTful web service in this example could be a Java servlet that performs a CRUD action based on the HTTP verb sent to it. If the HTTP verb was DELETE, then the <id> would tell the web service which record, for example, to delete. Notice that there was no mention of XML or WSDL. This is why people are starting to warm up to RESTful web services. It looks a lot like standard HTML, which means there's not much new stuff to learn and the web service itself does not have to follow a rigid standard. Although it looks as if you could call a RESTful web service with a standard HTML form in a browser, you can only send HTTP POST and GET verbs from a browser-based form. Therefore, you need a separate tool (client program) that can generate any of the four HTTP verbs.

To demonstrate the creation of a RESTful web service, it would be nice to be able to use the database server like we did for the WSDL-based variety, but Oracle only supports WSDL type Native Database Web Services. Another way to create a RESTful service would be to set up a Java application server, but that is outside the scope of this book. So, what do we do? We use APEX 4.0, which now allows you to create a RESTful web service out of any existing APEX report.

The first order of business, however, is to enable RESTful access to an APEX 4.0 instance. This can only be done via the APEX Administration interface. On the Mange Instance page, the Instance Settings section contains a link called "Security" that takes you to the page shown in Figure 13-19. The Allow RESTful Access setting is set to "No" by default so just set it to "Yes" and apply the changes. You can then log out of the Administration interface.

Note

If you have never been to the administration page in Figure 13-19, you will be prompted to set the "Maximum Login Failures Allowed" and "Account Password Lifetime" attributes even if the "Require User Account Expiration and Locking" attribute is set to "no." You must provide positive integer values for both attributes, but the resulting behavior will still depend on the "Require User Account Expiration and Locking" setting.

Enable RESTful web service access

Figure 13.19. Enable RESTful web service access

We want to keep this example nice and clean so we created a standard, interactive report on the Buglist table to use as our RESTful web service. We created the report on a new page because one of the requirements of exposing a report as a RESTful web service is that the page that contains the report must be made public, as shown in Figure 13-20.

Making the RESTful web service page public

Figure 13.20. Making the RESTful web service page public

Navigate back to the Page Definition of the page you're using for your RESTful web service and click on the region that contains the report you want to expose. Click on the region name that contains the report and view the attributes section of the Report Definition page, as shown in Figure 13-21. Change the "Enable RESTful access" attribute to "Yes." When you enable RESTful access, you also have to set a Static ID for the report object. The Static ID will be used when calling the report as a web service. Apply these changes, which will take you back to the edit report page.

Making the RESTful web service page public

Figure 13.21. Making the RESTful web service page public

If you navigate back to the report region you were just on and view the region definition attributes, you'll see that APEX has generated some very important information regarding your RESTful web service. Figure 13-22 shows that the bottom of the Attributes section now contains the actual URL that you, or anyone else, can use to access your report via a web service call. APEX even labels the URL as "REST Access URL" to ensure you know what it's for.

Rest Access URL generated automatically

Figure 13.22. Rest Access URL generated automatically

The result of accessing this URL is shown in Listing 13-8. It is a very readable XML document containing a <ROWSET> tag that signifies that a bunch of rows will follow along with multiple <ROW></ROW> tags that contain your data by row. Your client is now free to format that data in any way they see fit.

Example 13-8. XML Result of a Call to a Report Exposed as a RESTful Web Service

<ROWSET>
  <ROW>
    <ID>1</ID>
    <BUGID>1</BUGID>
    <REPORTED>27.01.06</REPORTED>
    <STATUS>Open</STATUS>
    <PRIORITY>High</PRIORITY>
    <DESCRIPTION>Pressing Cancel on the login screen gives an error</DESCRIPTION>
    <REPORTED_BY>RHuson</REPORTED_BY>
    <ASSIGNED_TO>John Scott</ASSIGNED_TO>
  </ROW>
  <ROW>
    <ID>2</ID>
    <BUGID>2</BUGID>
    <REPORTED>02.01.06</REPORTED>
    <STATUS>Closed</STATUS>
    <PRIORITY>High</PRIORITY>
    <DESCRIPTION>Logo occasionally does not appear</DESCRIPTION>
    <REPORTED_BY>CWhite</REPORTED_BY>
    <ASSIGNED_TO>Peter Ward</ASSIGNED_TO>
  </ROW>
...
</ROWSET>

While the foregoing is a great way to demonstrate a RESTful web service and also to make your application more accessible to others, it doesn't really benefit your application. To do that, we would need to call an external, RESTful web service.

Invoking an External Service

As mentioned before, organizations like Yahoo and Amazon have made RESTful web services available to the public so we can use one of those as an example. Since APEX does not allow you to declaratively build a RESTful web service, we won't go into detail about how the web services work, just how to use them.

We'll use Yahoo's RESTful web service for mapping to illustrate how APEX handles external web services. The prerequisite to running this example is to get a Yahoo Application ID. Yahoo requires that you identify how you're going to use their web service, but they ask only for minimal information before creating an application ID. You'll have to supply the application ID in all calls to the Yahoo RESTful web service. We'll create a page item for the application ID and make it visible, but once you get the process working you can make it invisible and default the value, since it is not important that the user see the application ID. The Yahoo page you use to start the application ID creation process is at the following location:

https://developer.yahoo.com/maps/rest/V1/

Click the "get an application ID" link to display the page that actually generates the application ID, as shown in Figure 13-23. If you don't have a Yahoo account, you will be asked to create one. Once you arrive at the Developer Registration page, fill it out so it looks something like Figure 13-23.

Note

Once you receive the application ID from Yahoo, we recommend that you copy and paste it into a document on your computer so it is easy to find if you need it again. Otherwise you will have to go back to Yahoo, login, and look around to find your application ID.

Yahoo developer network registration

Figure 13.23. Yahoo developer network registration

The next page will contain the application ID, which you should copy and store on your computer because you will need to enter it when you run your new page. Back in APEX, navigate to the Shared Components home page and click on "Web Service Reference," then click the Create button. For this example, you will choose the "REST" radio button, which will start the "REST Web Service Details" wizard as shown in Figure 13-24. The values you need to enter are as follows:

Name

Name of the REST web service reference

URL

The URL end point of the RESTful web service. If we didn't give you the URL, you could look it up yourself on Yahoo by searching for "REST web services."

https://developer.yahoo.com/maps/rest/V1/

The HTTP Method setting of "Get" denotes a read operation, which is what we want and this web service does not require username/password authentication, so leave that set at "No." We don't need to add REST HTTP Headers, so leave that blank as well.

REST web service wizard

Figure 13.24. REST web service wizard

We now need to identify the input parameters to the Yahoo web service. Figure 13-25 shows that we need to supply the application ID along with a location like a street address. Both inputs will string types.

Note

Pay close attention to the case of input parameters because case matters to the Yahoo web service. These parameters will be included in the URL so if you get the case wrong, the web service will not return the expected results and it can be very difficult to figure out why.

RESTful web service input parameters

Figure 13.25. RESTful web service input parameters

The final step in the RESTful web service reference creation is shown in Figure 13-26. Here you identify where the results of the web service call are found and the type of the parameter that contains the results. The Yahoo page where we went to start the developer registration (https://developer.yahoo.com/maps/rest/V1/) tells you what the inputs and outputs look like and even shows some example code. The parameter name that is set to "URL" is just a name, but Yahoo tells you that the return value from the map API web service is a URL pointing to the image of the map you requested. The path setting of "/text()" will be explained shortly.

Return value setup for RESTful web service

Figure 13.26. Return value setup for RESTful web service

After you click the "Create" button, a new wizard will launch, which allows you to create a form on the web service reference. Choose the "Create Form and Report on Web Service" radio button to continue. On the first step of the Form and Report creation wizard, choose the web service reference we just created (Yahoo Map REST), and the corresponding "Operation," which is populated based on the construction of the web service. There is only one operation (doREST), so select that value and click Next. The only two values you need to change on this page are the Form and Report region titles, as shown in Figure 13-27.

Form and Report settings for RESTful web service

Figure 13.27. Form and Report settings for RESTful web service

You then set the labels for the input parameters that will show up on the form. The only thing we need to do here is change the labels so they're a little more user friendly. Figure 13-28 shows the parameter settings. The original label for the appid field was "appid" and we changed it to "Application Id."

Form fields to call Yahoo web service

Figure 13.28. Form fields to call Yahoo web service

Now we have to define where to store the return value from the Yahoo web service. Thankfully, APEX does this for us by creating an APEX Collection and pulling the output parameter we set during the creation of the REST web service reference. All there is to do here is to tell APEX to display the output parameter (called URL) on the form, as shown in Figure 13-29. Of course you can change the name of the APEX collection, but we would only do this to adhere to some pre-defined standard.

Set the web service output parameters to display

Figure 13.29. Set the web service output parameters to display

At this point, the Form and Report are ready to go. You can click Finish now and run the page that is shown in Figure 13-30. Notice that we have entered the application ID obtained from Yahoo and an address to place on a map. What we got back was not an image, but a URL to the image we want, so there's one more little change to make so that we render the image at that URL instead of displaying the text.

Form to call the Yahoo Map web service

Figure 13.30. Form to call the Yahoo Map web service

Edit the page containing the Yahoo map and click on the "Report" link of the Map region. This will take you to the Report Attributes page, as shown in Figure 13-31. We need to edit the URL column of the report, so click on the edit link next to "URL," which is the only column in the report.

Web service report attributes

Figure 13.31. Web service report attributes

We will now simply modify the HTML Expression for this report column. Currently, there is no HTML expression, so we will tell this report column to display an image using the URL returned from the Yahoo web service. This is done simply by using a substitution, <img src="#URL#"/>, as shown in Figure 13-32.

Changing the HTML expression for the web service report

Figure 13.32. Changing the HTML expression for the web service report

After applying the changes and running the page again, you should see the address you entered, as shown in Figure 13-33, identified by a red star on a graphical Yahoo map. You'll just have to trust us on the red star thing, or you can go to Yahoo and enter the same address to ensure you're getting exactly the same information directly from Yahoo maps as you are from your web service call.

Graphical map display as a result of a RESTful web service call

Figure 13.33. Graphical map display as a result of a RESTful web service call

Summary

Web services, in their many forms, have been around for more than ten years and they still haven't gained the widespread acceptance that many people thought they would. There are now several tools available that assist in implementing Service Oriented Architectures (SOA) or Enterprise Service Buses (ESB), but they all require heavy investments in capital as well as manpower.

Using what we have learned in this chapter, you can begin using web services in both a budget- and developer-friendly way. We described how to expose any Oracle stored procedure or function as a WSDL web service and how to use the Oracle database server itself in place of an application server. Both of these features greatly simplify entry into the realm of web services. Since APEX does not let you declaratively build either RESTful or WSDL web services, we did not delve into the details of building server components. If your organization is moving towards a SOA implementation, there will likely be a team dedicated to building web services that you now know how to consume with APEX.

As with plug-ins described in the previous chapter, we encourage you to look for web services, both internal as well as external, which can improve the usability of your applications while also injecting standardization into your development efforts.

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

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