Skip to content

Commit 676f406

Browse files
sivankrigvenzl
andauthored
Sample client program/script to access read only data from Autonomous database Pre Authenticated request URL (#367)
* Sample client program/script to access read only data from Autonomous Database Pre Authenticated Request URL * Changing comments in README file. Signed-off-by: Sivanesan Krishnan <sivanesan.krishnan@oracle.com> * Adding pom.xml and the dependency libraries. Signed-off-by: Sivanesan Krishnan <sivanesan.krishnan@oracle.com> --------- Signed-off-by: Sivanesan Krishnan <sivanesan.krishnan@oracle.com> Co-authored-by: Gerald Venzl <gerald.venzl@oracle.com>
1 parent 45f5ee8 commit 676f406

File tree

8 files changed

+668
-0
lines changed

8 files changed

+668
-0
lines changed

java/autonomous-db-parurl/README.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
# Java Sample Accessing Read Only data from Autonomous Database Pre Authenticated Request URL.
2+
3+
This example java program allows consumers to access data from Autonomous Database Pre-Authenticated Request URL.
4+
5+
More details about the Autonomous Database Pre Authenticated Request URL can be found [here](https://docs.oracle.com/en/cloud/paas/autonomous-database/serverless/adbsb/autonomous-preauthenticated-request-url.html#GUID-976ABD3A-38A0-4E5E-BCA4-9FFB9A748C43).

java/autonomous-db-parurl/pom.xml

Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
<?xml version="1.0" encoding="UTF-8"?>
2+
<project xmlns="http://maven.apache.org/POM/4.0.0"
3+
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
4+
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
5+
<modelVersion>4.0.0</modelVersion>
6+
<groupId>autonomous-db-parurl</groupId>
7+
<artifactId>autonomous-db-parurl</artifactId>
8+
<version>0.0.1-SNAPSHOT</version>
9+
<name>autonomous-db-parurl</name>
10+
11+
<properties>
12+
<maven.compiler.source>11</maven.compiler.source>
13+
<maven.compiler.target>${maven.compiler.source}</maven.compiler.target>
14+
</properties>
15+
16+
<build>
17+
<plugins>
18+
<plugin>
19+
<groupId>org.apache.maven.plugins</groupId>
20+
<artifactId>maven-compiler-plugin</artifactId>
21+
</plugin>
22+
</plugins>
23+
</build>
24+
25+
<dependencies>
26+
<dependency>
27+
<groupId>org.projectlombok</groupId>
28+
<artifactId>lombok</artifactId>
29+
<version>RELEASE</version>
30+
</dependency>
31+
<dependency>
32+
<groupId>org.apache.commons</groupId>
33+
<artifactId>commons-lang3</artifactId>
34+
<version>3.12.0</version>
35+
</dependency>
36+
<dependency>
37+
<groupId>com.fasterxml.jackson.core</groupId>
38+
<artifactId>jackson-databind</artifactId>
39+
<version>2.17.1</version>
40+
</dependency>
41+
<dependency>
42+
<groupId>org.apache.httpcomponents</groupId>
43+
<artifactId>httpclient</artifactId>
44+
<version>4.5.4</version>
45+
</dependency>
46+
</dependencies>
47+
</project>
Lines changed: 224 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,224 @@
1+
/**
2+
* Copyright (c) 2024 Oracle and/or its affiliates.
3+
*
4+
* The Universal Permissive License (UPL), Version 1.0
5+
*
6+
* Subject to the condition set forth below, permission is hereby granted to any
7+
* person obtaining a copy of this software, associated documentation and/or data
8+
* (collectively the "Software"), free of charge and under any and all copyright
9+
* rights in the Software, and any and all patent rights owned or freely
10+
* licensable by each licensor hereunder covering either (i) the unmodified
11+
* Software as contributed to or provided by such licensor, or (ii) the Larger
12+
* Works (as defined below), to deal in both
13+
*
14+
* (a) the Software, and
15+
* (b) any piece of software and/or hardware listed in the lrgrwrks.txt file if
16+
* one is included with the Software (each a "Larger Work" to which the Software
17+
* is contributed by such licensors),
18+
*
19+
* without restriction, including without limitation the rights to copy, create
20+
* derivative works of, display, perform, and distribute the Software and make,
21+
* use, sell, offer for sale, import, export, have made, and have sold the
22+
* Software and the Larger Work(s), and to sublicense the foregoing rights on
23+
* either these or other terms.
24+
*
25+
* This license is subject to the following condition:
26+
* The above copyright notice and either this complete permission notice or at
27+
* a minimum a reference to the UPL must be included in all copies or
28+
* substantial portions of the Software.
29+
*
30+
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
31+
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
32+
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
33+
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
34+
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
35+
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
36+
* SOFTWARE.
37+
*/
38+
import com.fasterxml.jackson.databind.JsonNode;
39+
import com.fasterxml.jackson.databind.ObjectMapper;
40+
import lombok.Getter;
41+
import lombok.NoArgsConstructor;
42+
import lombok.Setter;
43+
import org.apache.commons.lang3.BooleanUtils;
44+
import org.apache.http.HttpResponse;
45+
import org.apache.http.client.methods.HttpGet;
46+
import org.apache.http.impl.client.CloseableHttpClient;
47+
import org.apache.http.impl.client.HttpClients;
48+
import org.apache.http.util.EntityUtils;
49+
50+
import java.io.IOException;
51+
import java.net.HttpURLConnection;
52+
import java.util.List;
53+
54+
/**
55+
* This class provides a basic example of how to read the data from Autonomous Database pre-authenticated URL.
56+
*
57+
* <p>The example has some constraints. This is a single threaded example & cannot be used to fetch
58+
* the data from same AdbsParUrlClient instance in multiple threads.
59+
*
60+
* <p>This example will do the following things:
61+
*
62+
* <ul>
63+
* <li>Accepts Autonomous Database pre-authenticated URL as input.
64+
* <li>Returns an iterator used to iterate records one by one.
65+
* </ul>
66+
*/
67+
public class AdbsParUrlClient {
68+
/**
69+
* Pre Authenticated Request URL.
70+
*/
71+
private final String adbsParUrl;
72+
73+
/**
74+
* Constructor
75+
*
76+
* @param adbsParUrl Pre Authenticated Request URL.
77+
*/
78+
public AdbsParUrlClient(String adbsParUrl) {
79+
this.adbsParUrl = adbsParUrl;
80+
}
81+
82+
/**
83+
* Creates ResultSet object for iterating the results.
84+
*
85+
* @return ResultSet object for iterating the results.
86+
* @throws IOException if fetching data from par url fails.
87+
*/
88+
public ResultSet execute() throws IOException {
89+
final ResultSet resultSet = new ResultSet(this.adbsParUrl);
90+
return resultSet;
91+
}
92+
93+
/**
94+
* Par Url Response pojo class
95+
*/
96+
@Getter
97+
@Setter
98+
@NoArgsConstructor
99+
public static class ParUrlResponse {
100+
private List<JsonNode> items;
101+
private Boolean hasMore;
102+
private long limit;
103+
private long offset;
104+
private long count;
105+
private List<Link> links;
106+
107+
@Getter
108+
@Setter
109+
public static class Link {
110+
private String rel;
111+
private String href;
112+
}
113+
}
114+
115+
/**
116+
* Helper class to iterate data fetched from the par url.
117+
*/
118+
public static class ResultSet {
119+
private static final ObjectMapper mapper = new ObjectMapper();
120+
private int currentOffset;
121+
private ParUrlResponse parUrlResponse;
122+
123+
/**
124+
* Constructor
125+
*
126+
* @param adbsParUrl Pre Authenticated Request URL.
127+
* @throws IOException if fetching data from par url fails.
128+
*/
129+
public ResultSet(String adbsParUrl) throws IOException {
130+
this.parUrlResponse = fetchData(adbsParUrl);
131+
this.currentOffset = 0;
132+
}
133+
134+
/**
135+
* Method to fetch data from the par url.
136+
*
137+
* @param adbsParUrl Pre Authenticated Request URL.
138+
* @return result pojo for the fetch par url data operation.
139+
* @throws IOException
140+
*/
141+
private ParUrlResponse fetchData(String adbsParUrl) throws IOException {
142+
final CloseableHttpClient httpClient = HttpClients.createDefault();
143+
final HttpGet request = new HttpGet(adbsParUrl);
144+
final HttpResponse response = httpClient.execute(request);
145+
final int statusCode = response.getStatusLine().getStatusCode();
146+
147+
if (statusCode == HttpURLConnection.HTTP_OK) { // success
148+
String responseStr = EntityUtils.toString(response.getEntity());
149+
return mapper.readValue(responseStr, ParUrlResponse.class);
150+
} else {
151+
//System.out.println(response.getStatusLine().toString());
152+
throw new RuntimeException("Error while fetching data for the par Url.");
153+
}
154+
155+
}
156+
157+
/**
158+
* Helper method to check if more items are still available.
159+
*
160+
* @return true if available else false
161+
*/
162+
public boolean hasNext() {
163+
return currentOffset < parUrlResponse.getCount() || (currentOffset == parUrlResponse.getCount() &&
164+
BooleanUtils.isTrue(parUrlResponse.hasMore));
165+
}
166+
167+
/**
168+
* Helper method to return the next item from the cached list.
169+
*
170+
* @return next item from the cached data list.
171+
* @throws IOException if fetching data from par url fails.
172+
*/
173+
public JsonNode next() throws IOException {
174+
if (currentOffset < parUrlResponse.getCount()) {
175+
return parUrlResponse.getItems().get(currentOffset++);
176+
}
177+
178+
this.currentOffset = 0;
179+
this.parUrlResponse = fetchData(getNextLink());
180+
return parUrlResponse.getItems().get(currentOffset++);
181+
}
182+
183+
/**
184+
* Method to get the fetch link for the next page items.
185+
*
186+
* @return next page link.
187+
*/
188+
private String getNextLink() {
189+
return parUrlResponse.links.stream()
190+
.filter(l -> "next".equalsIgnoreCase(l.rel))
191+
.map(l -> l.href)
192+
.findFirst().get();
193+
}
194+
}
195+
196+
/**
197+
* Fetch Data from par url sample main method.
198+
*
199+
* @param args input arguments
200+
* @throws IOException if fetching data from par url fails.
201+
*/
202+
public static void main(String[] args) throws IOException {
203+
204+
/**
205+
* Setting sample Adbs par url
206+
*/
207+
final String sampleAdbsParUrl = "https://dataaccess.adb.us-phoenix-1.oraclecloudapps.com/adb/p/NYGM5PicEMTe1hF.../data";
208+
209+
/**
210+
* Initialize the class instance fetching par url data
211+
*/
212+
AdbsParUrlClient parUrlClient = new AdbsParUrlClient(sampleAdbsParUrl);
213+
ResultSet rs = parUrlClient.execute();
214+
215+
/**
216+
* Iterate the list until all records are returned.
217+
*/
218+
while (rs.hasNext()) {
219+
JsonNode node = rs.next();
220+
System.out.println(node);
221+
}
222+
}
223+
}
224+
Lines changed: 113 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,113 @@
1+
/*
2+
## Copyright (c) 2024 Oracle and/or its affiliates.
3+
##
4+
## The Universal Permissive License (UPL), Version 1.0
5+
##
6+
## Subject to the condition set forth below, permission is hereby granted to any
7+
## person obtaining a copy of this software, associated documentation and/or data
8+
## (collectively the "Software"), free of charge and under any and all copyright
9+
## rights in the Software, and any and all patent rights owned or freely
10+
## licensable by each licensor hereunder covering either (i) the unmodified
11+
## Software as contributed to or provided by such licensor, or (ii) the Larger
12+
## Works (as defined below), to deal in both
13+
##
14+
## (a) the Software, and
15+
## (b) any piece of software and/or hardware listed in the lrgrwrks.txt file if
16+
## one is included with the Software (each a "Larger Work" to which the Software
17+
## is contributed by such licensors),
18+
##
19+
## without restriction, including without limitation the rights to copy, create
20+
## derivative works of, display, perform, and distribute the Software and make,
21+
## use, sell, offer for sale, import, export, have made, and have sold the
22+
## Software and the Larger Work(s), and to sublicense the foregoing rights on
23+
## either these or other terms.
24+
##
25+
## This license is subject to the following condition:
26+
## The above copyright notice and either this complete permission notice or at
27+
## a minimum a reference to the UPL must be included in all copies or
28+
## substantial portions of the Software.
29+
##
30+
## THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
31+
## IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
32+
## FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
33+
## AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
34+
## LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
35+
## OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
36+
## SOFTWARE.
37+
*/
38+
39+
/**
40+
* This javascript class provides a basic interface example to read the data from Autonomous Database pre-authenticated URL.
41+
*/
42+
class AdbsParUrlClient {
43+
constructor(parUrl) {
44+
this.items = [];
45+
this.totalRecords = 0;
46+
this.collectionIndexPosition = 0;
47+
this.nextGetParUrl = parUrl;
48+
this.itemsSize = 0;
49+
}
50+
51+
/**
52+
* Return the next record from the cache for the Pre-auth request url.
53+
*/
54+
getNextItem() {
55+
if (this.collectionIndexPosition < this.itemsSize) {
56+
return this.items[this.collectionIndexPosition++];
57+
} else if (this.nextGetParUrl == null) {
58+
this.items = [];
59+
this.collectionIndexPosition = 0;
60+
this.nextGetParUrl = null;
61+
this.itemsSize = 0;
62+
return null;
63+
} else {
64+
this.items = [];
65+
this.collectionIndexPosition = 0;
66+
this.itemsSize = 0;
67+
var jsonResponse = this.fetchParUrlData();
68+
var hasMore = jsonResponse.hasMore;
69+
70+
console.log("items returned: " + jsonResponse.items.length);
71+
this.totalRecords = this.totalRecords + jsonResponse.items.length;
72+
this.itemsSize = jsonResponse.items.length;
73+
74+
for (var count = 0; count < jsonResponse.items.length; count++) {
75+
this.items.push(jsonResponse.items[count]);
76+
}
77+
78+
console.log("hasMore: " + hasMore);
79+
if (hasMore) {
80+
var links = jsonResponse.links;
81+
for (var count = 0; count < links.length; count++) {
82+
if (links[count]['rel'] == 'next') {
83+
this.nextGetParUrl = links[count]['href'];
84+
console.log("Next url href: " + this.nextGetParUrl);
85+
}
86+
}
87+
} else {
88+
this.nextGetParUrl = null;
89+
}
90+
91+
return this.items[this.collectionIndexPosition++];
92+
}
93+
}
94+
95+
/**
96+
* Fetch the Par Url data by invoking HTTP Get call.
97+
*/
98+
fetchParUrlData() {
99+
console.log("Invoking Get call on Url: " + this.nextGetParUrl);
100+
var request = new XMLHttpRequest();
101+
request.open("GET", this.nextGetParUrl, false);
102+
request.setRequestHeader("Content-Type", "application/json");
103+
request.send();
104+
105+
console.log("Get Call status: " + request.status);
106+
107+
if (request.status === 200) {
108+
return JSON.parse(request.responseText);
109+
} else {
110+
throw new Error("Failed to fetch the par url data");
111+
}
112+
}
113+
}

0 commit comments

Comments
 (0)