Java Development with Autonomous Transaction Processing Dedicated (ATP-D)
The Oracle Autonomous Transaction Processing Dedicated (ATP-D) is a database Cloud service which allows implementing a private database Cloud service running on dedicated Exadata Infrastructure within the Oracle Public Cloud. The goal of this blog article is to help you, Java developer or architect, build and deploy fast, scalable, and reliable Java applications with ATP-D, using plain Java, Java Servlets, or Java Microservices with WebLogic, Helidon, WebSphere, Liberty, Tomcat, WildFly (JBoss), Spring, and so on.
I’ll walk you through: (i) the prerequisites and Java connectivity to ATP-D; (ii) zero downtime for Java applications with ATP-D; (iii) and finally, the performance and scalability of Java applications with ATP-D.
Although this blog uses Linux command line and scripts, an upcoming extension to the Oracle Cloud Infrastructure toolkit for Eclipse will make the experience more Java developer friendly.
Prerequisites and Java Connectivity to ATP-D
The following steps are required for using ATP-D with Java:
- Provision an ATP-D cloud service instance on the Oracle Cloud Infrastructure and populate your database; see videos here.
- Get the client credentials from the Cloud service console; you will be asked to furnish a password for securing the wallet and the trustStore; see details here (specifically step #2, under the prerequisites).
- The ojdbc.properties property file, part of the client credential package has been pre-configured, out of the box, to simplify the connectivity to ATP-D, using the Oracle Wallet.
For connecting using JKS, you need to edit the ojdbc.properties file as follows
- ATP-D furnishes five preconfigured services supporting TCPs and TCP protocols (TCPs recommended).
- Pick your database service name from the list above. These are similar to JNDI names and hide/virtualize the details of the database service; these details are in the tnsnames.ora file (shown hereafter), part of the client credentials.
- The virtualization allows the service to be moved from one instance to the other transparently. The name of your ATP-D service, is made of the service name you’ve picked (e.g., tpurgent), prefixed by your database name, “java” in my case, and postfixed by “tls”. For example: java_tpurgent_tls supports TCPs, while java_tpurgent, although a valid ATP-D instance name, supports only TCP, which is not recommended.
- Your responsibility is to edit that file and change some default values (e.g., RETRY_COUNT, RETRY_DELAY, CONNECT_TIMEOUT) to meet your specific requirements.
- Set your ATP-D service name either directly in the JDBC connect string or export it and retrieve it from an environment variable (my preference).
- For security reasons, you cannot directly connect to ATP-D from your Java apps running on-premises (for example, from your laptop); you need to provision a compute instance within the same Virtual Cloud Network (a.k.a. VCN), and perform your CI/CD work from it over your Java code, the clients credentials and the network configuration files and execute from that compute instance. You need a pair of (private, public) keys for accessing the compute; see the doc for more details.
ssh -i ~/ocikey firstname.lastname@example.org
- Get the latest JDK8 (JDK8u163+), JDK9, JDK10 or JDK11
- Get the latest JDBC and companion jars (DB 19c) from Maven Central, or the Oracle Maven repository or the JDBC download page: ojdbc8.jar or ojdbc10.jar (depending on your JDK), ucp.jar, oraclepki.jar, osdt_core.jar, osdt_cert.jar, ons.jar, simplefan.jar; xdb.jar + xmlparserv2.jar if you plan to use XML data type; and orai18n.jar if you need to deal with National Languages.
- Set the TNS_ADMIN environment variable to the location where you’ve extracted the client credentials, either in the JDBC URL (new with DB 18c), or as environment variable, or using the oracle.net.tns_admin Java system property; setting TNS_ADMIN this is required for the driver to locate the network configuration file tnsnames.ora, as well as the new ojdbc.properties file, and so on.
And here are the code fragment for getting a connection from your Java code; this fragment is using the Universal Connection Pool (UCP) datasource, not a JDBC datasource.
The JDBC datasource equivalent would be (no need for ucp.jar in the classpath)
javac -classpath ./lib/ojdbc10.jar:./lib/ucp.jar:./lib/ons.jar UCP.java
Running using Oracle Wallet
- the setting of oracle.ons.walletfile and oracle.ons.walletpassword as JDK system properties are global to all datasources/connections; could be replaced by the new per-connection properties oracle.jdbc.ons.walletfile and oracle.jdbc.ons.walletpassword
- the use of oraclepki.jar, osdt_core.jar and osdt_cert.jar, in the classpath in order to use the OraclePKI provider, instead of the SunJSSE provider which does not support all PKCS12 features.
Running using JKS
Notice the location of the trustStore.jks file as well as the trustStorePassword, which is the one you’ve entered when downloading the client credentials (above). The oraclepki.jar in this case, is used by the Oracle Notification System (ONS) (see later).
Zero Downtime for Java Applications using ATP-D
How to achieve continuous availability of your Java applications in the face of planned and/or unplanned database instance outages? With ATP-D, the infrastructure transparently handles most of the mechanisms that come into play to ensure zero downtime however, few steps are left under your responsibility, as Java developer/architect. This is the perfect place to stress the difference between your ATP-D service, iow your database, and an ATP-D instance, which is the RDBMS infrastructure running your service.
The following code fragment will print the instance name where your ATP-D service is running.
High Availability Mechanisms in ATP-D
The following mechanisms contribute, transparently, to zero downtime: Fast Application Notification events, Application Continuity and Transparent Application Continuity.
Fast Application Notification (FAN) Events
Traditionally, during database operations or attempts to connect to it, Java applications receive an exception at the expiration of the timeout; unfortunately, timeouts are not immediate and unpredictable. Fast Application Notification (FAN), on the other hand, furnishes immediate notification. The FAN events are triggered by the following database events:
With ATP-D, FAN events are automatically enabled and carried/delivered by the Oracle Notification System (ONS). Your responsibility, as Java developer/architect is to: (i) set ons.jar in the classpath for FAN subscription by the Java connection pool (UCP); or (ii) instead, set simplefan.jar in the classpath for FAN subscription by the JDBC driver, if not using UCP.
In ATP-D environment, the notification system (ONS) itself, uses the Oracle Wallet for its communication; your responsibility is to:
(i) specify the location of the wallet file and the wallet password either as system properties (-Doracle.ons.walletfile= … -Doracle.ons.walletpassword= …) or as per JDBC connection/datasource properties in your Java code (oracle.jdbc.ons.walletfile, oracle.jdbc.ons.walletpassword);
(ii) add oraclepki.jar to the classpath whether you are using JKS or Oracle Wallet for the Java connections (it is required by ONS).
Application Continuity (AC)
Application Continuity (AC) is a proven technology, introduced in RDBMS version 12.1, which straddles the RDBMS and its clients (drivers, connection pools). When enabled, AC consists in recording, in driver memory, all database calls made during an application unit of work (typically a transaction) and replaying these calls— upon the failure of an instance, host or network — against another instance of the same database, after hiding the exception. Upon replay, if the outcome is identical (i.e., result set checksum) then AC is successful and the control is given back to the application to continue, as if nothing has happened; if not, the exception is re-cast and visible the Java code.
The ATP-D infrastructure ensures the continuous availability of your database service however, as indicated, the Java developer needs to take few steps for transparently and continuously accessing the service during planned or un-planned outages.
AC is built on top of Transaction Guard, which guarantees that upon a failure of the COMMIT or ROLLBACK statement — if the status check of the in-flight transaction, returns “in-doubt”, the COMMIT or ROLLBACK will never complete, and therefore it is safe to replay the recorded calls.
With ATP-D, AC is enabled by default with all the pre-configured services. Your responsibility, as Java developer, is to use the Replay Datasource of the Oracle JDBC driver by setting the connection factory as follows
There are further considerations when AC is enabled:
- The explicit demarcation of units of work (a.k.a. database Requests) using conn.beginRequest() and conn.endRequest() calls, when not using Oracle UCP or Weblogic Active Gridlink
- You Java applications might have non-transactional database states such as NLS settings, optimizer preferences, event settings, PL/SQL global variables, temporary tables, advanced queues, LOBs, and result cache. Simple states are restored however, many others and the complex ones such as temporary tables or sys_context, will not be restored by AC; it is your responsibility as Java developer, to know your application and implement the “UCP Connection Labelling Callback” for restoring the states not covered by AC, during replay.
- If you usually set initial custom states upon checking a connection from the pool, the AC infrastructure will not reset these during replay; it is your responsibility to implement the JDBC Connection Initialization callback for that purpose.
- Database mutable functions such as SYSDATE, SYSTIMESTAMP, SYS_GUID and sequence.NEXTVAL return different values than their original calls, which invalidates the replay. You have the ability to prevent these mutable functions from returning a different value during the replay, by granting the KEEP privilege to your database user.
- Applications that perform calls to external system from within the database such as FTP callout (file transfer), sending emails, and so on, will incur side effects during the replay. You have the ability to explicitly disable replay by using the disableReplay call on the oracle.jdbc.replay.ReplayableConnection interface as follows:
- The legacy Oracle JDBC types implemented as concrete classes are supported by the AC infrastructure however, few types such as oracle.sql.OPAQUE, and oracle.sql.ANYDATA are not supported (i.e., replay will not work).
Transparent Application Continuity (TAC)
The Transparent Application Continuity (TAC), introduced in Oracle database release 18c and corresponding drivers and pools, is an enhancement of Application Continuity (AC).
With TAC, most of the AC setting left up to the developers, are taken care of transparently.
(i) TAC has a state tracking mechanisms capable of restoring most session states (NLS_*, CLIENT_INFO, MODULE, ACTION, CLIENT_ID, ECONTEXT_*), for complex session states such as temporary tables or sys_context, you would need to revert to AC and implement the “JDBC Connection Initialization Callback” or the “UCP Connection Labelling Callback”.
(ii) You don’t need to implement a callback for restoring initial session states; mutable database functions are “kept” (i.e., return the same value during replay).
(iii) You don’t need to explicitly demarcate the units of work (a.k.a. database Requests) when not using Oracle pools (UCP, Weblogic Active GridLink), these are implicitly identified.
(iv) You don’t need to explicitly disable side effects.
(v) You don’t need to use a connection pool i.e., just plain JDBC; you still need to use the Replay datasource, though.
TAC is enabled by default with the TPURGENT and TP services (e.g., java_tpurgent_tls).
Let’s now see how these mechanisms come into play to furnish zero-downtime for your Java applications, during planned or unplanned outages.
Sustaining Planned Database Downtime
The goal is to hide a planned downtime of the instance where your ATP-D service is running, from your Java application.
Upon the triggering of the scheduled planned maintenance operation (initiated by the Fleet Admin, sometime at user request), a FAN “planned-DOWN” event is issued and received by the connections pools and drivers.
The easiest and recommended approach is to use UCP with plain Java, or Weblogic or third-party Java containers; it stops dispensing connections to that ATP-D instance then, re-routes subsequent requests to another host or database container where the same/identical database service has been re-opened by the infrastructure, transparently to your Java application.
A default drain_timeout of about 5 min, with TP and TPURGENT services (up to 1 hour with HIGH, MEDIUM, and LOW services) allows in-flight database operations to complete on the instance targeted for maintenance. Long running operations or in-flight units of work that cannot complete, will be terminated upon the expiration of the timeout and replayed by AC/TAC.
If you are not using the UCP but just plain JDBC, ATP-D marks connections/sessions for draining; the JDBC driver closes the connections in use, when one of the “Safe-draining APIs” described hereafter is invoked, so as to allow those connections to be safely removed.
Java containers and frameworks including Tomcat, Weblogic, WebSphere, Liberty, Wildfly/JBoss, SpringBoot, Helidon may have specific connection validation options, such as: PreTest Connection, TestConnectionOnReserve, TestOnBorrow, check-valid-connection-sql — to be specified in their datasource configuration.
The reasoning is the following: calling one of these APIs — which is your responsibility as Java developer — indicates to the driver that the Java application has made provision to do something in case the result of the invocation is False (i.e., complete the unit of work, close the connection object, etc); therefore it is safe to terminate that connection.
During the transparent transition of your database from one instance to the other (on average the same period of time as the drain timeout), new connection requests might not succeed immediately, it is your responsibility to adjust the RETRY_COUNT, RETRY_DELAY, and CONNECT_TIMEOUT of the entry of your ATP-D service, in the tnsnames.ora file, as already discussed under “Prerequisites and Java Connectivity to ATP-D”.
Sustaining Unplanned Database Outages
The goal is to hide an unplanned outage of your ATP-D instance from your Java application.
Upon the failure of your ATP-D instance, a FAN “Down” event is issued that the infrastructure and an identical database is provisioned on another host or container database.
TAC or AC kicks in (i.e., takes control) to:
- Hide the SQL exception from the application (assuming this is a recoverable exception; see the JDBC doc for more details).
- Cleans up the pool by removing orphan connections attached to the failed instance.
- Creates temporary connections to the new instance (identical database); then restores the session states preserved by TAC/AC or user-callback(s). It also re-cast the values of mutable functions (explicit KEEP privilege with AC or transparently with TAC.
- Invokes Transaction Guard (TG) under the covers, to check whether an in-flight work has committed (or rolled back) or not. If TG returns “in-doubt” then it replays the recordings of in-flight units of work.
- Upon replay, if the outcome is identical to the original call(s) (i.e., checksums of result sets), then TAC/AC is successful and the control is given back to the application to continue; if not, the exception is re-cast and visible the user Java code .
More on Zero Downtime
TAC/AC works for most Java applications however, there could be situations where TAC/AC will not be able to replay successfully. We recommend to run the ORAchk utility, refer to My Oracle Support note 1268927.2.
There are more to TAC beyond this blog post; see the “MAA for Applications with the Oracle Database” white paper, the Application Continuity for Java chapter in the Oracle JDBC doc for more details.
Performance and Scalability of Java Applications with ATP-D
Getting the best performance and scalability for your Web applications using ATP-D includes: speeding up database connectivity, speeding up SQL statements processing, optimizing network traffic, in-place processing, and scaling out Java workloads.
I’ve discussed these and the related JDBC, UCP or OJVM features, at length, in my previous blog post.
Thanks for reading.