ORDS 22.x – How to setup and run multiple ORDS on single tomcat

Problem / Justification

The installation and configuration of ORDS has been changed quite a bit in version 22. Your hitherto existing installation and upgrade process needs to be carefully examined and probably reworked.

Here is an issue I encountered.

Imagine a database with two PDBs. One of them is the normal APEX database (test environment), the other is a regular pdb clone from a different environment, for example from development.

The goal is to run and access a different version of ORDS (and potentially APEX) in each PDB.
This post considers only ORDS, not APEX.

For simplicity we want to access the first environment using “ords” in the url and the second one using “clone”.

In older ORDS versions, it was possible to:

  1. configure ORDS in standalone mode,
  2. rename the war file and
  3. copy it into the webapps folder in tomcat.

And doing the same for the second database we could easily setup two independent versions of ords on a single tomcat.

This process does not function anymore, because the path to the configuration is not added to the ords.war file as it was previously.

Architecture overview

Solution

The following solution assumes that you already upgraded ords, including the ords meta data repository in both databases to the new version. If you don’t have that, look at the prerequisites section and the links near the end of this article.

To run two ords in standalone mode is fairly easy. Use a different port and a different --config parameter while starting ORDS (and possibly starting different versions of ORDS).

It is different for a single tomcat server whichs runs both ORDS using the same port but a different url base path.

We can configure a single ORDS to connect against multiple databases. However this means that the ords version is always the same. The goal is to run a different version of ORDS – so that ORDS matches the metadata repository in the PDB – and to use a slightly different base path. Both do not work when using the same ORDS with the same configuration.

Fortunatly we can recreate the pre 22.x behaviour by creating a new war file.

There is a documented way to create a war file similar to what we were used to. By using the ords war command we are able to inject the setting for the configuration path into a (new) war file. This setting eventually ends up in the web.xml of the tomcat deployment as we will show.

tomcat deployment

Setting the config.url parameter is possible during tomcat startup.

But doing it this way would not allow us to have two ords using a different configuration folder.

export JAVA_OPTS="-Dconfig.url=${ORDS_CONFIG}" 

The alternative is to set the config.url parameter inside the web.xml file in each webapp.

We could do that manually but fortunatly oracle gives us a command to create a war file. Using it we can take this war file, put it into the webapps folder on tomcat, and the necessary web.xml file will be created.

war file creation

Warning: the following command will immediately overwrite an existing war file on tomcat in the webapps folder. If you don’t want that then go to a different target folder.

configure ords for PDB1

export PATH=/opt/sven/tst/ords/ords-22.4.0/bin:$PATH
export JAVA_HOME=/usr/java/jdk-17.0.6
cd /opt/sven/tst/tomcat/latest/webapps

ORDS_CONFIG=/opt/sven/tst/ords/ordsconfig/ords
URL_BASE_PATH=ords

ords --config ${ORDS_CONFIG} war ${URL_BASE_PATH}.war

The variables are only created for easy usage and so that they can be easily adapted for the second database.

configure clone for PDB2
export PATH=/opt/sven/tst/ords/ords-22.4.0/bin:$PATH
export JAVA_HOME=/usr/java/jdk-17.0.6
cd /opt/sven/tst/tomcat/latest/webapps
ORDS_CONFIG=/opt/sven/tst/ords/ordsconfig/clone
URL_BASE_PATH=clone

ords --config ${ORDS_CONFIG} war ${URL_BASE_PATH}.war

result: check tomcat deployments

As soon as a new war file is put into the webapps folder, the subdirectories are created. This behaviour depends on the tomcat configuration, but it is the default. So no need to restart tomcat to see the unzipped war files. We can check the result in the webapps/ords/ and webapps/clone/ folders.

/opt/sven/tst/tomcat/latest/webapps/ords/WEB-INF/web.xml
<?xml version="1.0" encoding="UTF-8" standalone="no"?><web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" id="ORDS" metadata-complete="true" version="3.1" xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd">
        <display-name>Oracle REST Data Services</display-name>

        <context-param>
                <param-name>config.url</param-name>
                <param-value>/opt/sven/tst/ords/ordsconfig/ords</param-value>
        </context-param><context-param>
                <param-name>version</param-name>
                <param-value>22.4.0.r3401044</param-value>
        </context-param>

        <listener>
                <listener-class>oracle.dbtools.entrypoint.WebApplicationEntryPoint</listener-class>
        </listener>

        <servlet>
                <description>
                </description>
                <display-name>HttpEndPoint</display-name>
                <servlet-name>HttpEndPoint</servlet-name>
                <servlet-class>oracle.dbtools.entrypoint.WebApplicationRequestEntryPoint</servlet-class>
        </servlet>

        <servlet-mapping>
                <servlet-name>HttpEndPoint</servlet-name>
                <url-pattern>/*</url-pattern>
        </servlet-mapping>

        <servlet>
                <description>
                </description>
                <display-name>Forbidden</display-name>
                <servlet-name>Forbidden</servlet-name>
                <servlet-class>oracle.dbtools.entrypoint.Forbidden</servlet-class>
        </servlet>

        <servlet-mapping>

The relevant part in this and the following xml is the setting for the config.url context parameter.

/opt/sven/tst/tomcat/latest/webapps/clone/WEB-INF/web.xml
<?xml version="1.0" encoding="UTF-8" standalone="no"?><web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" id="ORDS" metadata-complete="true" version="3.1" xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd">
        <display-name>Oracle REST Data Services</display-name>

        <context-param>
                <param-name>config.url</param-name>
                <param-value>/opt/sven/tst/ords/ordsconfig/clone</param-value>
        </context-param><context-param>
                <param-name>version</param-name>
                <param-value>22.4.0.r3401044</param-value>
        </context-param>

        <listener>
                <listener-class>oracle.dbtools.entrypoint.WebApplicationEntryPoint</listener-class>
        </listener>

        <servlet>
                <description>
                </description>
                <display-name>HttpEndPoint</display-name>
                <servlet-name>HttpEndPoint</servlet-name>
                <servlet-class>oracle.dbtools.entrypoint.WebApplicationRequestEntryPoint</servlet-class>
        </servlet>

        <servlet-mapping>
                <servlet-name>HttpEndPoint</servlet-name>
                <url-pattern>/*</url-pattern>
        </servlet-mapping>

        <servlet>
                <description>
                </description>
                <display-name>Forbidden</display-name>
                <servlet-name>Forbidden</servlet-name>
                <servlet-class>oracle.dbtools.entrypoint.Forbidden</servlet-class>
        </servlet>

        <servlet-mapping>

Further considerations

prerequisites

The described solution assumes that you already upgraded ords, including the ords meta data repository in both databases to the new version.

The installation / migration requires to supply the old configuration folder, the new configuration folder and the database connect.

java version

ORDS 22 requires java 11 or 17. We decided to upgrade to java 17 (which is free again). I did not test if it is possible to run different java versions for each ORDS on the same TomCat. This might be a problem in the future, if the minimum java version for ORDS is increased again.

… The Oracle JDK is free to use for any Oracle product requiring Java, which includes ORDS.
That same Java can’t then be used for a non-Oracle product, that could trigger licensing issues.
Of course with Java 17, Oracle Java becomes free again. …

Jeff Smith
https://forums.oracle.com/ords/apexds/post/can-we-use-ords-free-of-cost-if-licensed-with-java-se-9569

automation

If you want to automate the installation and deployment process, below is a link to a blog post by Peter O’Brian that gives some more details about web deployments. It features a python script that is able to create a new .war file that includes the needed config path setting. It might be worth looking at, especially if you want to add more configurable options for automatic deployments.

alternative architecture

If you want to access multiple databases using the same ORDS then consider the following architecture. You will need a single configuration folder with multiple databases (pool configs) in it. I will not go into further details here, because that was not the goal of this post. But if you are interested in how to set it up, then add a comment and I might consider writing an extra post about it.

Useful links

6 thoughts on “ORDS 22.x – How to setup and run multiple ORDS on single tomcat

  1. HI Sven, Great document and very useful. We have a requirement using the alternative architecture appreciate if you could throw some light on this.

    Note! Does the document also valid for ORDS version 21.4?

    • Hi Mohan,

      thanks for your interest and sorry for the late answer. There were changes in ORDS version 22 especially regarding the config files. So in older versions a similar approach can be used. However it was easier to implement. Configure one ords in standalone mode, then deplay it on tomcat. Then configure the next standalone mode possibly using a different configuration folder, then deploy it on tomcat using a different name for the war file.

      Regards Sven

  2. In previous version of ORDS and Tomcat I have several Tomcat services on one machine each pointing to a different PDB.
    I am now trying to configure a similar set up and have one ORDS installed on the server and two Tomcat services set up. This appears to work, but when I connect to APEX administration I realise that I am connecting to the PDB in the default config database.
    I read the above article with interest thinking it might help me sort the problem out, but even though I changed the web.xml files to point to the correct config folder it does not pick it up.

    • Hi Liz,

      it is hard to judge what the exact problem is. It sound as if you have multiple PDBs each with a separate APEX environment. If your setup allows to connect to the APEX applications on each PDB, I do not understand why It should behave differently for the APEX adminstration. Unless you have additional url mappings in place.

      I think what you could do is to have two ORDS (at least two separate config paths) that are configured and deployed independently on each tomcat. It also depends on your ORDS version. The older versions included some part of the configuration inside the war file. A behavior that changed in version 22. In general the web.xml file is recreated when tomcat unpacks the war file. But that might not be what is causing your issue.

      Still I hope I could give you some ideas to explore.
      Regards Sven

  3. Hi Sven,

    Could you assist me in understanding whether I can modify the web.xml file or not? I’ve copied ‘ords.war’ to ‘test.war’ in the ‘webapps’ folder and added separate ‘config.url’ settings in the ‘WEB-INF/web.xml’ for both the ‘test’ and ‘ords’ contexts. Everything seems to be working fine. Is this ok method for adding a test ORDS, or should I be using the ‘ords –config ${ORDS_CONFIG} war’ command instead?

    Thanks!

    • Hi Alexander,

      thanks for the question. For testing purposes this is fine. However even if it works now, the next time you deploy a new ords.war (or test.war) file, tomcat will unzip it and possibly overwrite any settings that you made in the web.xml.

      So for a quick one time trial your method would be fine. For all other purposes I recommend to create a war file using the “war” command. So that the resulting .war file includes all the parameters and settings that you like to include, especially the setting for the config directory.

      Regards Sven

Leave a comment

This site uses Akismet to reduce spam. Learn how your comment data is processed.