Skip to content

Commit 218b7d9

Browse files
committed
Refactor code to use an internal connection pool
1 parent 4a56d1e commit 218b7d9

File tree

6 files changed

+496
-100
lines changed

6 files changed

+496
-100
lines changed

README.md

Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -61,24 +61,24 @@ import redis.clients.jedis.Jedis;
6161
import com.redislabs.modules.rejson.JReJSON;
6262

6363
// First get a connection
64-
Jedis jedis = new Jedis("localhost", 6379);
64+
JReJSON client = new JReJSON("localhost", 6379);
6565

6666
// Setting a Redis key name _foo_ to the string _"bar"_, and reading it back
67-
JReJSON.set(jedis,"foo", "bar");
68-
String s0 = (String) JReJSON.get(jedis,"foo");
67+
client.set("foo", "bar");
68+
String s0 = (String) client.get("foo");
6969

7070
// Omitting the path (usually) defaults to the root path, so the call above to
7171
// `get()` and the following ones // are basically interchangeable
72-
String s1 = (String) JReJSON.get(jedis,"foo", new Path("."));
73-
String s2 = (String) JReJSON.get(jedis, "foo", Path.RootPath());
72+
String s1 = (String) client.get("foo", new Path("."));
73+
String s2 = (String) client.get("foo", Path.ROOT_PATH);
7474

7575
// Any Gson-able object can be set and updated
76-
JReJSON.set(jedis,"obj", new Object()); // just an empty object
77-
JReJSON.set(jedis,"obj", null, new Path(".zilch"));
76+
client.set("obj", new Object()); // just an empty object
77+
client.set("obj", null, new Path(".zilch"));
7878
Path p = new Path(".whatevs");
79-
JReJSON.set(jedis,"obj", true, p);
80-
JReJSON.set(jedis,"obj", 42, p);
81-
JReJSON.del(jedis,"obj", p); // back to almost nothing
79+
client.set("obj", true, p);
80+
client.set("obj", 42, p);
81+
client.del("obj", p); // back to almost nothing
8282

8383
```
8484

pom.xml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66

77
<groupId>com.redislabs</groupId>
88
<artifactId>jrejson</artifactId>
9-
<version>1.0.0</version>
9+
<version>1.1.0-SNAPSHOT</version>
1010

1111
<name>JReJSON</name>
1212
<description>Official client for ReJSON</description>

src/main/java/com/redislabs/modules/rejson/JReJSON.java

Lines changed: 225 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -29,8 +29,11 @@
2929
package com.redislabs.modules.rejson;
3030

3131
import com.google.gson.Gson;
32+
3233
import redis.clients.jedis.Jedis;
34+
import redis.clients.jedis.JedisPool;
3335
import redis.clients.jedis.commands.ProtocolCommand;
36+
import redis.clients.jedis.util.Pool;
3437
import redis.clients.jedis.util.SafeEncoder;
3538

3639
import java.util.ArrayList;
@@ -41,7 +44,7 @@
4144
*/
4245
public class JReJSON {
4346

44-
private static Gson gson = new Gson();
47+
private static final Gson gson = new Gson();
4548

4649
private enum Command implements ProtocolCommand {
4750
DEL("JSON.DEL"),
@@ -77,6 +80,34 @@ public byte[] getRaw() {
7780
}
7881
}
7982

83+
private Pool<Jedis> client;
84+
85+
/**
86+
* Creates a client to the local machine
87+
*/
88+
public JReJSON() {
89+
this("localhost", 6379);
90+
}
91+
92+
/**
93+
* Creates a client to the specific host/post
94+
*
95+
* @param host Redis host
96+
* @param port Redis port
97+
*/
98+
public JReJSON(String host, int port) {
99+
this(new JedisPool(host, port));
100+
}
101+
102+
/**
103+
* Creates a client using provided Jedis pool
104+
*
105+
* @param jedis bring your own Jedis pool
106+
*/
107+
public JReJSON(Pool<Jedis> jedis) {
108+
this.client = jedis;
109+
}
110+
80111
/**
81112
* Helper to check for errors and throw them as an exception
82113
* @param str the reply string to "analyze"
@@ -103,27 +134,197 @@ private static void assertReplyOK(final String str) {
103134
*/
104135
private static Path getSingleOptionalPath(Path... path) {
105136
// check for 0, 1 or more paths
106-
if (1 > path.length)
107-
// default to root
137+
if (1 > path.length) { // default to root
108138
return Path.RootPath();
109-
else if (1 == path.length)
110-
// take 1
139+
}
140+
if (1 == path.length) { // take 1
111141
return path[0];
112-
else
113-
// throw out the baby with the water
114-
throw new RuntimeException("Only a single optional path is allowed");
142+
}
143+
144+
// throw out the baby with the water
145+
throw new RuntimeException("Only a single optional path is allowed");
146+
}
147+
148+
/**
149+
* Deletes the root path
150+
* @param key the key name
151+
* @return the number of paths deleted (0 or 1)
152+
*/
153+
public Long del(String key) {
154+
return del(key, Path.ROOT_PATH);
155+
}
156+
157+
158+
/**
159+
* Deletes a path
160+
* @param key the key name
161+
* @param path optional single path in the object, defaults to root
162+
* @return path deleted
163+
*/
164+
public Long del(String key, Path path) {
165+
byte[][] args = new byte[2][];
166+
args[0] = SafeEncoder.encode(key);
167+
args[1] = SafeEncoder.encode(path.toString());
168+
169+
try (Jedis conn = getConnection()) {
170+
conn.getClient().sendCommand(Command.DEL, args);
171+
return conn.getClient().getIntegerReply();
172+
}
173+
}
174+
175+
/**
176+
* Gets an object at the root path
177+
* @param key the key name
178+
* @return the requested object
179+
*/
180+
public Object get(String key) {
181+
return get(key, Path.ROOT_PATH);
182+
}
183+
184+
/**
185+
* Gets an object
186+
* @param key the key name
187+
* @param paths optional one ore more paths in the object
188+
* @return the requested object
189+
*/
190+
public Object get(String key, Path... paths) {
191+
byte[][] args = new byte[1 + paths.length][];
192+
int i=0;
193+
args[i] = SafeEncoder.encode(key);
194+
for (Path p :paths) {
195+
args[++i] = SafeEncoder.encode(p.toString());
196+
}
197+
198+
String rep;
199+
try (Jedis conn = getConnection()) {
200+
conn.getClient().sendCommand(Command.GET, args);
201+
rep = conn.getClient().getBulkReply();
202+
}
203+
assertReplyNotError(rep);
204+
return gson.fromJson(rep, Object.class);
205+
}
206+
207+
/**
208+
* Sets an object at the root path
209+
* @param key the key name
210+
* @param object the Java object to store
211+
* @param flag an existential modifier
212+
*/
213+
public void set(String key, Object object, ExistenceModifier flag) {
214+
set(key, object, flag, Path.ROOT_PATH);
215+
}
216+
217+
/**
218+
* Sets an object in the root path
219+
* @param key the key name
220+
* @param object the Java object to store
221+
* @param path in the object
222+
*/
223+
public void set(String key, Object object) {
224+
set(key, object, ExistenceModifier.DEFAULT, Path.ROOT_PATH);
225+
}
226+
227+
/**
228+
* Sets an object without caring about target path existing
229+
* @param key the key name
230+
* @param object the Java object to store
231+
* @param path in the object
232+
*/
233+
public void set(String key, Object object, Path path) {
234+
set(key, object, ExistenceModifier.DEFAULT, path);
235+
}
236+
237+
/**
238+
* Sets an object
239+
* @param key the key name
240+
* @param object the Java object to store
241+
* @param flag an existential modifier
242+
* @param path in the object
243+
*/
244+
public void set(String key, Object object, ExistenceModifier flag, Path path) {
245+
246+
List<byte[]> args = new ArrayList<>(4);
247+
248+
args.add(SafeEncoder.encode(key));
249+
args.add(SafeEncoder.encode(path.toString()));
250+
args.add(SafeEncoder.encode(gson.toJson(object)));
251+
if (ExistenceModifier.DEFAULT != flag) {
252+
args.add(flag.getRaw());
253+
}
254+
255+
String status;
256+
try (Jedis conn = getConnection()) {
257+
conn.getClient()
258+
.sendCommand(Command.SET, args.toArray(new byte[args.size()][]));
259+
status = conn.getClient().getStatusCodeReply();
260+
}
261+
assertReplyOK(status);
262+
}
263+
264+
/**
265+
* Gets the class of an object at the root path
266+
* @param key the key name
267+
* @return the Java class of the requested object
268+
*/
269+
public Class<?> type(String key) {
270+
return type(key);
271+
}
272+
273+
/**
274+
* Gets the class of an object
275+
* @param key the key name
276+
* @param path a path in the object
277+
* @return the Java class of the requested object
278+
*/
279+
public Class<?> type(String key, Path path) {
280+
281+
List<byte[]> args = new ArrayList<>(2);
282+
283+
args.add(SafeEncoder.encode(key));
284+
args.add(SafeEncoder.encode(path.toString()));
285+
286+
String rep;
287+
try (Jedis conn = getConnection()) {
288+
conn.getClient()
289+
.sendCommand(Command.TYPE, args.toArray(new byte[args.size()][]));
290+
rep = conn.getClient().getBulkReply();
291+
}
292+
293+
assertReplyNotError(rep);
294+
295+
switch (rep) {
296+
case "null":
297+
return null;
298+
case "boolean":
299+
return boolean.class;
300+
case "integer":
301+
return int.class;
302+
case "number":
303+
return float.class;
304+
case "string":
305+
return String.class;
306+
case "object":
307+
return Object.class;
308+
case "array":
309+
return List.class;
310+
default:
311+
throw new java.lang.RuntimeException(rep);
312+
}
115313
}
314+
116315

117316
/**
118317
* Deletes a path
119318
* @param conn the Jedis connection
120319
* @param key the key name
121320
* @param path optional single path in the object, defaults to root
122321
* @return the number of paths deleted (0 or 1)
322+
* @deprecated use {@link #del(String, Path...)} instead
123323
*/
324+
@Deprecated
124325
public static Long del(Jedis conn, String key, Path... path) {
125326

126-
List<byte[]> args = new ArrayList(2);
327+
List<byte[]> args = new ArrayList<>(2);
127328

128329
args.add(SafeEncoder.encode(key));
129330
args.add(SafeEncoder.encode(getSingleOptionalPath(path).toString()));
@@ -142,10 +343,12 @@ public static Long del(Jedis conn, String key, Path... path) {
142343
* @param key the key name
143344
* @param paths optional one ore more paths in the object, defaults to root
144345
* @return the requested object
346+
* @deprecated use {@link #get(String, Path...)} instead
145347
*/
348+
@Deprecated
146349
public static Object get(Jedis conn, String key, Path... paths) {
147350

148-
List<byte[]> args = new ArrayList(2);
351+
List<byte[]> args = new ArrayList<>(2);
149352

150353
args.add(SafeEncoder.encode(key));
151354
for (Path p :paths) {
@@ -168,10 +371,12 @@ public static Object get(Jedis conn, String key, Path... paths) {
168371
* @param object the Java object to store
169372
* @param flag an existential modifier
170373
* @param path optional single path in the object, defaults to root
374+
* @deprecated use {@link #set(String, Object, ExistenceModifier, Path...)} instead
171375
*/
376+
@Deprecated
172377
public static void set(Jedis conn, String key, Object object, ExistenceModifier flag, Path... path) {
173378

174-
List<byte[]> args = new ArrayList(4);
379+
List<byte[]> args = new ArrayList<>(4);
175380

176381
args.add(SafeEncoder.encode(key));
177382
args.add(SafeEncoder.encode(getSingleOptionalPath(path).toString()));
@@ -194,7 +399,9 @@ public static void set(Jedis conn, String key, Object object, ExistenceModifier
194399
* @param key the key name
195400
* @param object the Java object to store
196401
* @param path optional single path in the object, defaults to root
402+
* @deprecated use {@link #set(String, Object, ExistenceModifier, Path...)} instead
197403
*/
404+
@Deprecated
198405
public static void set(Jedis conn, String key, Object object, Path... path) {
199406
set(conn,key, object, ExistenceModifier.DEFAULT, path);
200407
}
@@ -205,10 +412,12 @@ public static void set(Jedis conn, String key, Object object, Path... path) {
205412
* @param key the key name
206413
* @param path optional single path in the object, defaults to root
207414
* @return the Java class of the requested object
415+
* @deprecated use {@link #type(String, Path...)} instead
208416
*/
417+
@Deprecated
209418
public static Class<?> type(Jedis conn, String key, Path... path) {
210419

211-
List<byte[]> args = new ArrayList(2);
420+
List<byte[]> args = new ArrayList<>(2);
212421

213422
args.add(SafeEncoder.encode(key));
214423
args.add(SafeEncoder.encode(getSingleOptionalPath(path).toString()));
@@ -239,4 +448,8 @@ public static Class<?> type(Jedis conn, String key, Path... path) {
239448
throw new java.lang.RuntimeException(rep);
240449
}
241450
}
451+
452+
private Jedis getConnection() {
453+
return this.client.getResource();
454+
}
242455
}

src/main/java/com/redislabs/modules/rejson/Path.java

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -30,10 +30,11 @@
3030

3131
/**
3232
* Path is a ReJSON path, representing a valid path into an object
33-
* TODO: make path building even more fun
3433
*/
35-
3634
public class Path {
35+
36+
public static final Path ROOT_PATH = new Path(".");
37+
3738
private final String strPath;
3839

3940
public Path(final String strPath) {
@@ -43,7 +44,9 @@ public Path(final String strPath) {
4344
/**
4445
* Makes a root path
4546
* @return the root path
47+
* @deprecated use {@value #ROOT_PATH} instead
4648
*/
49+
@Deprecated
4750
public static Path RootPath() {
4851
return new Path(".");
4952
}

0 commit comments

Comments
 (0)