Skip to content

Commit 046ae1c

Browse files
authored
docs: update onboarding steps for Java v3 client (#6994)
* docs: (WIP) updates onboarding steps for the influxdb3-java client. * chore: dry run onboarding java. Add missing semi-colon. Minor edit. * chore: run prettier:fix * docs: update wording of query requirements for Arrow. * chore: rerun linter * chore: retrigger checks
1 parent 1e3a946 commit 046ae1c

File tree

4 files changed

+184
-52
lines changed

4 files changed

+184
-52
lines changed

src/homepageExperience/components/steps/java/ExecuteQuerySql.tsx

Lines changed: 107 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -19,29 +19,103 @@ FROM 'census'
1919
WHERE time >= now() - interval '1 hour'
2020
AND ('bees' IS NOT NULL OR 'ants' IS NOT NULL) order by time asc`
2121

22-
const query = `String sql = "SELECT * " +
23-
"FROM 'census' " +
24-
"WHERE time >= now() - interval '1 hour' " +
25-
"AND ('bees' IS NOT NULL OR 'ants' IS NOT NULL) order by time asc";
22+
const query = ` String sql = "SELECT * " +
23+
"FROM 'census' " +
24+
"WHERE time >= now() - interval '5 minutes' " +
25+
"AND ('$species1' IS NOT NULL OR '$species2' IS NOT NULL) order by time asc";
2626
27-
System.out.printf("| %-5s | %-5s | %-8s | %-30s |%n", "ants", "bees", "location", "time");
28-
try (Stream<Object[]> stream = client.query(sql, new QueryOptions("${bucket}", QueryType.SQL))) {
29-
stream.forEach(row -> System.out.printf("| %-5s | %-5s | %-8s | %-30s |%n", row[0], row[1], row[2], row[3]));
30-
}
27+
System.out.printf("| %-5s | %-5s | %-8s | %-30s |%n", "ants", "bees", "location", "time");
28+
29+
try (Stream<PointValues> ps = client.queryPoints(sql,
30+
Map.of(
31+
"species1", "bees",
32+
"species2", "ants"), // Set Query Parameters
33+
new QueryOptions("${bucket}", QueryType.SQL))) { // Set Query Options
34+
ps.forEach(pv ->
35+
System.out.printf("| %-5s | %-5s | %-8s | %-30s |%n",
36+
IntOrDefault(pv, "ants", 0),
37+
IntOrDefault(pv,"bees", 0),
38+
pv.getTag("location"),
39+
InstantTime(pv, Instant.ofEpochSecond(0))));
40+
}
3141
`
3242

3343
const queryPreview = `| ants | bees | location | time |
34-
| null | 23 | Klamath | 2023-06-02T10:21:21.083529279 |
35-
| 30 | null | Portland | 2023-06-02T10:21:22.276295461 |
36-
| null | 28 | Klamath | 2023-06-02T10:21:23.462901032 |
37-
| 32 | null | Portland | 2023-06-02T10:21:24.608998154 |
38-
| null | 29 | Klamath | 2023-06-02T10:21:25.762346305 |
39-
| 40 | null | Portland | 2023-06-02T10:21:26.901005154 |
44+
| 0 | 23 | Klamath | 2024-12-18T15:58:07.275779579Z |
45+
| 30 | 0 | Portland | 2024-12-18T15:58:08.275779579Z |
46+
| 0 | 28 | Klamath | 2024-12-18T15:58:09.275779579Z |
47+
| 32 | 0 | Portland | 2024-12-18T15:58:10.275779579Z |
48+
| 0 | 29 | Klamath | 2024-12-18T15:58:11.275779579Z |
49+
| 40 | 0 | Portland | 2024-12-18T15:58:12.275779579Z |
50+
`
51+
52+
const staticHelpers = ` private static long IntOrDefault(final PointValues pointValues,
53+
final String key,
54+
final long defaultValue){
55+
Long result = pointValues.getIntegerField(key);
56+
return result == null ? defaultValue : result;
57+
}
58+
59+
private static Instant InstantTime(final PointValues pointValues,
60+
final Instant replacement){
61+
Number raw = pointValues.getTimestamp();
62+
if(raw == null) {
63+
if (replacement == null){
64+
return Instant.ofEpochSecond(0);
65+
}
66+
return replacement;
67+
}
68+
long stamp = raw.longValue();
69+
long sec = stamp / 1000000000;
70+
long nanos = stamp % 1000000000;
71+
return Instant.ofEpochSecond(sec, nanos);
72+
}
4073
`
4174

4275
return (
4376
<>
4477
<h1>Execute a SQL Query</h1>
78+
<p>
79+
The query transport makes use of Apache Arrow Flight to shorten
80+
processing time. When executing queries Arrow needs access to internal
81+
JVM resources. This requires setting the following JVM argument:{' '}
82+
<code>--add-opens=java.base/java.nio=ALL-UNNAMED</code>
83+
</p>
84+
<h2>Java</h2>
85+
<p>This can be done with an environment variable:</p>
86+
<CodeSnippet
87+
language="bash"
88+
onCopy={logCopyCodeSnippet}
89+
showCopyControl={false}
90+
text='export JDK_JAVA_OPTIONS="--add-opens=java.base/java.nio=ALL-UNNAMED"'
91+
/>
92+
<h2>Maven</h2>
93+
<p>
94+
This argument can also be added to <code>MAVEN_OPTS</code>:
95+
</p>
96+
<CodeSnippet
97+
language="bash"
98+
onCopy={logCopyCodeSnippet}
99+
showCopyControl={false}
100+
text='export MAVEN_OPTS="--add-opens=java.base/java.nio=ALL-UNNAMED"'
101+
/>
102+
<h2>Gradle</h2>
103+
<p>
104+
With gradle this can be added to the build file, e.g. in{' '}
105+
<code>build.gradle.kts</code>:
106+
</p>
107+
<CodeSnippet
108+
language="kotlin"
109+
onCopy={logCopyCodeSnippet}
110+
showCopyControl={false}
111+
text='...
112+
application {
113+
mainClass = "example.InfluxClientExample"
114+
applicationDefaultJvmArgs = listOf("--add-opens=java.base/java.nio=ALL-UNNAMED")
115+
}
116+
...'
117+
/>
118+
45119
<p>
46120
Now let's query the data we wrote into the database with SQL. Here is
47121
what our query looks like on its own:
@@ -57,11 +131,27 @@ try (Stream<Object[]> stream = client.query(sql, new QueryOptions("${bucket}", Q
57131
with a "census" measurement and either "bees" or "ants" fields.
58132
</p>
59133
<p>
60-
Let's use that SQL query in our <code>Java</code> code to show us the
61-
results of what we have written.
134+
The client API will pass through null values for mismatched or missing
135+
tags, fields and timestamps. In anticipation of this possibility copy
136+
the following static helper methods to the <em>bottom</em> of the{' '}
137+
<code>InfluxClientExample</code> class.
138+
</p>
139+
<CodeSnippet
140+
language="java"
141+
onCopy={logCopyCodeSnippet}
142+
text={staticHelpers}
143+
/>
144+
<p>
145+
Now let's use the model SQL query in our <code>Java</code> code to show
146+
us the results of what we have written. Furthermore, let's use the SQL
147+
query parameters feature of the client library to make query calls more
148+
dynamic.
62149
</p>
63150
<p>
64-
Add the following code to the <code>WriteQueryExample</code> class:
151+
The following code replaces the fixed values of "bees" and "ants" with
152+
the parameters <code>$species1</code> and <code>$species2</code>. Add it
153+
to the <code>InfluxClientExample</code> class <em>after</em> the write
154+
code added in the previous step:
65155
</p>
66156
<CodeSnippet language="java" onCopy={logCopyCodeSnippet} text={query} />
67157
<p>

src/homepageExperience/components/steps/java/InitializeClientSql.tsx

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -20,12 +20,12 @@ import java.time.Instant;
2020
import java.util.stream.Stream;
2121
2222
import com.influxdb.v3.client.InfluxDBClient;
23+
import com.influxdb.v3.client.Point;
2324
import com.influxdb.v3.client.query.QueryOptions;
2425
import com.influxdb.v3.client.query.QueryType;
25-
import com.influxdb.v3.client.write.Point;
2626
import com.influxdb.v3.client.write.WriteOptions;
2727
28-
public final class WriteQueryExample {
28+
public final class InfluxClientExample {
2929
3030
public static void main(final String[] args) throws Exception {
3131
String hostUrl = "${url}";

src/homepageExperience/components/steps/java/InstallDependenciesSql.tsx

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -10,12 +10,12 @@ export const InstallDependenciesSql: FC = () => {
1010
}
1111

1212
const mavenDependency = `<dependency>
13-
<groupId>com.influxdb</groupId>
14-
<artifactId>influxdb3-java</artifactId>
15-
<version>0.2.0</version>
16-
</dependency>`
13+
<groupId>com.influxdb</groupId>
14+
<artifactId>influxdb3-java</artifactId>
15+
<version>1.0.0</version>
16+
</dependency>`
1717
const gradleDependency = `dependencies {
18-
implementation "com.influxdb:influxdb3-java:0.2.0"
18+
implementation("com.influxdb:influxdb3-java:1.0.0")
1919
}`
2020
return (
2121
<>

src/homepageExperience/components/steps/java/WriteDataSql.tsx

Lines changed: 70 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -49,36 +49,57 @@ export const WriteDataSqlComponent = (props: OwnProps) => {
4949
onSelectBucket(bucket.name)
5050
}, [bucket, onSelectBucket])
5151

52-
const codeSnippet = `String database = "${bucket.name}";
52+
const internalClass = ` static class CensusRecord {
53+
String location;
54+
String species;
55+
int count;
5356
54-
Point[] points = new Point[] {
55-
Point.measurement("census")
56-
.addTag("location", "Klamath")
57-
.addField("bees", 23),
58-
Point.measurement("census")
59-
.addTag("location", "Portland")
60-
.addField("ants", 30),
61-
Point.measurement("census")
62-
.addTag("location", "Klamath")
63-
.addField("bees", 28),
64-
Point.measurement("census")
65-
.addTag("location", "Portland")
66-
.addField("ants", 32),
67-
Point.measurement("census")
68-
.addTag("location", "Klamath")
69-
.addField("bees", 29),
70-
Point.measurement("census")
71-
.addTag("location", "Portland")
72-
.addField("ants", 40)
73-
};
57+
public CensusRecord(String location, String species, int count) {
58+
this.location = location;
59+
this.species = species;
60+
this.count = count;
61+
}
7462
75-
for (Point point : points) {
76-
client.writePoint(point, new WriteOptions.Builder().database(database).build());
77-
78-
Thread.sleep(1000); // separate points by 1 second
79-
}
63+
public String getLocation() {
64+
return location;
65+
}
66+
67+
public String getSpecies() {
68+
return species;
69+
}
70+
71+
public int getCount() {
72+
return count;
73+
}
74+
}`
75+
76+
const dataPrep = ` String database = "${bucket.name}";
77+
78+
List<CensusRecord> records = Arrays.asList(
79+
new CensusRecord("Klamath", "bees", 23),
80+
new CensusRecord("Portland", "ants", 30),
81+
new CensusRecord("Klamath", "bees", 28),
82+
new CensusRecord("Portland", "ants", 32),
83+
new CensusRecord("Klamath", "bees", 29),
84+
new CensusRecord("Portland", "ants", 40)
85+
);
86+
87+
List<Point> points = new ArrayList<>();
8088
81-
System.out.println("Complete. Return to the InfluxDB UI.");
89+
Instant stamp = Instant.now().minusSeconds(records.size());
90+
91+
for (CensusRecord record : records) {
92+
points.add(Point.measurement("census")
93+
.setTag("location", record.getLocation())
94+
.setIntegerField(record.getSpecies(), record.getCount())
95+
.setTimestamp(stamp)
96+
);
97+
stamp = stamp.plusSeconds(1);
98+
}`
99+
100+
const codeSnippet = ` client.writePoints(points, new WriteOptions.Builder().database(database).build());
101+
102+
System.out.println("Complete. Return to the InfluxDB UI.");
82103
`
83104

84105
return (
@@ -239,7 +260,28 @@ System.out.println("Complete. Return to the InfluxDB UI.");
239260
let's write this data into our bucket.
240261
</p>
241262
<p>
242-
Add the following code to the <code>WriteQueryExample</code> class:
263+
First, add the following internal class to the
264+
<code>InfluxClientExample</code> <em>above</em> the <code>main</code>{' '}
265+
method:
266+
</p>
267+
<CodeSnippet
268+
language="java"
269+
onCopy={logCopyCodeSnippet}
270+
text={internalClass}
271+
/>
272+
<p>
273+
Then, copy the following data preparation statements, into the{' '}
274+
<code>main</code> method <em>above</em> the{' '}
275+
<code>try(InfluxDBClient ...)</code> block:
276+
</p>
277+
<CodeSnippet
278+
language="java"
279+
onCopy={logCopyCodeSnippet}
280+
text={dataPrep}
281+
/>
282+
<p>
283+
Finally, add the following code <em>within</em> the{' '}
284+
<code>try(InfluxDBClient ...)</code> block:
243285
</p>
244286
<CodeSnippet
245287
language="java"

0 commit comments

Comments
 (0)