Deploying Application Express with Delphix

Share Button

Seamless cloning of an application stack is an outstanding goal. Seamless cloning of an application stack including the full production database, application server, and webserver in a few minutes with next to zero disk space used or configuration required is the best goal since Alexander Graham Bell decided he wanted a better way tell Mr. Watson to “come here.”

So in the spirit of discovery, I’ve installed Oracle REST Data Services (ORDS) 2.0 and Oracle Application Express (APEX) 4.2 to a source Oracle database environment in my home Delphix setup. I’m going to:

  1. Sync the ORDS binaries with Delphix as a file source
  2. Sync the APEX binaries with Delphix as a file source
  3. Sync the ORCL database with Delphix as a database source
  4. Provision a clone of the ORCL database to a target linux system as DBDEV
  5. Provision a clone of the ORDS and APEX binaries to the target system

Some of you may be scratching your head right now thinking “What is Delphix?” I’ve written a few words on it in the past, and Kyle Hailey has quite a bit of information about it along with other links such as Jonathan Lewis explaining Delphix at OOW14.

If you’re into the whole brevity thing, here’s a short summation: Delphix is a technology you can sync nearly any kind of source data into and provision on demand from any point in time to any target, near instantly and at the click of a button, all without incurring additional disk space. What that means for your business is incredibly efficient development, faster time to market, and improved application quality. And if you want to see this in action, you can try it for yourself with Delphix Developer Edition.

Let’s use Delphix to deploy APEX to a target system.

Step 1. A look at the source

On the source environment (linuxsource, 172.16.180.11) I have an 11.2.0.1 database called “orcl”.

ORCL Source Database

In the /u01/app/oracle/product directory are ./apex and ./ords, holding the APEX and ORDS installations respectively.

Source Products Directory

When ORDS is started, I am able to see the APEX magic by browsing to http://172.16.180.11:8080/apex and logging in to my InvestPLUS workspace. Here’s the pre-packaged apps I have installed:

Source System APEX Apps

Sweet. Let’s check out what I have set up in Delphix.

Step 2. Check out the Delphix Sources

You can see that I have the ORCL database (named InvestPLUS DB Prod), Oracle REST Data Services, and APEX homes all loaded into Delphix here:

Delphix Sources

When I say they’re loaded into Delphix, I mean they’ve been synced. The ORCL database is synced over time with RMAN and archive logs and compressed about 3x on the base snapshot and 60x on the incremental changes. The /u01/app/oracle/product/apex and /u01/app/oracle/product/ords directories have also been synced with Delphix and are kept up to date over time. From these synced copies we can provision one or more Virtual Databases (VDBs) or Virtual Files (vFiles) to any target we choose.

Step 3. Deploy

Provisioning both VDBs and vFiles is very quick with Delphix and takes only a few button clicks. Just check out my awesomely dramatized video of the provisioning process. For this demo, first I provisioned a clone of the ORCL database to linuxtarget (172.16.180.12) with the name DBDEV.

Provisioning DBDEV to the target

Next I provisioned a copy of the ORDS home to the target at the same location as the source (/u01/app/oracle/product/ords) with the name ORDS Dev:

ORDS Dev on the target

And lastly I provisioned a copy of the APEX home to the target at the same location as the source (/u01/app/oracle/product/apex) with the name APEX Dev:

APEX Dev on target

In hindsight I probably could have just synced /u01/app/oracle/product and excluded the ./11.2.0 directory to get both ORDS and APEX, but hey, I like modularity. By having them separately synced, I can rewind or refresh either one on my target system.

Here’s the final provisioned set of clones on the target (you can see them under the “InvestPLUS Dev/QA” group on the left nav):

Provisioned Clones

Step 4. Check out the target system

Let’s see what all this looks like on the target system. Looking at the /u01/app/oracle/product directory on the target shows us the same directories as the source:

Target directories

I’ve also got the DBDEV database up on the target:

DBDEV on the target

To give you a glimpse of how Delphix provisioned the clone, check this out. Here’s a “df -h” on the linuxtarget environment:

Linux Target df command

What this is showing us is that the APEX Home, ORDS Home, and DBDEV clone are all being served over NFS from Delphix (172.16.180.3). This is how Delphix performs a clone operation, and why we call it virtual: data is synced and compressed from sources into Delphix, and when you provision a clone Delphix creates virtual sets of files that are presented over the wire to the target system. You can think of Delphix as a backup destination for source databases/filesystems, and as network attached storage for targets. The clever bit is that Delphix uses the same storage for both purposes, with no block copies at all unless data is changed on the target VDBs or vFiles. Cool, right? On a side note and for the curious, Delphix can use dNFS as well for your Oracle VDBs.

Step 5. Reconfigure ORDS

On the source environment, ORDS is configured to connect to the ORCL database. On the target we’re going to the DBDEV database. So the one quick change we’ll need to make is to change the SID in the /u01/app/oracle/product/ords/config/apex/defaults.xml file.

[delphix@linuxtarget ords]$ vi config/apex/defaults.xml
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!DOCTYPE properties SYSTEM "http://java.sun.com/dtd/properties.dtd">
<properties>
<comment>Saved on Wed Jan 14 08:38:04 EST 2015</comment>
<entry key="cache.caching">false</entry>
<entry key="cache.directory">/tmp/apex/cache</entry>
<entry key="cache.duration">days</entry>
<entry key="cache.expiration">7</entry>
<entry key="cache.maxEntries">500</entry>
<entry key="cache.monitorInterval">60</entry>
<entry key="cache.procedureNameList"/>
<entry key="cache.type">lru</entry>
<entry key="db.hostname">localhost</entry>
<entry key="db.password">@050784E0F3307C86A62BF4C58EE984BC49</entry>
<entry key="db.port">1521</entry>
<entry key="db.sid">DBDEV</entry>
<entry key="debug.debugger">false</entry>
<entry key="debug.printDebugToScreen">false</entry>
<entry key="error.keepErrorMessages">true</entry>
<entry key="error.maxEntries">50</entry>
<entry key="jdbc.DriverType">thin</entry>
<entry key="jdbc.InactivityTimeout">1800</entry>
<entry key="jdbc.InitialLimit">3</entry>
<entry key="jdbc.MaxConnectionReuseCount">1000</entry>
<entry key="jdbc.MaxLimit">10</entry>
<entry key="jdbc.MaxStatementsLimit">10</entry>
<entry key="jdbc.MinLimit">1</entry>
<entry key="jdbc.statementTimeout">900</entry>
<entry key="log.logging">false</entry>
<entry key="log.maxEntries">50</entry>
<entry key="misc.compress"/>
<entry key="misc.defaultPage">apex</entry>
<entry key="security.disableDefaultExclusionList">false</entry>
<entry key="security.maxEntries">2000</entry>
</properties>

Note the only line I had to change was this one: <entry key=”db.sid”>DBDEV</entry>

After the config change, I just had to start ORDS on the target:

[delphix@linuxtarget ords]$ java -jar apex.war
Jan 21, 2015 1:18:22 PM oracle.dbtools.standalone.Standalone execute
INFO: NOTE:

Standalone mode is designed for use in development and test environments. It is not supported for use in production environments.

Jan 21, 2015 1:18:22 PM oracle.dbtools.standalone.Standalone execute
INFO: Starting standalone Web Container in: /u01/app/oracle/product/ords/config/apex
Jan 21, 2015 1:18:22 PM oracle.dbtools.standalone.Deployer deploy
INFO: Will deploy application path = /u01/app/oracle/product/ords/config/apex/apex/WEB-INF/web.xml
Jan 21, 2015 1:18:22 PM oracle.dbtools.standalone.Deployer deploy
INFO: Deployed application path = /u01/app/oracle/product/ords/config/apex/apex/WEB-INF/web.xml
Jan 21, 2015 1:18:22 PM oracle.dbtools.common.config.file.ConfigurationFolder logConfigFolder
INFO: Using configuration folder: /u01/app/oracle/product/ords/config/apex
Configuration properties for: apex
cache.caching=false
cache.directory=/tmp/apex/cache
cache.duration=days
cache.expiration=7
cache.maxEntries=500
cache.monitorInterval=60
cache.procedureNameList=
cache.type=lru
db.hostname=localhost
db.password=******
db.port=1521
db.sid=DBDEV
debug.debugger=false
debug.printDebugToScreen=false
error.keepErrorMessages=true
error.maxEntries=50
jdbc.DriverType=thin
jdbc.InactivityTimeout=1800
jdbc.InitialLimit=3
jdbc.MaxConnectionReuseCount=1000
jdbc.MaxLimit=10
jdbc.MaxStatementsLimit=10
jdbc.MinLimit=1
jdbc.statementTimeout=900
log.logging=false
log.maxEntries=50
misc.compress=
misc.defaultPage=apex
security.disableDefaultExclusionList=false
security.maxEntries=2000
db.username=APEX_PUBLIC_USER
Jan 21, 2015 1:18:58 PM oracle.dbtools.common.config.db.ConfigurationValues intValue
WARNING: *** jdbc.MaxLimit in configuration apex is using a value of 10, this setting may not be sized adequately for a production environment ***
Jan 21, 2015 1:18:58 PM oracle.dbtools.common.config.db.ConfigurationValues intValue
WARNING: *** jdbc.InitialLimit in configuration apex is using a value of 3, this setting may not be sized adequately for a production environment ***
Using JDBC driver: Oracle JDBC driver version: 11.2.0.3.0
Jan 21, 2015 1:18:59 PM oracle.dbtools.rt.web.SCListener contextInitialized
INFO: Oracle REST Data Services initialized
Oracle REST Data Services version : 2.0.10.289.08.09
Oracle REST Data Services server info: Grizzly/1.9.49

Jan 21, 2015 1:18:59 PM com.sun.grizzly.Controller logVersion
INFO: GRIZZLY0001: Starting Grizzly Framework 1.9.49 - 1/21/15 1:18 PM
Jan 21, 2015 1:18:59 PM oracle.dbtools.standalone.Standalone execute
INFO: http://localhost:8080/apex/ started.

Step 6. Victory

With ORDS started, I’m now able to access APEX on my target and log in to see my applications.

APEX Login on TargetAPEX Apps on Target

Conclusion (or Step 7. Celebrate)

The cloned ORDS and APEX homes on the target and the DBDEV database are 100% full clones of their respective sources; block for block copies if you will. No matter how big the source data, these clones are done with a few clicks and takes only a few minutes, barely any disk space (in the megabytes, not gigabytes), and the clones can be refreshed from the source or rewound in minutes.

Delphix is capable of deploying not just database clones, but the whole app stack. Because Delphix stores incremental data changes (based on a retention period you decide), applications can be provisioned from any point in time or multiple points in time. And you can provision as many clones as you want to as many targets as you want, CPU and RAM on the targets permitting. All in all a fairly powerful capability and one I’ll be experimenting on quite a bit to see how the process and benefits can be improved. I’m thinking multi-VDB development deployments and a rewindable QA suite next!

Share Button

Leave a Reply

Your email address will not be published. Required fields are marked *

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