Skip to content

Commit 2a3a080

Browse files
authored
Merge pull request #263 from eclipse/enhance-oracle-configuration
Enhance Oracle NoSQL Configuration
2 parents c70cf49 + f010b61 commit 2a3a080

File tree

9 files changed

+462
-60
lines changed

9 files changed

+462
-60
lines changed

README.adoc

Lines changed: 43 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -1058,13 +1058,13 @@ Stream<Person> stream = template.select(Person.class , filter);
10581058

10591059
image::https://www.jnosql.org/img/logos/oracle.png[Oracle NoSQL Project,align="center"width=25%,height=25%]
10601060

1061-
https://www.oracle.com/database/nosql/technologies/nosql/[Oracle NoSQL Database] is a native multi-model database that provides flexible data models for documents, graphs, and key values. You can develop high-performance applications using a user-friendly SQL-like query language or JavaScript extensions.
1061+
[Oracle NoSQL Database](https://www.oracle.com/database/nosql/technologies/nosql/) is a versatile multi-model database offering flexible data models for documents, graphs, and key-value pairs. It empowers developers to build high-performance applications using a user-friendly SQL-like query language or JavaScript extensions.
10621062

1063-
This API offers support for *Document* and *Key-Value* data types.
1063+
This API provides support for *Document* and *Key-Value* data types.
10641064

1065-
=== How To Install
1065+
=== Installation
10661066

1067-
You can use either the Maven or Gradle dependencies:
1067+
You can include Oracle NoSQL as a dependency using either Maven or Gradle:
10681068

10691069
[source,xml]
10701070
----
@@ -1077,41 +1077,60 @@ You can use either the Maven or Gradle dependencies:
10771077

10781078
=== Configuration
10791079

1080-
This API provides the ```OracleNoSQLConfigurations``` class to programmatically establish the credentials.
1081-
Please note that you can establish properties using the https://microprofile.io/microprofile-config/[MicroProfile Config] specification.
1080+
The API offers the `OracleNoSQLConfigurations` class to programmatically set up credentials. It also supports configuration via the [MicroProfile Config](https://microprofile.io/microprofile-config/) specification.
10821081

10831082
[cols="Oracle NoSQL Properties"]
10841083
|===
10851084
| Property Name | Description
10861085

1087-
| `jnosql.oracle.nosql.host` | Specifies the hostname or IP address of the Oracle NoSQL database server.
1086+
| `jnosql.oracle.nosql.host` | Hostname or IP address of the Oracle NoSQL database server.
10881087

1089-
| `jnosql.oracle.nosql.user` | Specifies the username used to authenticate with the Oracle NoSQL database.
1088+
| `jnosql.oracle.nosql.user` | Username for Oracle NoSQL database authentication.
10901089

1091-
| `jnosql.oracle.nosql.password` | Specifies the password used to authenticate with the Oracle NoSQL database.
1090+
| `jnosql.oracle.nosql.password` | Password for Oracle NoSQL database authentication.
10921091

1093-
| `jnosql.oracle.nosql.table.read.limit` | Specifies the desired throughput of read operations when creating a table using Eclipse JNoSQL.
1092+
| `jnosql.oracle.nosql.table.read.limit` | Desired throughput of read operations when creating tables with Eclipse JNoSQL.
10941093

1095-
| `jnosql.oracle.nosql.table.write.limit` | Specifies the desired throughput of write operations when creating a table using Eclipse JNoSQL.
1094+
| `jnosql.oracle.nosql.table.write.limit` | Desired throughput of write operations when creating tables with Eclipse JNoSQL.
10961095

1097-
| `jnosql.oracle.nosql.table.storage.gb` | Specifies the maximum storage, in gigabytes, to be consumed by a table created using Eclipse JNoSQL.
1096+
| `jnosql.oracle.nosql.table.storage.gb` | Maximum storage in gigabytes for tables created with Eclipse JNoSQL.
10981097

1099-
| `jnosql.oracle.nosql.table.wait.millis` | Specifies the total amount of time to wait, in milliseconds, when creating a table.
1098+
| `jnosql.oracle.nosql.table.wait.millis` | Total waiting time in milliseconds when creating a table.
11001099

1101-
| `jnosql.oracle.nosql.table.delay.millis` | Specifies the amount of time to wait, in milliseconds, between polling attempts when creating a table.
1100+
| `jnosql.oracle.nosql.table.delay.millis` | Time between polling attempts in milliseconds when creating a table.
11021101

1103-
| `jnosql.oracle.nosql.deployment` | Specifies the deployment type for Oracle NoSQL database.
1102+
| `jnosql.oracle.nosql.tenant.id` | Tenant ID for Oracle NoSQL database in a Cloud deployment.
11041103

1105-
| `jnosql.oracle.nosql.tenant.id` | Specifies the Oracle NoSQL database tenant ID for Cloud deployment.
1104+
| `jnosql.oracle.nosql.fingerprint` | Fingerprint for authentication with Oracle NoSQL database in a Cloud deployment.
11061105

1107-
| `jnosql.oracle.nosql.fingerprint` | Specifies the fingerprint for authentication with Oracle NoSQL database for Cloud deployment.
1106+
| `jnosql.oracle.nosql.private.key` | Private key for authentication with Oracle NoSQL database in a Cloud deployment.
11081107

1109-
| `jnosql.oracle.nosql.private.key` | Specifies the private key for authentication with Oracle NoSQL database for Cloud deployment.
1110-
|===
1108+
| `jnosql.oracle.nosql.compartment` | Compartment name in Oracle Cloud Infrastructure.
1109+
1110+
| `jnosql.oracle.nosql.namespace` | Namespace name in Oracle NoSQL on-premises.
1111+
1112+
| `jnosql.oracle.nosql.profile.name` | Specifies the profile name used to load session token in Oracle NoSQL cloud.
1113+
1114+
| `jnosql.oracle.nosql.config.file` | Specifies the path of configuration file used to load session token in Oracle NoSQL cloud.
1115+
1116+
| `jnosql.oracle.nosql.deployment` | Specifies the deployment type for Oracle NoSQL database. You can choose from the following options:
11111117

1118+
- `ON_PREMISES`: Represents an on-premises deployment where software solutions are deployed and managed within an organization's physical premises or data centers.
11121119

1120+
- `CLOUD_API_KEY`: Represents a cloud deployment using API key for authentication and authorization.
11131121

1114-
This is an example using Oracle NoSQL's Document API with MicroProfile Config.
1122+
- `CLOUD_INSTANCE_PRINCIPAL`: Represents a cloud deployment using instance principal for authentication and authorization.
1123+
1124+
- `CLOUD_RESOURCE_PRINCIPAL`: Represents a cloud deployment using resource principal for authentication and authorization.
1125+
1126+
- `CLOUD_INSTANCE_OBO_USER`: Represents a cloud deployment using instance principal for delegation with an OBO token.
1127+
1128+
- `CLOUD_SECURITY_TOKEN`: Represents a "Cloud" deployment using resource principal for delegation with an OBO token.
1129+
|===
1130+
1131+
Below are examples using Oracle NoSQL's Document API and Key-Value API with MicroProfile Config.
1132+
1133+
**Document API Example:**
11151134

11161135
[source,properties]
11171136
----
@@ -1120,7 +1139,7 @@ jnosql.document.database=library
11201139
jnosql.oracle.nosql.host=http://localhost:8080
11211140
----
11221141

1123-
This is an example using Oracle NoSQL's Key-Value API with MicroProfile Config.
1142+
**Key-Value API Example:**
11241143

11251144
[source,properties]
11261145
----
@@ -1129,7 +1148,7 @@ jnosql.keyvalue.database=library
11291148
jnosql.oracle.nosql.host=http://localhost:8080
11301149
----
11311150

1132-
The config settings are the default behavior; nevertheless, there is an option to do it programmatically. Create a class that implements the `Supplier<ArangoDBDocumentManager>` and then defines it as an `@Alternative` and the `Priority`.
1151+
Although these are the default configuration settings, you have the option to configure them programmatically. Create a class that implements `Supplier<OracleNoSQLDocumentManager>`, annotate it with `@Alternative`, and set the priority using `@Priority`.
11331152

11341153
[source,java]
11351154
----
@@ -1151,7 +1170,7 @@ public class ManagerSupplier implements Supplier<OracleNoSQLDocumentManager> {
11511170

11521171
=== Repository
11531172

1154-
The ```OracleNoSQLRepository``` interface is an extension of the Repository interface that allows execution of SQL via the ```@SQL``` annotation. Also, it's possible to combine with ```@Param``` annotation to execute parameterized SQL queries:
1173+
The `OracleNoSQLRepository` interface extends the Repository interface and allows executing SQL queries using the `@SQL` annotation. You can also combine it with the `@Param` annotation for parameterized SQL queries:
11551174

11561175
[source,java]
11571176
----
@@ -1169,7 +1188,7 @@ interface PersonRepository extends OracleNoSQLRepository<Person, String> {
11691188

11701189
=== Template
11711190

1172-
The ```OracleNoSQLTemplate``` interface is a specialization of the ```DocumentTemplate``` interface that allows using synchronous SQL operation.
1191+
The `OracleNoSQLTemplate` interface, an extension of the `DocumentTemplate`, enables synchronous SQL operations.
11731192

11741193
[source,java]
11751194
----

jnosql-nosql-oracle/src/main/java/org/eclipse/jnosql/databases/oracle/communication/DefaultOracleNoSQLDocumentManager.java

Lines changed: 30 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@
2020
import jakarta.json.JsonValue;
2121
import jakarta.json.bind.Jsonb;
2222
import oracle.nosql.driver.NoSQLHandle;
23+
import oracle.nosql.driver.TimeToLive;
2324
import oracle.nosql.driver.ops.DeleteRequest;
2425
import oracle.nosql.driver.ops.GetRequest;
2526
import oracle.nosql.driver.ops.GetResult;
@@ -86,26 +87,17 @@ public String name() {
8687
@Override
8788
public DocumentEntity insert(DocumentEntity entity) {
8889
Objects.requireNonNull(entity, "entity is required");
89-
Map<String, Object> entityMap = new HashMap<>(entity.toMap());
90-
entityMap.put(ENTITY, entity.name());
91-
String id = entity.find(ID).map(Document::get)
92-
.map(Object::toString)
93-
.orElseGet(() -> UUID.randomUUID().toString());
94-
95-
MapValue mapValue = new MapValue().put(ORACLE_ID, id).put(ENTITY, entity.name());
96-
MapValue contentVal = mapValue.putFromJson("content", jsonB.toJson(entityMap),
97-
OPTIONS);
98-
PutRequest putRequest = new PutRequest()
99-
.setValue(contentVal)
100-
.setTableName(name());
101-
102-
serviceHandle.put(putRequest);
90+
put(entity, TimeToLive.DO_NOT_EXPIRE);
10391
return entity;
10492
}
10593

94+
10695
@Override
10796
public DocumentEntity insert(DocumentEntity entity, Duration ttl) {
108-
throw new UnsupportedOperationException("Oracle NoSQL database does not support TTL");
97+
Objects.requireNonNull(entity, "entity is required");
98+
Objects.requireNonNull(ttl, "ttl is required");
99+
put(entity, TimeToLive.ofHours(ttl.toHours()));
100+
return entity;
109101
}
110102

111103
@Override
@@ -117,7 +109,10 @@ public Iterable<DocumentEntity> insert(Iterable<DocumentEntity> entities) {
117109

118110
@Override
119111
public Iterable<DocumentEntity> insert(Iterable<DocumentEntity> entities, Duration ttl) {
120-
throw new UnsupportedOperationException("Oracle NoSQL database does not support TTL");
112+
Objects.requireNonNull(entities, "entities is required");
113+
Objects.requireNonNull(ttl, "ttl is required");
114+
StreamSupport.stream(entities.spliterator(), false).forEach(d -> insert(d, ttl));
115+
return entities;
121116
}
122117

123118
@Override
@@ -286,4 +281,23 @@ private List<DocumentEntity> executeSQL(String sql, List<FieldValue> params) {
286281
} while (!queryRequest.isDone());
287282
return entities;
288283
}
284+
285+
private void put(DocumentEntity entity, TimeToLive ttl) {
286+
Map<String, Object> entityMap = new HashMap<>(entity.toMap());
287+
entityMap.put(ENTITY, entity.name());
288+
String id = entity.find(ID).map(Document::get)
289+
.map(Object::toString)
290+
.orElseGet(() -> UUID.randomUUID().toString());
291+
292+
MapValue mapValue = new MapValue().put(ORACLE_ID, id).put(ENTITY, entity.name());
293+
MapValue contentVal = mapValue.putFromJson("content", jsonB.toJson(entityMap),
294+
OPTIONS);
295+
PutRequest putRequest = new PutRequest()
296+
.setValue(contentVal)
297+
.setTTL(ttl)
298+
.setTableName(name());
299+
300+
serviceHandle.put(putRequest);
301+
}
302+
289303
}

jnosql-nosql-oracle/src/main/java/org/eclipse/jnosql/databases/oracle/communication/DeploymentType.java

Lines changed: 53 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@
2020
import org.eclipse.jnosql.communication.Configurations;
2121
import org.eclipse.jnosql.communication.Settings;
2222

23+
import java.io.File;
2324
import java.io.IOException;
2425
import java.util.List;
2526
import java.util.Optional;
@@ -33,8 +34,12 @@ public enum DeploymentType implements Function<Settings, Optional<AuthorizationP
3334
/**
3435
* Represents an "On-premises" deployment where software solutions are deployed and managed
3536
* within an organization's physical premises or data centers.
37+
* Usage: Choose this deployment type when your software solutions are hosted and managed within your organization's physical infrastructure.
38+
* - Authentication: Uses username and password for access.
39+
* - Configuration: Requires USER (username) and PASSWORD (password).
40+
* If not provided, it falls back to default values or empty credentials.
3641
*/
37-
ON_PREMISES{
42+
ON_PREMISES {
3843
@Override
3944
public Optional<AuthorizationProvider> apply(Settings settings) {
4045
String user = settings.get(List.of(OracleNoSQLConfigurations.USER.get(), Configurations.USER.get()))
@@ -51,10 +56,9 @@ public Optional<AuthorizationProvider> apply(Settings settings) {
5156
},
5257

5358
/**
54-
* Represents a "Cloud" deployment where software solutions are delivered and managed
55-
* over the internet (the cloud) by Oracle cloud provider.
59+
* Represents a "Cloud" deployment using API key for authentication and authorization.
5660
*/
57-
CLOUD{
61+
CLOUD_API_KEY {
5862
@Override
5963
public Optional<AuthorizationProvider> apply(Settings settings) {
6064

@@ -69,14 +73,58 @@ public Optional<AuthorizationProvider> apply(Settings settings) {
6973
if(user != null && password.length > 0 && tenantId != null && fingerprint != null && privateKey != null) {
7074
return Optional.of(new SignatureProvider(tenantId, user, fingerprint, privateKey, password));
7175
}
72-
7376
try {
7477
return Optional.of(new SignatureProvider());
7578
} catch (IOException e) {
7679
throw new OracleNoSQLException("Error to load configuration to Oracle Cloud at Oracle NoSQL", e);
7780
}
7881

7982
}
83+
},
84+
/**
85+
* Represents a "Cloud" deployment using resource principal for authentication and authorization.
86+
*/
87+
CLOUD_INSTANCE_PRINCIPAL {
88+
@Override
89+
public Optional<AuthorizationProvider> apply(Settings settings) {
90+
return Optional.of(SignatureProvider.createWithInstancePrincipal());
91+
}
92+
},
93+
/**
94+
* Represents a "Cloud" deployment using resource principal for authentication and authorization.
95+
*/
96+
CLOUD_RESOURCE_PRINCIPAL {
97+
@Override
98+
public Optional<AuthorizationProvider> apply(Settings settings) {
99+
return Optional.of(SignatureProvider.createWithResourcePrincipal());
100+
}
101+
},
102+
/**
103+
* Represents a "Cloud" deployment using instance principal for delegation with an OBO token.
104+
*/
105+
CLOUD_INSTANCE_OBO_USER {
106+
@Override
107+
public Optional<AuthorizationProvider> apply(Settings settings) {
108+
return Optional.of(SignatureProvider.createWithInstancePrincipalForDelegation(new File(System.getenv("OCI_obo_token_path"))));
109+
}
110+
},
111+
/**
112+
* Represents a "Cloud" deployment using resource principal for delegation with an OBO token.
113+
*/
114+
CLOUD_SECURITY_TOKEN {
115+
@Override
116+
public Optional<AuthorizationProvider> apply(Settings settings) {
117+
118+
String profileName = settings.get(OracleNoSQLConfigurations.PROFILE_NAME, String.class).orElse(null);
119+
String configFile = settings.get(OracleNoSQLConfigurations.CONFIG_FILE, String.class).orElse(null);
120+
if(profileName != null && configFile != null) {
121+
return Optional.of(SignatureProvider.createWithSessionToken(configFile, profileName));
122+
} else if(profileName != null) {
123+
return Optional.of(SignatureProvider.createWithSessionToken(profileName));
124+
} else {
125+
return Optional.of(SignatureProvider.createWithSessionToken());
126+
}
127+
}
80128
};
81129

82130

jnosql-nosql-oracle/src/main/java/org/eclipse/jnosql/databases/oracle/communication/NoSQLHandleConfigConfiguration.java

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,11 +20,14 @@
2020

2121
import java.util.List;
2222
import java.util.function.Function;
23+
import java.util.logging.Logger;
2324

2425
enum NoSQLHandleConfigConfiguration implements Function<Settings, NoSQLHandleConfiguration> {
2526

2627
INSTANCE;
2728

29+
private static final Logger LOGGER = Logger.getLogger(NoSQLHandleConfigConfiguration.class.getName());
30+
2831
private static final String DEFAULT_HOST = "http://localhost:8080";
2932
private static final int DEFAULT_TABLE_READ_LIMITS = 25;
3033
private static final int DEFAULT_TABLE_WRITE_LIMITS = 25;
@@ -33,12 +36,16 @@ enum NoSQLHandleConfigConfiguration implements Function<Settings, NoSQLHandleCon
3336
private static final int DEFAULT_TABLE_DELAY_MILLIS = 500;
3437
@Override
3538
public NoSQLHandleConfiguration apply(Settings settings) {
39+
3640
String host = settings.get(List.of(OracleNoSQLConfigurations.HOST.get(), Configurations.HOST.get()))
3741
.map(Object::toString).orElse(DEFAULT_HOST);
3842

3943

4044
DeploymentType deploymentType = settings.get(OracleNoSQLConfigurations.DEPLOYMENT.get())
4145
.map(Object::toString).map(DeploymentType::parse).orElse(DeploymentType.ON_PREMISES);
46+
47+
LOGGER.info("Connecting to Oracle NoSQL database at " + host + " using " + deploymentType + " deployment type");
48+
4249
NoSQLHandleConfig config = new NoSQLHandleConfig(host);
4350

4451
deploymentType.apply(settings).ifPresent(config::setAuthorizationProvider);
@@ -48,6 +55,10 @@ public NoSQLHandleConfiguration apply(Settings settings) {
4855
int waitMillis = settings.getOrDefault(OracleNoSQLConfigurations.TABLE_WAIT_MILLIS, DEFAULT_TABLE_WAIT_MILLIS);
4956
int delayMillis = settings.getOrDefault(OracleNoSQLConfigurations.TABLE_DELAY_MILLIS, DEFAULT_TABLE_DELAY_MILLIS);
5057
var tableLimits = new TableCreationConfiguration(readLimit, writeLimit, storageGB, waitMillis, delayMillis);
58+
settings.get(OracleNoSQLConfigurations.NAMESPACE.get())
59+
.map(Object::toString).ifPresent(config::setDefaultNamespace);
60+
settings.get(OracleNoSQLConfigurations.COMPARTMENT.get())
61+
.map(Object::toString).ifPresent(config::setDefaultCompartment);
5162
return new NoSQLHandleConfiguration(config, tableLimits);
5263
}
5364
}

0 commit comments

Comments
 (0)