Skip to content

Commit 36360f8

Browse files
Alexandre Dutraolim7t
authored andcommitted
JAVA-1237: Add JSR-353 JSON examples
1 parent 4d1c7f2 commit 36360f8

4 files changed

Lines changed: 539 additions & 0 deletions

File tree

driver-examples/pom.xml

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,21 @@
5555
<optional>true</optional>
5656
</dependency>
5757

58+
<dependency>
59+
<groupId>javax.json</groupId>
60+
<artifactId>javax.json-api</artifactId>
61+
<version>${jsr353-api.version}</version>
62+
<optional>true</optional>
63+
</dependency>
64+
65+
<dependency>
66+
<groupId>org.glassfish</groupId>
67+
<artifactId>javax.json</artifactId>
68+
<version>${jsr353-ri.version}</version>
69+
<optional>true</optional>
70+
<scope>runtime</scope>
71+
</dependency>
72+
5873
<!-- driver logs -->
5974
<dependency>
6075
<groupId>ch.qos.logback</groupId>
Lines changed: 164 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,164 @@
1+
/*
2+
* Copyright (C) 2012-2015 DataStax Inc.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
package com.datastax.driver.examples.json;
17+
18+
import com.datastax.driver.core.*;
19+
import com.datastax.driver.extras.codecs.json.Jsr353JsonCodec;
20+
21+
import javax.json.Json;
22+
import javax.json.JsonObject;
23+
import javax.json.JsonStructure;
24+
25+
import static com.datastax.driver.core.querybuilder.QueryBuilder.*;
26+
27+
/**
28+
* Illustrates how to map a single table column of type {@code VARCHAR},
29+
* containing JSON payloads, into a Java object using
30+
* the <a href="https://jcp.org/en/jsr/detail?id=353">Java API for JSON processing</a>.
31+
* <p/>
32+
* This example makes usage of a custom {@link TypeCodec codec},
33+
* {@link Jsr353JsonCodec}, which is declared in the driver-extras module.
34+
* If you plan to follow this example, make sure to include the following
35+
* Maven dependencies in your project:
36+
* <pre>{@code
37+
* <dependency>
38+
* <groupId>com.datastax.cassandra</groupId>
39+
* <artifactId>cassandra-driver-extras</artifactId>
40+
* <version>${driver.version}</version>
41+
* </dependency>
42+
*
43+
* <dependency>
44+
* <groupId>javax.json</groupId>
45+
* <artifactId>javax.json-api</artifactId>
46+
* <version>${jsr353-api.version}</version>
47+
* </dependency>
48+
*
49+
* <dependency>
50+
* <groupId>org.glassfish</groupId>
51+
* <artifactId>javax.json</artifactId>
52+
* <version>${jsr353-ri.version}</version>
53+
* <scope>runtime</scope>
54+
* </dependency>
55+
* }</pre>
56+
* This example also uses the {@link com.datastax.driver.core.querybuilder.QueryBuilder QueryBuilder};
57+
* for examples using the "core" API, see {@link PlainTextJson} (they are easily translatable to the
58+
* queries in this class).
59+
* <p/>
60+
* Preconditions:
61+
* - a Cassandra cluster is running and accessible through the contacts points identified by CONTACT_POINTS and PORT;
62+
* <p/>
63+
* Side effects:
64+
* - creates a new keyspace "examples" in the cluster. If a keyspace with this name already exists, it will be reused;
65+
* - creates a table "examples.json_jsr353_column". If it already exists, it will be reused;
66+
* - inserts data in the table.
67+
*/
68+
public class Jsr353JsonColumn {
69+
70+
static String[] CONTACT_POINTS = {"127.0.0.1"};
71+
static int PORT = 9042;
72+
73+
public static void main(String[] args) {
74+
Cluster cluster = null;
75+
try {
76+
77+
// A codec to convert JSON payloads into JsonObject instances;
78+
// this codec is declared in the driver-extras module
79+
Jsr353JsonCodec userCodec = new Jsr353JsonCodec();
80+
81+
cluster = Cluster.builder()
82+
.addContactPoints(CONTACT_POINTS).withPort(PORT)
83+
.withCodecRegistry(new CodecRegistry().register(userCodec))
84+
.build();
85+
86+
Session session = cluster.connect();
87+
88+
createSchema(session);
89+
insertJsonColumn(session);
90+
selectJsonColumn(session);
91+
92+
} finally {
93+
if (cluster != null) cluster.close();
94+
}
95+
}
96+
97+
private static void createSchema(Session session) {
98+
session.execute("CREATE KEYSPACE IF NOT EXISTS examples " +
99+
"WITH replication = {'class': 'SimpleStrategy', 'replication_factor': 1}");
100+
session.execute("CREATE TABLE IF NOT EXISTS examples.json_jsr353_column(" +
101+
"id int PRIMARY KEY, json text)");
102+
}
103+
104+
// Mapping a JSON object to a table column
105+
private static void insertJsonColumn(Session session) {
106+
107+
JsonObject alice = Json.createObjectBuilder()
108+
.add("name", "alice")
109+
.add("age", 30)
110+
.build();
111+
112+
JsonObject bob = Json.createObjectBuilder()
113+
.add("name", "bob")
114+
.add("age", 35)
115+
.build();
116+
117+
// Build and execute a simple statement
118+
Statement stmt = insertInto("examples", "json_jsr353_column")
119+
.value("id", 1)
120+
// the JSON object will be converted into a String and persisted into the VARCHAR column "json"
121+
.value("json", alice);
122+
session.execute(stmt);
123+
124+
// The JSON object can be a bound value if the statement is prepared
125+
// (we use a local variable here for the sake of example, but in a real application you would cache and reuse
126+
// the prepared statement)
127+
PreparedStatement pst = session.prepare(
128+
insertInto("examples", "json_jsr353_column")
129+
.value("id", bindMarker("id"))
130+
.value("json", bindMarker("json")));
131+
session.execute(pst.bind()
132+
.setInt("id", 2)
133+
// note that the codec requires that the type passed to the set() method
134+
// be always JsonStructure, and not a subclass of it, such as JsonObject
135+
.set("json", bob, JsonStructure.class));
136+
}
137+
138+
// Retrieving JSON objects from a table column
139+
private static void selectJsonColumn(Session session) {
140+
141+
Statement stmt = select()
142+
.from("examples", "json_jsr353_column")
143+
.where(in("id", 1, 2));
144+
145+
ResultSet rows = session.execute(stmt);
146+
147+
for (Row row : rows) {
148+
int id = row.getInt("id");
149+
// retrieve the JSON payload and convert it to a JsonObject instance
150+
// note that the codec requires that the type passed to the get() method
151+
// be always JsonStructure, and not a subclass of it, such as JsonObject,
152+
// hence the need to downcast to JsonObject manually
153+
JsonObject user = (JsonObject) row.get("json", JsonStructure.class);
154+
// it is also possible to retrieve the raw JSON payload
155+
String json = row.getString("json");
156+
System.out.printf("Retrieved row:%n" +
157+
"id %d%n" +
158+
"user %s%n" +
159+
"user (raw) %s%n%n",
160+
id, user, json);
161+
}
162+
}
163+
164+
}
Lines changed: 201 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,201 @@
1+
/*
2+
* Copyright (C) 2012-2015 DataStax Inc.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
package com.datastax.driver.examples.json;
17+
18+
import com.datastax.driver.core.*;
19+
import com.datastax.driver.extras.codecs.json.Jsr353JsonCodec;
20+
21+
import javax.json.Json;
22+
import javax.json.JsonObject;
23+
import javax.json.JsonStructure;
24+
25+
import static com.datastax.driver.core.querybuilder.QueryBuilder.*;
26+
27+
/**
28+
* Illustrates how to map a single table column of an arbitrary type
29+
* to a Java object using
30+
* the <a href="https://jcp.org/en/jsr/detail?id=353">Java API for JSON processing</a>,
31+
* and leveraging the {@code toJson()} and {@code fromJson()} functions
32+
* introduced in Cassandra 2.2.
33+
* <p/>
34+
* This example makes usage of a custom {@link TypeCodec codec},
35+
* {@link Jsr353JsonCodec}, which is declared in the driver-extras module.
36+
* If you plan to follow this example, make sure to include the following
37+
* Maven dependencies in your project:
38+
* <pre>{@code
39+
* <dependency>
40+
* <groupId>com.datastax.cassandra</groupId>
41+
* <artifactId>cassandra-driver-extras</artifactId>
42+
* <version>${driver.version}</version>
43+
* </dependency>
44+
*
45+
* <dependency>
46+
* <groupId>javax.json</groupId>
47+
* <artifactId>javax.json-api</artifactId>
48+
* <version>${jsr353-api.version}</version>
49+
* </dependency>
50+
*
51+
* <dependency>
52+
* <groupId>org.glassfish</groupId>
53+
* <artifactId>javax.json</artifactId>
54+
* <version>${jsr353-ri.version}</version>
55+
* <scope>runtime</scope>
56+
* </dependency>
57+
* }</pre>
58+
* This example also uses the {@link com.datastax.driver.core.querybuilder.QueryBuilder QueryBuilder};
59+
* for examples using the "core" API, see {@link PlainTextJson} (they are easily translatable to the
60+
* queries in this class).
61+
* <p/>
62+
* Preconditions:
63+
* - a Cassandra cluster is running and accessible through the contacts points identified by CONTACT_POINTS and PORT;
64+
* <p/>
65+
* Side effects:
66+
* - creates a new keyspace "examples" in the cluster. If a keyspace with this name already exists, it will be reused;
67+
* - creates a user-defined type (UDT) "examples.json_jsr353_function_user". If it already exists, it will be reused;
68+
* - creates a table "examples.json_jsr353_function". If it already exists, it will be reused;
69+
* - inserts data in the table.
70+
*
71+
* @see <a href="http://www.datastax.com/dev/blog/whats-new-in-cassandra-2-2-json-support">What’s New in Cassandra 2.2: JSON Support</a>
72+
*/
73+
public class Jsr353JsonFunction {
74+
75+
static String[] CONTACT_POINTS = {"127.0.0.1"};
76+
static int PORT = 9042;
77+
78+
public static void main(String[] args) {
79+
Cluster cluster = null;
80+
try {
81+
82+
// A codec to convert JSON payloads into JsonObject instances;
83+
// this codec is declared in the driver-extras module
84+
Jsr353JsonCodec userCodec = new Jsr353JsonCodec();
85+
86+
cluster = Cluster.builder()
87+
.addContactPoints(CONTACT_POINTS).withPort(PORT)
88+
.withCodecRegistry(new CodecRegistry()
89+
.register(userCodec))
90+
.build();
91+
92+
Session session = cluster.connect();
93+
94+
createSchema(session);
95+
insertFromJson(session);
96+
selectToJson(session);
97+
98+
} finally {
99+
if (cluster != null) cluster.close();
100+
}
101+
}
102+
103+
private static void createSchema(Session session) {
104+
session.execute("CREATE KEYSPACE IF NOT EXISTS examples " +
105+
"WITH replication = {'class': 'SimpleStrategy', 'replication_factor': 1}");
106+
session.execute("CREATE TYPE IF NOT EXISTS examples.json_jsr353_function_user(" +
107+
"name text, age int)");
108+
session.execute("CREATE TABLE IF NOT EXISTS examples.json_jsr353_function(" +
109+
"id int PRIMARY KEY, user frozen<json_jsr353_function_user>, scores map<varchar,float>)");
110+
}
111+
112+
// Mapping JSON payloads to table columns of arbitrary types,
113+
// using fromJson() function
114+
private static void insertFromJson(Session session) {
115+
116+
JsonObject alice = Json.createObjectBuilder()
117+
.add("name", "alice")
118+
.add("age", 30)
119+
.build();
120+
121+
JsonObject bob = Json.createObjectBuilder()
122+
.add("name", "bob")
123+
.add("age", 35)
124+
.build();
125+
126+
JsonObject aliceScores = Json.createObjectBuilder()
127+
.add("call_of_duty", 4.8)
128+
.add("pokemon_go", 9.7)
129+
.build();
130+
131+
JsonObject bobScores = Json.createObjectBuilder()
132+
.add("zelda", 8.3)
133+
.add("pokemon_go", 12.4)
134+
.build();
135+
136+
// Build and execute a simple statement
137+
Statement stmt = insertInto("examples", "json_jsr353_function")
138+
.value("id", 1)
139+
// client-side, the JsonObject will be converted into a JSON String;
140+
// then, server-side, the fromJson() function will convert that JSON string
141+
// into an instance of the json_jsr353_function_user user-defined type (UDT),
142+
// which will be persisted into the column "user"
143+
.value("user", fromJson(alice))
144+
// same thing, but this time converting from
145+
// a JsonObject to a JSON string, then from this string to a map<varchar,float>
146+
.value("scores", fromJson(aliceScores));
147+
session.execute(stmt);
148+
149+
// The JSON object can be a bound value if the statement is prepared
150+
// (we use a local variable here for the sake of example, but in a real application you would cache and reuse
151+
// the prepared statement)
152+
PreparedStatement pst = session.prepare(
153+
insertInto("examples", "json_jsr353_function")
154+
.value("id", bindMarker("id"))
155+
.value("user", fromJson(bindMarker("user")))
156+
.value("scores", fromJson(bindMarker("scores"))));
157+
session.execute(pst.bind()
158+
.setInt("id", 2)
159+
// note that the codec requires that the type passed to the set() method
160+
// be always JsonStructure, and not a subclass of it, such as JsonObject
161+
.set("user", bob, JsonStructure.class)
162+
.set("scores", bobScores, JsonStructure.class));
163+
}
164+
165+
// Retrieving JSON payloads from table columns of arbitrary types,
166+
// using toJson() function
167+
private static void selectToJson(Session session) {
168+
169+
Statement stmt = select()
170+
.column("id")
171+
.toJson("user").as("user")
172+
.toJson("scores").as("scores")
173+
.from("examples", "json_jsr353_function")
174+
.where(in("id", 1, 2));
175+
176+
ResultSet rows = session.execute(stmt);
177+
178+
for (Row row : rows) {
179+
int id = row.getInt("id");
180+
// retrieve the JSON payload and convert it to a JsonObject instance
181+
// note that the codec requires that the type passed to the get() method
182+
// be always JsonStructure, and not a subclass of it, such as JsonObject,
183+
// hence the need to downcast to JsonObject manually
184+
JsonObject user = (JsonObject) row.get("user", JsonStructure.class);
185+
// it is also possible to retrieve the raw JSON payload
186+
String userJson = row.getString("user");
187+
// retrieve the JSON payload and convert it to a JsonObject instance
188+
JsonObject scores = (JsonObject) row.get("scores", JsonStructure.class);
189+
// it is also possible to retrieve the raw JSON payload
190+
String scoresJson = row.getString("scores");
191+
System.out.printf("Retrieved row:%n" +
192+
"id %d%n" +
193+
"user %s%n" +
194+
"user (raw) %s%n" +
195+
"scores %s%n" +
196+
"scores (raw) %s%n%n",
197+
id, user, userJson, scores, scoresJson);
198+
}
199+
}
200+
201+
}

0 commit comments

Comments
 (0)