Chapter 27 · Application Integration: Drivers, Pools, Session State, Transactions, and Resilience
JDBC, ODP.NET, Python/Node Drivers, Connection Descriptors, Services, and TLS
Connect Java, .NET, Python, and Node applications to FREEPDB1 with service-aware Oracle Net descriptors, distinguish current Thin/Thick modes, verify the server-side session, and design TLS without hard-coded credentials.
Learning outcomes
A ServiceHub Java API works on a developer laptop, but a Python worker gets ORA-12514, a .NET service lands on the wrong PDB, and a Node deployment accidentally commits a database password to source control. Oracle connectivity is a contract among the driver, Oracle Net naming, a database service, authentication, transport security, and the server-side PDB/session—not merely a host and port.
Pin and identify the exact JDBC/UCP, ODP.NET, python-oracledb, and node-oracledb versions used by the chapter.
Distinguish Easy Connect, connect descriptors, service names, PDBs, and SIDs, then verify the actual service/container from SQL.
Compare Java JDBC Thin, Python/Node Thin/Thick, and ODP.NET managed/core behavior without installing Oracle Client unnecessarily.
Design TCPS/TLS trust with wallets, PKCS12/JKS/system trust stores, and server-DN matching while keeping secrets outside source control.
Diagnose ORA-12514 from a nonexistent service and verify the repaired state from listener and V$SESSION evidence.
Mandatory database examples target Oracle AI Database Free 26ai, reviewed against RU 23.26.3, SQL Developer 26.2, SQLcl 26.2.1.222.1617, JDBC/UCP 23.26.3.0, ODP.NET 23.26.3, python-oracledb 4.0.2, node-oracledb 7.0.1, and Oracle Instant Client 23.26.3 where Thick mode is discussed. Free is limited to 2 foreground CPU cores, 2 GB database RAM, 12 GB user data, and one installation per logical environment, with no Release Update patching or Oracle Support SRs. The course baseline is CDB/instance FREE, application PDB/service FREEPDB1 on port 1521, owner SERVICEHUB_OWNER, and runtime user SERVICEHUB_APP. JDBC Thin is the preferred Java path; JDBC OCI/Type 2 is deprecated in 26ai. python-oracledb and node-oracledb default to Thin mode and use Oracle Client libraries only if Thick mode is explicitly initialized. Application Continuity and Transaction Guard are not licensed in Free. On EE/EE-ES, Application Continuity requires Active Data Guard, RAC One Node, or RAC. DRCP and RESET_STATE are separate mechanisms. TCPS examples require a configured TLS listener/server certificate and trusted client configuration. No real password, wallet, private key, or provider secret is embedded, no mandatory lab changes COMPATIBLE, and no remote GitHub file is modified.
1. Pin the client you tested
Database RU and client-driver release are independent variables. Record both in incident and performance evidence. The chapter pins current stable releases rather than using an unbounded “latest” dependency.
| Stack | Pin | Connection architecture |
|---|---|---|
| Java | JDBC/UCP 23.26.3.0 | JDBC Thin preferred; no Oracle Client required |
| .NET | ODP.NET 23.26.3 | Managed/Core provider package |
| Python | python-oracledb 4.0.2 | Thin default; optional Thick |
| Node.js | node-oracledb 7.0.1 | Thin default; optional Thick |
python -m pip install "oracledb==4.0.2"npm install --save-exact oracledb@7.0.1dotnet add package Oracle.ManagedDataAccess.Core --version 23.26.3
<dependency> <groupId>com.oracle.database.jdbc</groupId> <artifactId>ojdbc17-production</artifactId> <version>23.26.3.0.0</version> <type>pom</type></dependency>
Use the JDK/provider combination certified for the chosen driver. Version-pinning is reproducibility, not a command to remain on an obsolete client forever.
2. Service name is the application routing identity
In this course, FREE is the instance/CDB baseline
and FREEPDB1 is the application PDB service.
Applications should target a service, not assume that a SID
names the business endpoint. Easy Connect encodes host, listener
port, and service:
sql servicehub_app@//localhost:1521/FREEPDB1
Enter the lab password interactively or use an approved credential/profile mechanism. Do not paste production passwords into command history, source, CI variables printed to logs, or connection URLs.
3. Verify where the session landed
SELECT SYS_CONTEXT('USERENV','DB_NAME') AS db_name, SYS_CONTEXT('USERENV','CON_NAME') AS con_name, SYS_CONTEXT('USERENV','SERVICE_NAME') AS service_name, SYS_CONTEXT('USERENV','INSTANCE_NAME') AS instance_name, SYS_CONTEXT('USERENV','SESSION_USER') AS session_userFROM dual;
Expected course state is CON_NAME=FREEPDB1 and
runtime identity SERVICEHUB_APP. A successful TCP socket proves
neither the correct PDB nor the correct service; this query
does.
4. Python Thin connection
import osimport oracledbwith oracledb.connect( user="servicehub_app", password=os.environ["SERVICEHUB_DB_PASSWORD"], dsn="localhost:1521/FREEPDB1") as conn: print("thin_mode =", conn.thin) with conn.cursor() as cur: cur.execute(""" select sys_context('USERENV','SERVICE_NAME'), sys_context('USERENV','CON_NAME') from dual """) print(cur.fetchone())
Thin mode speaks Oracle Net directly and needs no Instant
Client. Call oracledb.init_oracle_client() before
the first connection or pool only when Thick mode
capabilities/client integration are actually required; mode is
process-wide once initialized.
5. Node Thin connection
const oracledb = require("oracledb");async function main() { const conn = await oracledb.getConnection({ user: "servicehub_app", password: process.env.SERVICEHUB_DB_PASSWORD, connectString: "localhost:1521/FREEPDB1" }); console.log("thin =", conn.thin); const r = await conn.execute(` select sys_context('USERENV','SERVICE_NAME') service_name, sys_context('USERENV','CON_NAME') con_name from dual`); console.log(r.rows); await conn.close();}main().catch(console.error);
Node Thin mode similarly requires no Oracle Client. Thick mode
is enabled with oracledb.initOracleClient() before
the first connection/pool and changes the whole process.
6. Java JDBC Thin connection
import java.sql.*;String url = "jdbc:oracle:thin:@//localhost:1521/FREEPDB1";String user = "servicehub_app";String password = System.getenv("SERVICEHUB_DB_PASSWORD");try (Connection c = DriverManager.getConnection(url, user, password); PreparedStatement ps = c.prepareStatement( "select sys_context('USERENV','SERVICE_NAME'), " + " sys_context('USERENV','CON_NAME') from dual"); ResultSet rs = ps.executeQuery()) { while (rs.next()) { System.out.println(rs.getString(1) + " / " + rs.getString(2)); }}
Oracle deprecates JDBC OCI/Type 2 in 26ai. Use Thin unless an explicitly verified OCI-dependent requirement justifies carrying Oracle Client libraries.
7. ODP.NET connection
using Oracle.ManagedDataAccess.Client;var password = Environment.GetEnvironmentVariable("SERVICEHUB_DB_PASSWORD");var cs = "User Id=servicehub_app;" + $"Password={password};" + "Data Source=localhost:1521/FREEPDB1;";using var conn = new OracleConnection(cs);conn.Open();using var cmd = conn.CreateCommand();cmd.CommandText = "select sys_context('USERENV','SERVICE_NAME'), " + " sys_context('USERENV','CON_NAME') from dual";using var reader = cmd.ExecuteReader();while (reader.Read()) Console.WriteLine($"{reader.GetString(0)} / {reader.GetString(1)}");
8. A full descriptor makes behavior explicit
(DESCRIPTION= (CONNECT_TIMEOUT=5) (RETRY_COUNT=2) (ADDRESS=(PROTOCOL=TCP)(HOST=localhost)(PORT=1521)) (CONNECT_DATA=(SERVICE_NAME=FREEPDB1)))
The timeout/retry values are lab examples, not universal production settings. A real descriptor can carry multiple addresses, retry delay, transport timeout, HA settings, TLS security fields, and a service name. Tune connection establishment from the actual failover/SLO topology.
9. Deliberate failure: nonexistent service
sql servicehub_app@//localhost:1521/FREEPDB2-- Typical result:-- ORA-12514: listener does not currently know of service requested
ORA-12514 means the listener could not route the requested service; it is not evidence of a bad password.
lsnrctl statussql servicehub_app@//localhost:1521/FREEPDB1
lsnrctl status shows registered service handlers;
the earlier SYS_CONTEXT query then proves the actual
database/PDB session.
10. TLS/TCPS is a trust contract
Transport Layer Security changes Oracle Net transport from TCP
to TCPS. The server/listener needs a certificate and private
key, the client must trust the issuer/server identity, and
mutual TLS additionally requires a client identity. Merely
writing PROTOCOL=TCPS cannot create those
prerequisites.
(DESCRIPTION= (ADDRESS=(PROTOCOL=TCPS)(HOST=db.example.com)(PORT=2484)) (CONNECT_DATA=(SERVICE_NAME=servicehub.example.com)) (SECURITY=(SSL_SERVER_DN_MATCH=YES)))
JDBC Thin uses JSSE and documented trust-store/wallet formats. Python/Node Thin support TLS directly; Thick mode moves more Oracle Net behavior into Oracle Client. ODP.NET TLS/wallet support varies by provider. Keep wallet passwords/private keys out of source and use approved trust/secret stores.
11. 26ai TLS/client observations
Current JDBC adds certificate alias/thumbprint and TLS version controls; Oracle recommends negotiating the strongest supported TLS version unless policy requires a floor. SSLv3 is desupported. During incidents record listener certificate identity, trust-store source, runtime/JDK, driver mode, and client library version.
SELECT sid, serial#, username, service_name, program, module, machine, client_driver, client_version, statusFROM v$sessionWHERE username='SERVICEHUB_APP'ORDER BY logon_time DESC;
V$SESSION can prove service/client/session identity; it does not prove that the TLS certificate chain or hostname was correctly validated. For that, use client/listener/network trace and TLS evidence.
12. Production judgment
Prefer services over SID affinity, Thin clients when they meet requirements, pinned/tested driver versions, externalized secrets, bounded connect timeouts, and TCPS with server identity verification when transport policy requires it. Always verify the actual PDB/service after connection.
No mandatory lab needs a paid option, restart, or COMPATIBLE change. TCPS requires listener/wallet/certificate work. Thick Python/Node requires compatible Oracle Client libraries; JDBC OCI is deprecated. Lesson 2 starts reusing these connections safely under pool concurrency.
Check your understanding
- What does FREEPDB1 identify?
- Why is ORA-12514 not an invalid-password error?
- Which Java driver mode is preferred in 26ai?
- What must exist before TCPS works?
- Does V$SESSION prove TLS certificate validation?
Review the answers
The application PDB service used for routing.
The listener could not resolve the requested service before successful application authentication to it.
JDBC Thin.
A TLS-configured listener/server certificate and client trust; mutual TLS also needs client credentials.
No; it proves database session/client metadata, not transport trust validation.
Authoritative references
- JDBC/UCP Downloads — 23.26.3 driver/UCP release
- JDBC Client-Side Security — TLS/wallet/certificate behavior
- python-oracledb — Thin/Thick/current driver usage
- node-oracledb Connection Handling — Thin/Thick/Easy Connect/TLS
- ODP.NET New Features — current .NET provider release