From cf08792944b75ce48e178a43ea0a1a88adbe3e38 Mon Sep 17 00:00:00 2001 From: Michael-A-McMahon Date: Tue, 30 Mar 2021 14:12:00 -0700 Subject: [PATCH 1/3] Add TNS descriptor sample code --- sample/build.gradle | 2 +- sample/example-config.properties | 2 +- .../oracle/r2dbc/samples/DatabaseConfig.java | 75 +++++++++++++++++++ .../oracle/r2dbc/samples/DescriptorURL.java | 74 ++++++++++++++++++ .../r2dbc/samples}/TcpsConnectDemo.java | 51 +++---------- 5 files changed, 161 insertions(+), 43 deletions(-) create mode 100644 sample/src/main/java/oracle/r2dbc/samples/DatabaseConfig.java create mode 100644 sample/src/main/java/oracle/r2dbc/samples/DescriptorURL.java rename sample/src/main/java/{ => oracle/r2dbc/samples}/TcpsConnectDemo.java (81%) diff --git a/sample/build.gradle b/sample/build.gradle index f1234d6..8a3e598 100644 --- a/sample/build.gradle +++ b/sample/build.gradle @@ -36,7 +36,7 @@ dependencies { sourceCompatibility = 1.11 targetCompatibility = 1.11 -mainClassName = 'TcpsConnectDemo' +mainClassName = 'oracle.r2dbc.samples.TcpsConnectDemo' run { // To enable network debugging: diff --git a/sample/example-config.properties b/sample/example-config.properties index edb2e36..e03375c 100644 --- a/sample/example-config.properties +++ b/sample/example-config.properties @@ -11,7 +11,7 @@ HOST=db.host.example.com PORT=1521 # Service name of a test database -DATABASE=db.service.name +SERVICE_NAME=db.service.name # User name authenticated by a test database USER=db_user diff --git a/sample/src/main/java/oracle/r2dbc/samples/DatabaseConfig.java b/sample/src/main/java/oracle/r2dbc/samples/DatabaseConfig.java new file mode 100644 index 0000000..58b1246 --- /dev/null +++ b/sample/src/main/java/oracle/r2dbc/samples/DatabaseConfig.java @@ -0,0 +1,75 @@ +/* + Copyright (c) 2020, 2021, Oracle and/or its affiliates. + + This software is dual-licensed to you under the Universal Permissive License + (UPL) 1.0 as shown at https://oss.oracle.com/licenses/upl or Apache License + 2.0 as shown at http://www.apache.org/licenses/LICENSE-2.0. You may choose + either license. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + https://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +package oracle.r2dbc.samples; + +import java.io.IOException; +import java.io.UncheckedIOException; +import java.nio.file.Files; +import java.nio.file.Path; +import java.util.Properties; + +/** + *

+ * Configuration for connecting code samples to an Oracle Database instance. + *

+ * The configuration is read from a properties file in the current directory + * by default, or from a file specified as + * -DCONFIG_FILE=/path/to/your/config.properties + *

+ */ +public class DatabaseConfig { + + /** Path to a configuration file: config.properties */ + private static final Path CONFIG_PATH = + Path.of(System.getProperty("CONFIG_FILE", "config.properties")); + + /** Configuration that is read from a file at {@link #CONFIG_PATH} */ + private static final Properties CONFIG; + static { + try (var fileStream = Files.newInputStream(CONFIG_PATH)) { + CONFIG = new Properties(); + CONFIG.load(fileStream); + } + catch (IOException readFailure) { + throw new UncheckedIOException(readFailure); + } + } + + /** Host name where an Oracle Database instance is running */ + static final String HOST = CONFIG.getProperty("HOST"); + + /** Port number where an Oracle Database instance is listening */ + static final int PORT = Integer.parseInt(CONFIG.getProperty("PORT")); + + /** Service name of an Oracle Database */ + static final String SERVICE_NAME = CONFIG.getProperty("SERVICE_NAME"); + + /** User name that connects to an Oracle Database */ + static final String USER = CONFIG.getProperty("USER"); + + /** Password of the user that connects to an Oracle Database */ + static final String PASSWORD = CONFIG.getProperty("PASSWORD"); + + /** The file system path of a wallet directory */ + static final String WALLET_LOCATION = + CONFIG.getProperty("WALLET_LOCATION"); +} diff --git a/sample/src/main/java/oracle/r2dbc/samples/DescriptorURL.java b/sample/src/main/java/oracle/r2dbc/samples/DescriptorURL.java new file mode 100644 index 0000000..23875be --- /dev/null +++ b/sample/src/main/java/oracle/r2dbc/samples/DescriptorURL.java @@ -0,0 +1,74 @@ +/* + Copyright (c) 2020, 2021, Oracle and/or its affiliates. + + This software is dual-licensed to you under the Universal Permissive License + (UPL) 1.0 as shown at https://oss.oracle.com/licenses/upl or Apache License + 2.0 as shown at http://www.apache.org/licenses/LICENSE-2.0. You may choose + either license. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + https://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +package oracle.r2dbc.samples; + +import io.r2dbc.spi.ConnectionFactories; +import io.r2dbc.spi.ConnectionFactoryOptions; +import reactor.core.publisher.Mono; + +import static oracle.r2dbc.samples.DatabaseConfig.HOST; +import static oracle.r2dbc.samples.DatabaseConfig.PORT; +import static oracle.r2dbc.samples.DatabaseConfig.SERVICE_NAME; +import static oracle.r2dbc.samples.DatabaseConfig.USER; +import static oracle.r2dbc.samples.DatabaseConfig.PASSWORD; + +/** + * This code example shows how to use TNS descriptor URLs with Oracle R2DBC. + * The TNS descriptor has the form: + *
+ *   (DESCRIPTION=...)
+ * 
+ * The full syntax of the TNS descriptor is described in the + * + * Oracle Net Services Administrator's Guide + * + */ +public class DescriptorURL { + + /** + * A TNS descriptor specifying the HOST, PORT, and SERVICE_NAME read from + * {@link DatabaseConfig}. + */ + private static final String DESCRIPTOR = "(DESCRIPTION=" + + "(ADDRESS=(HOST="+HOST+")(PORT="+PORT+")(PROTOCOL=tcp))" + + "(CONNECT_DATA=(SERVICE_NAME="+SERVICE_NAME+")))"; + + public static void main(String[] args) { + // A descriptor may appear in the host section of an R2DBC URL: + String r2dbcUrl = "r2dbc:oracle://"+DESCRIPTOR; + Mono.from(ConnectionFactories.get(ConnectionFactoryOptions.parse(r2dbcUrl) + .mutate() + .option(ConnectionFactoryOptions.USER, USER) + .option(ConnectionFactoryOptions.PASSWORD, PASSWORD) + .build()) + .create()) + .flatMapMany(connection -> + Mono.from(connection.createStatement( + "SELECT 'Connected with TNS descriptor' FROM sys.dual") + .execute()) + .flatMapMany(result -> + result.map((row, metadata) -> row.get(0, String.class))) + .concatWith(Mono.from(connection.close()).cast(String.class))) + .toStream() + .forEach(System.out::println); + } +} diff --git a/sample/src/main/java/TcpsConnectDemo.java b/sample/src/main/java/oracle/r2dbc/samples/TcpsConnectDemo.java similarity index 81% rename from sample/src/main/java/TcpsConnectDemo.java rename to sample/src/main/java/oracle/r2dbc/samples/TcpsConnectDemo.java index 1ae6645..ee280f9 100644 --- a/sample/src/main/java/TcpsConnectDemo.java +++ b/sample/src/main/java/oracle/r2dbc/samples/TcpsConnectDemo.java @@ -19,6 +19,8 @@ limitations under the License. */ +package oracle.r2dbc.samples; + import io.r2dbc.spi.ConnectionFactories; import io.r2dbc.spi.ConnectionFactory; import io.r2dbc.spi.ConnectionFactoryOptions; @@ -28,14 +30,15 @@ import reactor.core.publisher.Flux; import reactor.core.publisher.Mono; -import java.io.IOException; -import java.io.UncheckedIOException; import java.net.URI; import java.net.URISyntaxException; -import java.nio.file.Files; -import java.nio.file.Path; import java.time.Duration; -import java.util.Properties; + +import static oracle.r2dbc.samples.DatabaseConfig.HOST; +import static oracle.r2dbc.samples.DatabaseConfig.PASSWORD; +import static oracle.r2dbc.samples.DatabaseConfig.PORT; +import static oracle.r2dbc.samples.DatabaseConfig.USER; +import static oracle.r2dbc.samples.DatabaseConfig.WALLET_LOCATION; /** * Sample code that uses an Oracle Wallet to authenticate with an Oracle @@ -67,40 +70,6 @@ */ public class TcpsConnectDemo { - /** Path to a configuration file: config.properties */ - private static final Path CONFIG_PATH = - Path.of(System.getProperty("CONFIG_FILE", "config.properties")); - - /** Configuration that is read from a file at {@link #CONFIG_PATH} */ - private static final Properties CONFIG; - static { - try (var fileStream = Files.newInputStream(CONFIG_PATH)) { - CONFIG = new Properties(); - CONFIG.load(fileStream); - } - catch (IOException readFailure) { - throw new UncheckedIOException(readFailure); - } - } - - /** Host name where an Oracle Database instance is running */ - private static final String HOST = CONFIG.getProperty("HOST"); - - /** Port number where an Oracle Database instance is listening */ - private static final int PORT = Integer.parseInt(CONFIG.getProperty("PORT")); - - /** Service name of an Oracle Database */ - private static final String SERVICE_NAME = CONFIG.getProperty("SERVICE_NAME"); - - /** User name that connects to an Oracle Database */ - private static final String USER = CONFIG.getProperty("USER"); - - /** Password of the user that connects to an Oracle Database */ - private static final String PASSWORD = CONFIG.getProperty("PASSWORD"); - - /** The file system path of a wallet directory */ - private static final String WALLET_LOCATION = - CONFIG.getProperty("WALLET_LOCATION"); public static void main(String[] args) throws URISyntaxException { @@ -122,7 +91,7 @@ public static void main(String[] args) throws URISyntaxException { USER + ":" + PASSWORD, // userInfo HOST, // host PORT, // port - "/" + SERVICE_NAME, // path + "/" + DatabaseConfig.SERVICE_NAME, // path "oracle.net.wallet_location=" + WALLET_LOCATION + "&oracle.jdbc.fanEnabled=false", // query null) // fragment @@ -145,7 +114,7 @@ public static void main(String[] args) throws URISyntaxException { .option(ConnectionFactoryOptions.DRIVER, "oracle") .option(ConnectionFactoryOptions.HOST, HOST) .option(ConnectionFactoryOptions.PORT, PORT) - .option(ConnectionFactoryOptions.DATABASE, SERVICE_NAME) + .option(ConnectionFactoryOptions.DATABASE, DatabaseConfig.SERVICE_NAME) .option(ConnectionFactoryOptions.USER, USER) .option(ConnectionFactoryOptions.PASSWORD, PASSWORD) // To configure a TCPS/SSL/TLS enabled ConnectionFactory, set the SSL From b105fe63c9383427153a7992718d50924e4ca78e Mon Sep 17 00:00:00 2001 From: Michael-A-McMahon Date: Tue, 30 Mar 2021 14:13:32 -0700 Subject: [PATCH 2/3] Use static import of SERVICE_NAME --- .../src/main/java/oracle/r2dbc/samples/TcpsConnectDemo.java | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/sample/src/main/java/oracle/r2dbc/samples/TcpsConnectDemo.java b/sample/src/main/java/oracle/r2dbc/samples/TcpsConnectDemo.java index ee280f9..1a242be 100644 --- a/sample/src/main/java/oracle/r2dbc/samples/TcpsConnectDemo.java +++ b/sample/src/main/java/oracle/r2dbc/samples/TcpsConnectDemo.java @@ -37,6 +37,7 @@ import static oracle.r2dbc.samples.DatabaseConfig.HOST; import static oracle.r2dbc.samples.DatabaseConfig.PASSWORD; import static oracle.r2dbc.samples.DatabaseConfig.PORT; +import static oracle.r2dbc.samples.DatabaseConfig.SERVICE_NAME; import static oracle.r2dbc.samples.DatabaseConfig.USER; import static oracle.r2dbc.samples.DatabaseConfig.WALLET_LOCATION; @@ -91,7 +92,7 @@ public static void main(String[] args) throws URISyntaxException { USER + ":" + PASSWORD, // userInfo HOST, // host PORT, // port - "/" + DatabaseConfig.SERVICE_NAME, // path + "/" + SERVICE_NAME, // path "oracle.net.wallet_location=" + WALLET_LOCATION + "&oracle.jdbc.fanEnabled=false", // query null) // fragment @@ -114,7 +115,7 @@ public static void main(String[] args) throws URISyntaxException { .option(ConnectionFactoryOptions.DRIVER, "oracle") .option(ConnectionFactoryOptions.HOST, HOST) .option(ConnectionFactoryOptions.PORT, PORT) - .option(ConnectionFactoryOptions.DATABASE, DatabaseConfig.SERVICE_NAME) + .option(ConnectionFactoryOptions.DATABASE, SERVICE_NAME) .option(ConnectionFactoryOptions.USER, USER) .option(ConnectionFactoryOptions.PASSWORD, PASSWORD) // To configure a TCPS/SSL/TLS enabled ConnectionFactory, set the SSL From 320d8ce3ecc1854107f57565756c7ba2efbe2950 Mon Sep 17 00:00:00 2001 From: Michael-A-McMahon Date: Tue, 30 Mar 2021 14:19:16 -0700 Subject: [PATCH 3/3] Adding sample with descriptor set as ConnectionFactoryOptions.HOST --- .../oracle/r2dbc/samples/DescriptorURL.java | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/sample/src/main/java/oracle/r2dbc/samples/DescriptorURL.java b/sample/src/main/java/oracle/r2dbc/samples/DescriptorURL.java index 23875be..5002630 100644 --- a/sample/src/main/java/oracle/r2dbc/samples/DescriptorURL.java +++ b/sample/src/main/java/oracle/r2dbc/samples/DescriptorURL.java @@ -70,5 +70,24 @@ public static void main(String[] args) { .concatWith(Mono.from(connection.close()).cast(String.class))) .toStream() .forEach(System.out::println); + + // A descriptor may also be specified as the value of + // ConnectionFactoryOptions.HOST + Mono.from(ConnectionFactories.get(ConnectionFactoryOptions.builder() + .option(ConnectionFactoryOptions.DRIVER, "oracle") + .option(ConnectionFactoryOptions.HOST, DESCRIPTOR) + .option(ConnectionFactoryOptions.USER, USER) + .option(ConnectionFactoryOptions.PASSWORD, PASSWORD) + .build()) + .create()) + .flatMapMany(connection -> + Mono.from(connection.createStatement( + "SELECT 'Connected with TNS descriptor' FROM sys.dual") + .execute()) + .flatMapMany(result -> + result.map((row, metadata) -> row.get(0, String.class))) + .concatWith(Mono.from(connection.close()).cast(String.class))) + .toStream() + .forEach(System.out::println); } }