Skip to content

Commit 325f13a

Browse files
author
Alexandre Dutra
committed
JAVA-1458: Check thread in mapper sync methods
This commit has substantial contributions by Greg Bestland (@GregBestland).
1 parent 24cc847 commit 325f13a

3 files changed

Lines changed: 180 additions & 12 deletions

File tree

changelog/README.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414
- [documentation] JAVA-1445: Clarify how nodes are penalized in LatencyAwarePolicy docs.
1515
- [improvement] JAVA-1446: Support 'DEFAULT UNSET' in Query Builder JSON Insert.
1616
- [improvement] JAVA-1443: Add groupBy method to Select statement.
17+
- [improvement] JAVA-1458: Check thread in mapper sync methods.
1718

1819

1920
### 3.2.0

driver-mapping/src/main/java/com/datastax/driver/mapping/Mapper.java

Lines changed: 48 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -171,15 +171,18 @@ public MappingManager getManager() {
171171
* Creates a query that can be used to save the provided entity.
172172
* <p/>
173173
* This method is useful if you want to setup a number of options (tracing,
174-
* conistency level, ...) of the returned statement before executing it manually
174+
* consistency level, ...) of the returned statement before executing it manually
175175
* or need access to the {@code ResultSet} object after execution (to get the
176176
* trace, the execution info, ...), but in other cases, calling {@link #save}
177177
* or {@link #saveAsync} is shorter.
178+
* <p/>
179+
* Note: this method might block if the query is not prepared yet.
178180
*
179181
* @param entity the entity to save.
180-
* @return a query that saves {@code entity} (based on it's defined mapping).
182+
* @return a query that saves {@code entity} (based on its defined mapping).
181183
*/
182184
public Statement saveQuery(T entity) {
185+
checkNotInEventLoop();
183186
try {
184187
return Uninterruptibles.getUninterruptibly(saveQueryAsync(entity, this.defaultSaveOptions));
185188
} catch (ExecutionException e) {
@@ -191,7 +194,7 @@ public Statement saveQuery(T entity) {
191194
* Creates a query that can be used to save the provided entity.
192195
* <p/>
193196
* This method is useful if you want to setup a number of options (tracing,
194-
* conistency level, ...) of the returned statement before executing it manually
197+
* consistency level, ...) of the returned statement before executing it manually
195198
* or need access to the {@code ResultSet} object after execution (to get the
196199
* trace, the execution info, ...), but in other cases, calling {@link #save}
197200
* or {@link #saveAsync} is shorter.
@@ -203,11 +206,13 @@ public Statement saveQuery(T entity) {
203206
* <li>Consistency level</li>
204207
* <li>Tracing</li>
205208
* </ul>
209+
* Note: this method might block if the query is not prepared yet.
206210
*
207211
* @param entity the entity to save.
208-
* @return a query that saves {@code entity} (based on it's defined mapping).
212+
* @return a query that saves {@code entity} (based on its defined mapping).
209213
*/
210214
public Statement saveQuery(T entity, Option... options) {
215+
checkNotInEventLoop();
211216
try {
212217
return Uninterruptibles.getUninterruptibly(saveQueryAsync(entity, toMapWithDefaults(options, this.defaultSaveOptions)));
213218
} catch (ExecutionException e) {
@@ -271,10 +276,13 @@ else if (customCodec != null)
271276
* Saves an entity mapped by this mapper.
272277
* <p/>
273278
* This method is basically equivalent to: {@code getManager().getSession().execute(saveQuery(entity))}.
279+
* <p/>
280+
* Note: this method will block until the entity is fully saved.
274281
*
275282
* @param entity the entity to save.
276283
*/
277284
public void save(T entity) {
285+
checkNotInEventLoop();
278286
try {
279287
Uninterruptibles.getUninterruptibly(saveAsync(entity));
280288
} catch (ExecutionException e) {
@@ -292,11 +300,13 @@ public void save(T entity) {
292300
* <li>Consistency level</li>
293301
* <li>Tracing</li>
294302
* </ul>
303+
* Note: this method will block until the entity is fully saved.
295304
*
296305
* @param entity the entity to save.
297306
* @param options the options object specified defining special options when saving.
298307
*/
299308
public void save(T entity, Option... options) {
309+
checkNotInEventLoop();
300310
try {
301311
Uninterruptibles.getUninterruptibly(saveAsync(entity, options));
302312
} catch (ExecutionException e) {
@@ -346,7 +356,7 @@ public ListenableFuture<ResultSet> apply(BoundStatement bs) throws Exception {
346356
* KEY (in the order of said primary key).
347357
* <p/>
348358
* This method is useful if you want to setup a number of options (tracing,
349-
* conistency level, ...) of the returned statement before executing it manually,
359+
* consistency level, ...) of the returned statement before executing it manually,
350360
* but in other cases, calling {@link #get} or {@link #getAsync} is shorter.
351361
* <p/>
352362
* This method allows you to provide a suite of {@link Option} to include in
@@ -355,6 +365,7 @@ public ListenableFuture<ResultSet> apply(BoundStatement bs) throws Exception {
355365
* <li>Consistency level</li>
356366
* <li>Tracing</li>
357367
* </ul>
368+
* Note: this method might block if the query is not prepared yet.
358369
*
359370
* @param objects the primary key of the entity to fetch, or more precisely
360371
* the values for the columns of said primary key in the order of the primary key.
@@ -365,6 +376,7 @@ public ListenableFuture<ResultSet> apply(BoundStatement bs) throws Exception {
365376
* at least one of those values is {@code null}.
366377
*/
367378
public Statement getQuery(Object... objects) {
379+
checkNotInEventLoop();
368380
try {
369381
return Uninterruptibles.getUninterruptibly(getQueryAsync(objects));
370382
} catch (ExecutionException e) {
@@ -422,6 +434,8 @@ public BoundStatement apply(PreparedStatement input) {
422434
* Fetch an entity based on its primary key.
423435
* <p/>
424436
* This method is basically equivalent to: {@code map(getManager().getSession().execute(getQuery(objects))).one()}.
437+
* <p/>
438+
* Note: this method will block until the entity is fully fetched.
425439
*
426440
* @param objects the primary key of the entity to fetch, or more precisely
427441
* the values for the columns of said primary key in the order of the primary key.
@@ -432,6 +446,7 @@ public BoundStatement apply(PreparedStatement input) {
432446
* at least one of those values is {@code null}.
433447
*/
434448
public T get(Object... objects) {
449+
checkNotInEventLoop();
435450
try {
436451
return Uninterruptibles.getUninterruptibly(getAsync(objects));
437452
} catch (ExecutionException e) {
@@ -474,7 +489,7 @@ public ListenableFuture<ResultSet> apply(BoundStatement bs) throws Exception {
474489
* is supported for DELETE queries.
475490
* <p/>
476491
* This method is useful if you want to setup a number of options (tracing,
477-
* conistency level, ...) of the returned statement before executing it manually
492+
* consistency level, ...) of the returned statement before executing it manually
478493
* or need access to the {@code ResultSet} object after execution (to get the
479494
* trace, the execution info, ...), but in other cases, calling {@link #delete}
480495
* or {@link #deleteAsync} is shorter.
@@ -486,13 +501,15 @@ public ListenableFuture<ResultSet> apply(BoundStatement bs) throws Exception {
486501
* <li>Consistency level</li>
487502
* <li>Tracing</li>
488503
* </ul>
504+
* Note: this method might block if the query is not prepared yet.
489505
*
490506
* @param entity the entity to delete.
491507
* @param options the options to add to the DELETE query.
492-
* @return a query that delete {@code entity} (based on it's defined mapping) with
508+
* @return a query that delete {@code entity} (based on its defined mapping) with
493509
* provided USING options.
494510
*/
495511
public Statement deleteQuery(T entity, Option... options) {
512+
checkNotInEventLoop();
496513
try {
497514
return Uninterruptibles.getUninterruptibly(deleteQueryAsync(entity, toMapWithDefaults(options, defaultDeleteOptions)));
498515
} catch (ExecutionException e) {
@@ -507,15 +524,18 @@ public Statement deleteQuery(T entity, Option... options) {
507524
* provided entity and call {@link #deleteQuery(Object...)} with it.
508525
* <p/>
509526
* This method is useful if you want to setup a number of options (tracing,
510-
* conistency level, ...) of the returned statement before executing it manually
527+
* consistency level, ...) of the returned statement before executing it manually
511528
* or need access to the {@code ResultSet} object after execution (to get the
512529
* trace, the execution info, ...), but in other cases, calling {@link #delete}
513530
* or {@link #deleteAsync} is shorter.
531+
* <p/>
532+
* Note: this method might block if the query is not prepared yet.
514533
*
515534
* @param entity the entity to delete.
516-
* @return a query that delete {@code entity} (based on it's defined mapping).
535+
* @return a query that delete {@code entity} (based on its defined mapping).
517536
*/
518537
public Statement deleteQuery(T entity) {
538+
checkNotInEventLoop();
519539
try {
520540
return Uninterruptibles.getUninterruptibly(deleteQueryAsync(entity, defaultDeleteOptions));
521541
} catch (ExecutionException e) {
@@ -533,7 +553,7 @@ public Statement deleteQuery(T entity) {
533553
* is supported for DELETE queries.
534554
* <p/>
535555
* This method is useful if you want to setup a number of options (tracing,
536-
* conistency level, ...) of the returned statement before executing it manually
556+
* consistency level, ...) of the returned statement before executing it manually
537557
* or need access to the {@code ResultSet} object after execution (to get the
538558
* trace, the execution info, ...), but in other cases, calling {@link #delete}
539559
* or {@link #deleteAsync} is shorter.
@@ -544,6 +564,7 @@ public Statement deleteQuery(T entity) {
544564
* <li>Consistency level</li>
545565
* <li>Tracing</li>
546566
* </ul>
567+
* Note: this method might block if the query is not prepared yet.
547568
*
548569
* @param objects the primary key of the entity to delete, or more precisely
549570
* the values for the columns of said primary key in the order of the primary key.
@@ -555,6 +576,7 @@ public Statement deleteQuery(T entity) {
555576
* at least one of those values is {@code null}.
556577
*/
557578
public Statement deleteQuery(Object... objects) {
579+
checkNotInEventLoop();
558580
try {
559581
return Uninterruptibles.getUninterruptibly(deleteQueryAsync(objects));
560582
} catch (ExecutionException e) {
@@ -622,10 +644,13 @@ public BoundStatement apply(PreparedStatement input) {
622644
* Deletes an entity mapped by this mapper.
623645
* <p/>
624646
* This method is basically equivalent to: {@code getManager().getSession().execute(deleteQuery(entity))}.
647+
* <p/>
648+
* Note: this method will block until the entity is fully deleted.
625649
*
626650
* @param entity the entity to delete.
627651
*/
628652
public void delete(T entity) {
653+
checkNotInEventLoop();
629654
try {
630655
Uninterruptibles.getUninterruptibly(deleteAsync(entity));
631656
} catch (ExecutionException e) {
@@ -637,11 +662,14 @@ public void delete(T entity) {
637662
* Deletes an entity mapped by this mapper using provided options.
638663
* <p/>
639664
* This method is basically equivalent to: {@code getManager().getSession().execute(deleteQuery(entity, options))}.
665+
* <p/>
666+
* Note: this method will block until the entity is fully deleted.
640667
*
641668
* @param entity the entity to delete.
642669
* @param options the options to add to the DELETE query.
643670
*/
644671
public void delete(T entity, Option... options) {
672+
checkNotInEventLoop();
645673
try {
646674
Uninterruptibles.getUninterruptibly(deleteAsync(entity, options));
647675
} catch (ExecutionException e) {
@@ -678,6 +706,8 @@ public ListenableFuture<Void> deleteAsync(T entity, Option... options) {
678706
* Deletes an entity based on its primary key.
679707
* <p/>
680708
* This method is basically equivalent to: {@code getManager().getSession().execute(deleteQuery(objects))}.
709+
* <p/>
710+
* Note: this method will block until the entity is fully deleted.
681711
*
682712
* @param objects the primary key of the entity to delete, or more precisely
683713
* the values for the columns of said primary key in the order
@@ -688,6 +718,7 @@ public ListenableFuture<Void> deleteAsync(T entity, Option... options) {
688718
* at least one of those values is {@code null}.
689719
*/
690720
public void delete(Object... objects) {
721+
checkNotInEventLoop();
691722
try {
692723
Uninterruptibles.getUninterruptibly(deleteAsync(objects));
693724
} catch (ExecutionException e) {
@@ -844,6 +875,13 @@ private static EnumMap<Option.Type, Option> toMapWithDefaults(Option[] options,
844875
return result;
845876
}
846877

878+
private void checkNotInEventLoop() {
879+
Session session = manager.getSession();
880+
if (session instanceof AbstractSession) {
881+
((AbstractSession) session).checkNotInEventLoop();
882+
}
883+
}
884+
847885
/**
848886
* An option for a mapper operation.
849887
* <p/>

0 commit comments

Comments
 (0)