Configuring custom error pages with Oracle REST Data Services

If you need to configure a custom error page instead of the error page generated by Oracle REST Data Services (ORDS), then do the following:

  • Edit the defaults.xml file in the ORDS configuration folder
  • Add the following setting to defaults.xml:

    <entry key="error.externalPath">/path/to/error/pages/folder/</entry>
      
  • /path/to/error/pages/folder is the fully qualified path to a folder which contains files named with the following pattern {status}.html, where {status} is the HTTP status code that you wish to define a custom error page for.
  • For example if you wish to define a custom error page for the HTTP 404 – Not Found status and store it in a folder named /usr/local/share/ords/error-pages/ then create a file named 404.html in /usr/local/share/ords/error-pages/ and configure error.externalPath to point at /usr/local/share/ords/errro-pages/.
Advertisements

Understanding the Oracle REST Data Services Configuration Folder

Oracle REST Data Services (ORDS) needs a location to store it’s configuration files. The location is configured using the config.dir setting. You can view and set this setting using the configdir command.

Set config.dir setting

$ java -jar ords.war configdir /tmp/wls/conf
Feb 27, 2014 2:58:47 PM oracle.dbtools.cmdline.ModifyConfigDir execute
INFO: Set config.dir to /tmp/wls/conf in: /Users/cdivilly/ords.war

View config.dir setting

$ java -jar ords.war configdir
Feb 27, 2014 3:00:16 PM oracle.dbtools.cmdline.ModifyConfigDir execute
INFO: The config.dir value is /tmp/wls/conf

The important thing to be aware of is that the configuration data is not stored directly in the location pointed to by config.dir. Instead the data is located in a sub-folder named after the context-path (aka context-root) that ords.war is deployed at.

A second point to be aware of is that when configuring ORDS, the context-path that the application will be deloyed at is not known, so it is inferred from the filename of ords.war.

Deploying to /apex

If you need to deploy ORDS to a context-path of: /apex, then make sure to do the following:

  1. Rename ords.war to apex.war
  2. Configure ORDS by doing:
    java -jar apex.war
  3. Deploy apex.war to your application server

If you follow these steps in the order laid out above, you will not encounter any issues.

Help! I forgot to rename ords.war before configuring and deploying it

If you did not rename ords.war before doing configuration and deployment, then you are likely to see an error page like the following:

ORDS Not Configured

ORDS Not Configured

Note the highlighted text in the bottom left. This reveals the problem, ORDS is expecting to find the configuration files in /tmp/wls/conf/apex (because the context-path is /apex), but does not find anything in this folder, because the data is actually in /tmp/wls/conf/ords.

In this case, to address the problem rename or copy /tmp/wls/conf/ords to /tmp/wls/conf/apex, and restart ORDS.

Listener 2.x Static Resources and i.war

Oracle Application Express (APEX) relies on a set of static resources to function properly. These static resources contain the JavaScript, CSS, and images that the APEX user interface needs to render and function correctly. The static resources are located in the /images folder in the APEX distribution. Typically the resources are made available at the /i/ path on an APEX web server.

In the Oracle Application Express Listener (Listener) 1.x.x series the process for deploying the /i/ bundle was to manually zip the contents of /images into an archive named i.war and then to deploy that archive on the same application server as Listener.

This meant that every time the static resources were modified (for example to add custom stylesheets or images), the archive needed to be recreated and then redeployed on the application server.

In the Listener 2.x.x series the process was improved. Rather than creating the archive manually the static sub-command of apex.war is used to generate i.war as documented here, and reproduced below:

Use the static command to create a web archive file named i.war:

java -jar apex.war static <apex directory>/images

Where:

<apex directory> is the directory location of Oracle Application Express.

The created images WAR does not contain the static resources, instead it references the location where the static resources are stored. Therefore the static resources must be available at the specified path on the server where the WAR is deployed.

Note the emphasis in the last paragraph above. In contrast to Listener 1.x.x, in 2.x.x the static resources are not included in the archive. Instead functionality in Oracle WebLogic and Oracle GlassFish is leveraged to create an i.war that references the path where the static resource are located. This means that the static resources can be updated without having to recreate and redeploy i.war.

Thus when i.war is deployed on WebLogic or GlassFish, and a request for a resource is made within the /i/ path then the application server looks for the corresponding resource within the <apex directory>/images folder specified above. It looks for the path in the file system of the server where i.war is deployed. Therefore it is imperative that the APEX static resources are copied to the application server at the exact path specified when using the static command.

For example if i.war is created using the following command:

java -jar apex.war static /usr/local/apex/4.2.2/apex/images

then the path /usr/local/apex/4.2.2/apex/images must exist on the server where i.war is deployed and it must contain all the static resources for the version of APEX installed in the database. It is not sufficient that the files exist on a local development box where the i.war was created, they must be copied to the application server machine’s file system as well.

Deploying static resources at custom path

Occasionally you may need to deploy the APEX static resources at a path other than the default of /i/. To do this use the --context-path argument of the static command, for example to deploy static resources at /apex-images you would do the following:

java -jar apex.war static --context-path /apex-images /usr/local/apex/4.2.2/apex/images

which will produce output similar to the following:

WAR Generation complete
 WAR location     : /home/cdivilly/apex-images.war
 Context path     : /apex-images
 Static resources : /usr/local/apex/4.2.2/apex/images

Note that this time the archive is named apex-images.war. Note however it is not the name of the archive that determines it’s context-path, rather it is a setting in the deployment descriptor in the archive that determines this. In this case the value of that setting is /apex-images. You could rename the archive to abc.war and it would still be delpoyed at /apex-images. A previous post provides more detail on these deployment descriptors.

See Also

  • To learn more detail on the WebLogic and GlassFish functionality that enables i.war to refer to resources located in the file system, see this post.
  • If you are having problems with APEX static resources not being found and APEX pages not displaying properly, see this post

Configuring Application Express Static Resources with Listener 2.0

A problem sometimes encountered when using Oracle Application Express Listener, is getting a blank page displayed when attempting to access an Oracle Application Express (APEX) page. For example getting a blank page when trying to display http://server:port/apex/. The cause of this problem is not having the APEX static resources configured properly. This leads to the JavaScript and CSS resources required by APEX not being found, and the APEX page failing to render correctly.

Possible Causes

Any of the following can cause this issue to occur:

  1. Forgetting to deploy i.war on WebLogic/GlassFish
  2. Specifying an incorrect path when using the java -jar apex.war static command to generate i.war
  3. Configuring APEX to use a non default context path for static resources (/i) and not specifying the same context path (via the --context-path option) when using java -jar apex.war static.
  4. Moving, renaming or deleting the folder pointed to by i.war after deploying i.war
  5. When running in Standalone Mode, entering an incorrect path (or skipping specifying a path) when prompted, on the first run of Standalone Mode
  6. When running in Standalone Mode, entering an incorrect path via the --static-images option
  7. And last, the one I most often forget myself, upgrading to a new version of APEX and forgetting to reconfigure and redeploy i.war to point to the static resources for the new APEX version, or in Standalone Mode forgetting to update the location by using the --apex-images option.

Confirming the problem

Assume your APEX deployment is located at http://example.com/apex/ and your static resources have been deployed at http://example.com/i/, then try accessing the following url:

http://example.com/i/apex_version.txt

If you get a 404 Not Found error then you need to double check points 1-6 in the list above, i.war is not deployed or is not pointing at a folder containing APEX static resources.

Otherwise a plain text file will be displayed with contents like the following:

Application Express Version:  4.2.1

Pay close attention to the version number displayed, it must match the version of APEX deployed on the database. If they differ then check point 7 on the list above, the Listener is not configured to use the correct version of APEX static resources to match the APEX version in the database.

Curing the problem

Consult the Oracle Application Express Listener for detailed documentation on how to create and deploy i.war. See instructions for WebLogic here, and GlassFish here.

You can get detailed help on the static listener command by typing the following at a command prompt:

java -jar apex.war help static

Listener 2.0 picks up changes to APEX static resources immediately

For Listener 1.1.x the deployment process for i.war required zipping all the APEX static resources into i.war and then deploying the resultant i.war.

The problem with this approach is that if the contents of the APEX static resources are updated (for example to add some custom style sheets), then i.war needs to be recreated and redeployed.

In 2.0 we leverage capabilities in WebLogic and GlassFish (described in more detail in a previous post) to create an i.war which does not actually contain the static resources, but instead points to the folder containing the static resources.

The advantage of this approach is that the static resources can be updated and the updates are immediately picked up by the server without requiring any restarting or redeploying of i.war

Oracle Application Express Listener 2.0 Released

Oracle Application Express Listener version 2.0 is now available for download.

This release includes many new features including:

  • Support for multi tenant/multiple database connections

    In earlier releases, you could only configure one database connection per listener instance. With Release 2.0, you can configure multiple database connections. See “Configuring Multiple Databases” in the Oracle Application Express Listener Installation and Configuration Guide.

  • Use Oracle SQL Developer to administer Oracle Application Express Listener

    Oracle SQL Developer 3.2.2 is able to remotely administer Oracle Application Express Listener instances. Access the Administration interface by selecting View|APEX Listener from the SQL Developer main menu. See “Application Express Listener Administration” in the Oracle SQL Developer User Guide.

  • Use command line to configure Oracle Application Express Listener

    You can also configure Application Express Listener using the command line. See “About the Command-Line Interface” in the Oracle Application Express Listener Installation and Configuration Guide.

  • Resource Templates are now known as RESTful Services.

    The Resource Templates functionality has been enhanced and integrated with Oracle Application Express 4.2. Now known as RESTful Services, services are now defined using Oracle Application Express. See “Using RESTful Services” in the Oracle Application Express SQL Workshop Guide.

  • OAuth2 support for RESTful Services

    Oracle Application Express Listener now uses the recently finalized Open Authorization 2.0 (OAuth2) framework to secure access to resources generated using RESTful Services.

  • RESTful Services support Paging of results

    RESTful Services now support paging of results, enabling large result sets to be spread across many page resources instead of a single resource. The really nice thing about this feature is that the pagination can be done automatically simply by setting the pagination size to a non zero value on a Resource Handler. Alternatively if you need fine control over how pagination is done the Listener provides a number of implicit bind variables (:row_offset,:row_count,:page_offset,:page_size) that Resource Handlers can reference to customize how paging is done.

  • Cross Origin Resource Scripting (CORS) support

    RESTful Services support the Cross Origin Resource Sharing Specification. All public RESTful Services are automatically CORS enabled, this means any public RESTful Service can be accessed from any web origin via an XMLHttpRequest. For non public (protected) RESTful Services, Resource Handler definitions include a new Origins Allowed field that enables you to include a comma delimited list of other server names that are permitted to make cross origin requests to the RESTful Service.

  • RESTful Services Hyperlinks

    RESTful Services now support a mechanism for result sets to include hyperlinks to other resources.

Serving Static Content on WebLogic and GlassFish

Both Oracle WebLogic and Oracle GlassFish provide mechanisms to mix-in static content located outside a Web Application Archive (WAR). We can leverage these facilities to create a simple WAR that can be used on either WebLogic or GlassFish for serving static content.

This provides an easier to use approach for serving Oracle Application Express static resources when using Oracle Application Express Listener, compared to zipping all the Application Express resources into a large WAR. An added benefit of this approach is that changes within the static resources folder are picked up immediately, no need to restart or update the WAR.

Let’s get started, we’re going to create a small WAR that contains the necessary deployment descriptors. First create a folder to work in.

mkdir static
cd static
mkdir WEB-INF
cd WEB-INF

Now create the JEE WAR descriptor, named: web.xml with the following contents:

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE web-app PUBLIC
"-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN"
"http://java.sun.com/j2ee/dtds/web-app_2_3.dtd">
<web-app/>

Next create the WebLogic specific deployment descriptor, named: weblogic.xml with the following contents:

<weblogic-web-app xmlns="http://www.bea.com/ns/weblogic/weblogic-web-app">
 <!-- This element specifies the context path the static resources are served from -->
 <context-root>/i</context-root>
 <virtual-directory-mapping>
  <!-- This element specifies the location on disk where the static resources are located -->
  <local-path>/path/to/apex/images</local-path>
  <url-pattern>/*</url-pattern>
 </virtual-directory-mapping>
</weblogic-web-app>

Note the values of the context-root and local-path elements, adjust these values to match your requirements.

Next create the GlassFish specific deployment descriptor, named: sun-web.xml with the following contents:

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE sun-web-app PUBLIC "-//Sun Microsystems, Inc.//DTD GlassFish Application Server 3.0 Servlet 3.0//EN" "http://www.sun.com/software/appserver/dtds/sun-web-app_3_0-0.dtd">
<sun-web-app>
 <!-- This element specifies the context path the static resources are served from --> 
 <context-root>/i</context-root>
 <!-- This element specifies the location on disk where the static resources are located -->
 <property name="alternatedocroot_1" value="from=/* dir=/path/to/apex/images"/>
</sun-web-app>

Note the values of the context-root element and the dir field within the value attribute of the property element, adjust these values to match your requirements.

Next create the WAR from these files:

cd ..
jar cvf ../static.war .

Finally deploy the static.war file to your WebLogic or GlassFish server.

One point to note is when using the Administration UI in GlassFish to deploy the WAR, the context root field is auto-filled by the UI based on the name of the WAR. Clear the contents of this field to ensure the context-root value specified in the sun-web.xml is used.

Resource Templates, not just for APEX

Oracle APEX Listener‘s primary function is to serve as a Java friendly alternative to mod_plsql. The most well known application that uses mod_plsql being APEX. However the Listener is not restricted to providing HTTP access to APEX, it can provide HTTP access to any PL/SQL procedure that mod_plsql can.

Similarly the Resource Templates functionality we have introduced in the latest APEX Listener Early Access Release is not dependent on APEX. Resource Templates can be used to expose any data stored in the database via HTTP, regardless of whether that data is managed by an APEX application or not. To be clear you don’t need to use APEX to be able to use Resource Templates.

P.S. If you’re using the new Resource Templates functionality, I’d love to hear about it, let me know the good or bad here or in the forum, thanks!

REST and Oracle APEX Listener

Update: November 2011, This functionality is available in Oracle Application Express Listener 1.1 and later, note the syntax of bind variables has been changed to match that used in other Oracle products: {person} becomes :person. The examples below have been changed to reflect the updated syntax

Oracle Application Express Listener Early Adopter Release 1.1 introduces a feature called Resource Templates that enables quick and easy configuration of RESTful web services for exposing and manipulating data stored in an Oracle Database via HTTP.

Hello REST World

Resource Templates are a mechanism to bind a URI Template to an SQL Query or a PL/SQL Block. For example a Resource Template could bind the URI Template: hello?who={person} to the following SQL Query:

select 'Hello ' || :person || ' from Oracle Application Express Listener' greeting from dual

Note how the {person} parameter in the URI Template is bound to a similarly named variable (:person) in the SQL query. Suppose our Application Express Listener is deployed at: http://example.com/apex/ then a HTTP request like the following:

GET /apex/hello?who=World HTTP/1.1
Host: example.com

will generate a HTTP response like the following:

HTTP/1.1 200 OK
ETag: "vovmx3pCoUq/DcdTY/hXusiq1QU="
Content-Type: application/json

{
 "greeting": "Hello World from Oracle Application Express Listener"
}
  • When the path: hello?who=World is received by the Application Express Listener, it is matched against our Resource Template’s URI Template.
  • The concrete value World is used as the value for :person parameter
  • The results of the Resource Template’s SQL Query are transformed into a JSON document
  • The JSON document consists of a JSON object. Each column in the query result set is mapped to a property of the JSON object.

Entity Tags and Conditional Operations

Note the ETag header in the HTTP response of the previous example. An ETag is a version identifier for a resource, in other words whenever the content of a resource changes, the value of its ETag header also changes. Resource Templates can generate an ETag header as follows:

  • By generating a secure hash of the resource’s contents. This is the default mechanism, but requires buffering the content of the resource to generate the hash
  • Sometimes the resource or its constituent parts will already contain information to uniquely identify a version of a resource, so alternatively a SQL query may be defined that generates a unique version identifier. The result set of the SQL query is securely hashed and used as the ETag value. This option does not require buffering of the resource, but care needs to be taken to ensure the SQL query does guarantee a different result set for each resource version
  • No ETag. Naturally there is an option to suppress generation of an ETag header

Resource Templates have an automatic capability for handling HTTP Conditional Operations where a If-None-Match or If-Match header is included with a request. To follow on from the example in the previous section a HTTP request like the following:

GET /apex/hello?who=World HTTP/1.1
Host: example.com
If-None-Match: "vovmx3pCoUq/DcdTY/hXusiq1QU="

will generate a HTTP response like the following:

HTTP/1.1 304 Not Modified
  • Again when the path: hello?who=World is received by the Application Express Listener, it is matched against our Resource Template’s URI Template.
  • The results of the Resource Template’s SQL Query are transformed into a JSON document
  • A secure hash of the JSON document is generated and is compared to the value of the If-None-Match header
  • Since the values are identical the Application Express Listener generates a 304 Not Modified response and does not include the resource’s content in the response
  • So in the case where a resource representation has not changed since the last time a client retrieved it, the overhead of transmitting the resource’s contents from server to client is avoided.

Media Resources

Resource Templates can be used to generate any type of resource not just the default of JSON documents. Resource Templates support a special type of SQL query called a Media Resource Query. Media Resource Queries consist of an SQL Query that generate a single result row with two columns in the row. The first column denotes the resource’s MIME type, the second column contains the resource’s content. For example if we have a Resource Template with a URI Template of : customers/locations/{state} bound to the following query:

select 'application/vnd.google-earth.kml+xml', xmlquery('
<k:kml xmlns:k="http://www.opengis.net/kml/2.2">
 <k:Folder>
  <k:name>{$state}</k:name>
{ for $c in ora:view("oe","customers")/ROW
let $loc := $c/CUST_GEO_LOCATION/SDO_POINT
where $c/CUST_ADDRESS/STATE_PROVINCE = $state
return
   <k:Placemark>
    <k:name>{concat($c/CUST_FIRST_NAME," ",$c/CUST_LAST_NAME)}</k:name>
     <k:Point>
      <k:coordinates>{$loc/X/text()},{$loc/Y/text()},0</k:coordinates>
     </k:Point>
    </k:Placemark>
}
</k:Folder>
</k:kml>' passing upper(:state) as "state" returning content) from dual

Then a HTTP request like:

GET /apex/customers/locations/ny HTTP/1.1
Host: example.com

will generate a HTTP response like:

HTTP/1.1 200 OK
ETag: "P4eISUyr2BZwtN1VnQHYyV556wU="
Content-Type: application/vnd.google-earth.kml+xml

<kml xmlns="http://www.opengis.net/kml/2.2">
 <Folder>
  <name>NY</name>
  <Placemark>
   <name>Blake Seignier</name>
   <Point>
    <coordinates>-76.14607,43.106533,0</coordinates>
   </Point>
  </Placemark>
  ...
 </Folder>
</kml>
  • In this example we leverage the powerful XMLQuery SQL function to generate a standards compliant KML file, thus quickly making our customer data available to third party GIS applications

And There’s More…

The above gives a brief flavour of what Resource Templates can accomplish, but there’s lots more functionality, here’s a few highlights:

  • HTTP Headers can be bound to Queries/PLSQL blocks in a similar manner to URI Template parameters, allowing responses to vary depending on HTTP headers received (e.g. localizing the response based on the Accept-Language header
  • Similar support for HTML Forms enables form fields to be bound to Query/PLSQL parameters, making processing of HTML forms straightforward, including forms containing file upload fields
  • Extraction of HTML5 Microdata from HTML resources to enable production of an alternate JSON representation of the microdata

Try it out, Learn More

You can download the Early Adopter Release here. The Developer Guide provides all the information needed to get started with Resource Templates.

The latest version of Oracle Application Express Listener can be downloaded here. The Developer Guide provides all the information needed to get started with Resource Templates.

Your Feedback

This is an Early Adopter release, it is not a finished product, As ever we encourage you to try out Oracle Application Express Listener and tell us what you think in the Oracle Application Express Listener forum. We look forward to your feedback.