Tag: ords jetty standalone

  • Adding X-Powered-By, Version, and Date Headers to ORDS Standalone

    Additional functionality with Jetty XML

    Here is an example of a Jetty Context XML file that adds additional headers to your ORDS HTTP responses.

    <?xml version="1.0"?>
    <!DOCTYPE Configure PUBLIC "-//Jetty//Configure//EN" "http://www.eclipse.org/jetty/configure_10_0.dtd">
    <Configure id="httpConfig" class="org.eclipse.jetty.server.HttpConfiguration">
        <Set name="sendXPoweredBy">
          <Property name= "jetty.send.xpoweredBy" default="true" />
        </Set>
        <Set name="sendServerVersion">
          <Property name="jetty.send.server.version" default="true" />
        </Set>
        <Set name="sendDateHeader">
          <Property name="jetty.send.date.header" default="true" />
        </Set>
    </Configure>

    Note

    This example is designed to show how you might structure a Jetty Content XML file to add additional functionality to ORDS’ embedded Jetty server. I’m using ORDS in standalone mode, so if you are using Apache Tomcat or Weblogic, this will not work.

    To test this out, first, create a Jetty XML file and populate the body with the contents in the above example. In this example, I’ve named the file jetty_headers.xml.

    Next, place the file in your /etc folder1. Once there, start ORDS back up (i.e., ords serve). I have installed and deployed ORDS locally (i.e., localhost), with my configuration folder named configuration. With the full path being:

    /Users/choina/ords/configuration/global/standalone/etc/jetty_headers.xml

    For reference, here is a view of how my ORDS configuration folder is structured:

    .
    ├── databases
    │   └── default
    │       ├── pool.xml
    │       └── wallet
    │           └── cwallet.sso
    └── global
        ├── settings.xml
        └── standalone
            ├── access_logs
            ├── etc
            │   └── jetty_headers.xml
            ├── self-signed.key
            └── self-signed.pem

    With everything in place, I can issue a request to one of my ORDS endpoints. In this case, I’ve created a simple GET Handler that queries the EMP table. The actual response isn’t the focus, but rather the response headers.

    I used cURL for this:

    curl http://localhost:8080/ords/hr/employees/

    In the response, I now see three new response headers displayed in a console output2:

    Server: Jetty(12.0.18)

    X-Powered-By: Jetty(12.0.18)

    Date: Sat, 24 2025 11:46:12 GMT

    Below is a console log printout showing the full details of the request and response (excluding the response body):

    * Preparing request to http://localhost:8080/ords/hr/employees/
    * Current time is 2025-05-24T11:46:12.857Z
    * Enable automatic URL encoding
    * Using default HTTP version
    * Enable timeout of 30000ms
    * Enable SSL validation
    * Connection 9 seems to be dead
    * Closing connection 9
    * Hostname in DNS cache was stale, zapped
    *   Trying 127.0.0.1:8080...
    * Connected to localhost (127.0.0.1) port 8080 (#10)
    
    > GET /ords/hr/employees/ HTTP/1.1
    > Host: localhost:8080
    > User-Agent: insomnia/11.1.0
    > Accept: */*
    
    * Mark bundle as not supporting multiuse
    
    < HTTP/1.1 200 OK
    < Server: Jetty(12.0.18)
    < X-Powered-By: Jetty(12.0.18)
    < Date: Sat, 24 May 2025 11:46:12 GMT
    < Content-Type: application/json
    < X-ORDS_DEBUG: true
    < ETag: "yGRRTja1S+tUjM5cGRS/a6WnUiHoqAczoKJ0J5Ty9sAGg1QeeXN3G+BtUukHu9DWgxrpOAOaapoBAd++rVdl6g=="
    < Transfer-Encoding: chunked
    
    
    * Received 8.2 KB chunk
    * Received 7 B chunk
    * Connection #10 to host localhost left intact

    Conclusion

    Arguably, the Server, X-Powered-By, and Date response headers could be considered functionally useless. However, for logging purposes, especially when it comes to huge applications or microservices more data can aid in quicker root-cause analyses.

    In any case, pretty neat how you can easily add enhanced functionality to ORDS standalone with a few lines of XML.

    References

    Footnotes

    1. You need to create this `/etc` folder manually. As of ORDS 25.1, this folder isn’t something that already exists. You might have a path similar to the one I shared above. ↩︎
    2. You may notice the Date header is returned in GMT/Zulu. This will always be the case with ORDS. ORDS will always return data and times in GMT/Zulu format. For reference, if you independently alter the `user.timezone` JVM Option, this would only change how ORDS interprets dates and times where no timezone is attached. The Oracle Database `Date` and `Timestamp` datatypes are two examples where the timezone is not indicated. ↩︎
  • ORDS Standalone: specifying a response header with jetty.xml

    NOTE: A Load Balancer or Reverse Proxy can achieve this same result. If your current ORDS deployment consists of either, you may prefer to add header "rules" there instead.
    Should you choose to operate ORDS in Standalone mode, you can rely on the Jetty server to provide this header rule. See the this section of my latest article for configuring the /etc folder.

    Start here

    Once you have created the /etc folder, save the following code block as a XML file using an easily recognizable file name.

    <?xml version="1.0"?>
    <!DOCTYPE Configure PUBLIC "-//Jetty//Configure//EN" "http://www.eclipse.org/jetty/configure.dtd">
    <Configure id="Server" class="org.eclipse.jetty.server.Server">
      <Call name="insertHandler">
      <Arg>
        <New class="org.eclipse.jetty.rewrite.handler.RewriteHandler">
          <Get id="Rewrite" name="ruleContainer" />
          <Call name="addRule">
            <Arg>
              <New id="header"  class="org.eclipse.jetty.rewrite.handler.HeaderPatternRule">
                <Set name="pattern">*</Set>
                <Set name="name">Strict-Transport-Security</Set>
                <Set name="value">max-age=31536000;includeSubDomains</Set>
              </New>
            </Arg>
          </Call>
        </New>
      </Arg>
    </Call>
    </Configure>

    In this example, we use jetty-response.xml as the file name. With this file included in the /etc directory, ORDS will “pick up” this configuration setting during runtime.1

    Some details of this file

    This jetty-response.xml file will enable ORDS Standalone to include the Strict-Transport-Security header name and its values max-age=3153600;includeSubDomains in each response to a request.2 In lay terms this XML file establishes a new Jetty response header, named Strict-Transport-Security, it applies to its responses for all requests (denoted by the *), and this header’s value is comprised of the following:

    • max-age=31536000;
    • includeSubDomains

    To illustrate this behavior, consider the following curl command and subsequent response. A request is sent to a resource (in this case /departments_json) and the subsequent ORDS response includes:

    1. a JSON payload
    2. the typical/standard headers, and
    3. additional headers indicated in the jetty-response.xml file

    And that’s it, you’ve yet again customized the Jetty server (that is responsible for ORDS Standalone)!

    That’s it for now

    Similarly to the Jetty Access Log example, these XML files can be a quick and easy way to introduce additional functionality into your ORDS Stand-Alone deployment. What else can you imagine? Take a look at the Jetty APIs for inspiration. Did you know you can extend ORDS with plugins, too?

    And of course, obligatory ORDS resources: Download ORDS | Oracle ORDS forum | ORDS Docs | ORDS playlist

    Follow

    And don’t forget to follow, like, subscribe, share, taunt, troll, or stalk me!

    Footnotes

    1. What the hell is runtime? Having no formal education in software engineering, my understanding is that runtime has to do with the execution of a program. Runtime relates to the initial and continued execution of the program. In the case of these XML files, the instructions therein are not formally part of the Jetty server but are included in the instructions when you issue the ords serve command. Doing so effectively starts up the Jetty web server. Jetty then recognizes there are files in the /etc folder and includes them when it enters into “runtime” or the “runtime environment.” This Wikipedia post is a great place to start. But I certainly wouldn’t use that as the “official” definition. This stackoverflow thread is extremely helpful as well. ↩︎
    2. Strict-Transport-Security (about this header) is a response header. This header is used to inform the browser that HTTPS should only be used to access ORDS resource/s. You’ve probably seen * used in the ORDS documentation. In this case, <Set name="pattern">*</Set> found in the XML file is used * as a wildcard (i.e. I interpret this as “apply this rule to everything and anything.”). The <Set name="value">max-age=31536000;includeSubDomains</Set> line includes the “directives”: max-age=3153600; and includeSubDomains. Examples of subdomains would be something like: en.wikipedia.org, where en (English language) is a subdomain of wikipedia.org; more details here. ↩︎

  • The one ORDS command you NEED to know!

    The one ORDS command you NEED to know!

    ords config list --include-defaults

    That’s it. Goodbye!

    I’m kidding, there’s more. But if you don’t feel like reading anymore, bookmark this post and return when you’re ready.

    Assuming you have ORDS installed, you too can execute the ords config list --include-defaults command to reveal almost all the configuration settings for your ORDS installation.

    Here is what my configuration looks like:

    Configuration settings: what am I seeing?

    This command is a quick way to see all the settings from your .XML configuration files (i.e., the settings.xml and pool.xml files), including other settings automatically configured for you when you first ran the ords interactive installer.

    Read on to explore further…

    Version, config folder location, and pool information

    I use this first section as an easy, convenient way to determine the ORDS version I’m running. Additionally, you can verify the location of your configuration folder (in case you forget). You can also verify the database pool (default is the default name for the pool unless you modify the name) you are using.

    Pool and global settings

    Not much here that you probably already don’t know. However, in the future I will look at the features associated with the database.api.management.services.disabled = false property (also, I think the way this is written is a referred to as a “logical negation”, and it hurts my brain to read).

    Read more about this service here. But in short (and once you’ve created the requisite user), you can explore various services such as:

    • DBCA Jobs, available methods: DELETE, GET and POST
    • DBCA Templates GET
    • Oracle Home Environment GET
    • PDB Lifecycle DELETE, GET, POST
    • Open Service Broker DELETE, GET, and PUT

    Debug and Error

    My settings are false (these are the default settings). But if I were to, for instance, set debug.printDebugToScreen = true, I would then be able to see any error messages in the browser.

    I can change the responseFormat to always display as JSON, HTML, or AUTO (i.e., Automatically determine the most appropriate format).

    Did you know you can create custom HTTP error pages in ORDS? These two error.properties appear to be associated in some way. So if you were two create custom error pages, you’d probably need to consider the format as well. Nonetheless, could you imagine the fun you could have coming up with something totally unique to your application?

    GraphQL and SQL Developer Web

    ORDS supports GraphQL now; did you know?! I just set up my local installation (it wasn’t too bad once I figured out how to properly set my Java to GraalVM 😑), so I can start learning GraphQL queries.

    Did you know ORDS ships with the GraphiQL IDE now? Learn how to set it up here.

    Cookies and ICAP

    I honestly wouldn’t have known ORDS could offload virus scanning to ICAP (Internet Content Adaptation Protocol) servers unless I looked at what was actually in the configuration settings. I’m not sure if I’ll configure this anytime soon, but maybe you will.

    Bookmark this link for future reference!

    Java Database Connectivity (JDBC)

    I am NOT going to spend much time here. I still need toggle these parameters and experiment more. However, I will point out that the default setting for maximum JDBC connections is 20 (jdbc.MaxLimit setting).

    jdbc.MaxLimit=20 is probably too low for a production environment. I’ve left it as-is because it’s just me, and I’m doing everything locally in my Podman container.

    Suppose you need to familiarize yourself with JDBC or Universal Connection Pools (UCPs)? In that case, we should both read the introduction sections of the following guides:

    MongoDB

    I have spent little time with MongoDB, but from what I understand, the Oracle Database API for MongoDB translates the MongoDB wire protocol into SQL statements executed by the Oracle.

    What I’m inferring from our docs is that once you’ve migrated your data from a MongoDB into a supported Oracle database, you (or your application) can keep talking “MongoDB speak,” and at least in this case, ORDS will be able to interpret this Mongospeak and query the database on your behalf 🤯!

    If this describes you or your use-case, you’re in luck; I found some excellent resources!

    Security

    You’ll notice, no red arrows here. I have yet to spend much time with this section. However, I want to draw your attention to the security.jwks.[etc...] and security.jwt.[etc...] properties.

    In ORDS 23.3, we introduced JSON Web Tokens (JWTs) support, so these properties very much concern that new functionality.

    Good resources to bookmark:

    Standalone (Jetty)

    The nice thing about ORDS is that you can use the embedded Jetty server as a local web server for testing. This section shows most of the essential settings for running Jetty in “Standalone mode.”

    I use the term “testing” because our docs state, “the default configuration of Jetty is optimized for the most common ORDS use cases.” I interpret this as, “This is designed to expose you to Jetty (and make it easy to get you up and running), but you’ll probably need to adjust this according to your own requirements.”

    The only things I want to point out here are the standalone.doc.root and standalone.static.context.path properties. These settings will look familiar if you’ve ever performed an APEX installation (available herefor free, BTW). 

    However, if you want to deploy custom HTML, CSS, and image files, you can configure this for ORDS. We have an overview in our docs here.

    Okay, that’s it for now. Thank you for choosing to waste your time with me.

    What’s the point of this post?

    There was no point to this post. I’m constantly wasting time researching technology and techniques I don’t need to know. However, in this case, I’ve hopefully:

    • left you with at least one helpful ORDS command-line command (ords config list --include-defaults), and
    • provided you with some helpful explanations and resources on what is contained in your ORDS installation (again, this list is NOT exhaustive)

    And if you found this post helpful, please share it!

    Follow

    And don’t forget to follow, like, subscribe, share, taunt, troll, or stalk me!