19
19
package org .neo4j .docs .driver ;
20
20
import io .reactivex .Flowable ;
21
21
// tag::reactor-unmanaged-transaction-import[]
22
+ import io .reactivex .Observable ;
23
+ import org .reactivestreams .Publisher ;
22
24
import reactor .core .publisher .Flux ;
25
+ import reactor .core .publisher .Mono ;
23
26
24
27
import java .util .Collections ;
25
28
import java .util .Map ;
26
29
30
+ import org .neo4j .driver .reactive .RxQueryRunner ;
27
31
import org .neo4j .driver .reactive .RxSession ;
28
- import org . neo4j . driver . reactive . RxTransaction ;
32
+
29
33
// tag::reactor-unmanaged-transaction-import[]
30
34
public class RxUnmanagedTransactionExample extends BaseApplication
31
35
{
@@ -35,15 +39,41 @@ public RxUnmanagedTransactionExample(String uri, String user, String password )
35
39
}
36
40
37
41
// tag::reactor-unmanaged-transaction[]
42
+ static class QueryRunnerAndCallbacks
43
+ {
44
+ final RxQueryRunner queryRunner ;
45
+
46
+ final Publisher <Void > commit ;
47
+ final Publisher <Void > rollback ;
48
+
49
+ QueryRunnerAndCallbacks ( RxQueryRunner queryRunner , Publisher <Void > commit , Publisher <Void > rollback )
50
+ {
51
+ this .queryRunner = queryRunner ;
52
+ this .commit = commit ;
53
+ this .rollback = rollback ;
54
+ }
55
+ }
56
+
38
57
public Flux <String > readSingleProduct ()
39
58
{
40
59
String query = "MATCH (p:Product) WHERE p.id = $id RETURN p.title" ;
41
60
Map <String ,Object > parameters = Collections .singletonMap ( "id" , 0 );
42
61
43
- RxSession session = driver .rxSession ();
44
- return Flux .usingWhen ( session .beginTransaction (),
45
- tx -> Flux .from ( tx .run ( query , parameters ).records () ).map ( record -> record .get ( 0 ).asString () ),
46
- RxTransaction ::commit , ( tx , error ) -> tx .rollback (), null );
62
+ // The additional holder is required to make both usingWhen constructs close
63
+ // the resources in the correct order.
64
+ Mono <QueryRunnerAndCallbacks > queryRunnerSupplier = Mono .using (
65
+ driver ::rxSession ,
66
+ session -> Mono .from ( session .beginTransaction () ).map (tx -> new QueryRunnerAndCallbacks ( tx , tx .commit (), tx .rollback () ) ),
67
+ RxSession ::close
68
+ );
69
+
70
+ return Flux .usingWhen (
71
+ queryRunnerSupplier ,
72
+ queryRunnerAndCallbacks -> Flux .from ( queryRunnerAndCallbacks .queryRunner .run ( query , parameters ).records () ).map ( record -> record .get ( 0 ).asString () ),
73
+ queryRunnerAndCallbacks -> queryRunnerAndCallbacks .commit ,
74
+ (queryRunnerAndCallbacks , error ) -> queryRunnerAndCallbacks .rollback ,
75
+ queryRunnerAndCallbacks -> queryRunnerAndCallbacks .rollback
76
+ );
47
77
}
48
78
// end::reactor-unmanaged-transaction[]
49
79
@@ -53,16 +83,20 @@ public Flowable<String> readSingleProductRxJava()
53
83
String query = "MATCH (p:Product) WHERE p.id = $id RETURN p.title" ;
54
84
Map <String ,Object > parameters = Collections .singletonMap ( "id" , 0 );
55
85
56
- RxSession session = driver .rxSession ();
57
- return Flowable .fromPublisher ( session .beginTransaction () )
58
- .flatMap ( tx ->
59
- Flowable .fromPublisher ( tx .run ( query , parameters ).records () )
60
- .map ( record -> record .get ( 0 ).asString () )
61
- .concatWith ( tx .commit () )
62
- .onErrorResumeNext ( error -> {
63
- // We rollback and rethrow the error. For a real application, you may want to handle the error directly here
64
- return Flowable .<String >fromPublisher ( tx .rollback () ).concatWith ( Flowable .error ( error ) );
65
- } ) );
86
+ return Flowable .using (
87
+ driver ::rxSession ,
88
+ session -> Flowable .fromPublisher ( session .beginTransaction () )
89
+ .flatMap ( tx ->
90
+ Flowable .fromPublisher ( tx .run ( query , parameters ).records () )
91
+ .map ( record -> record .get ( 0 ).asString () )
92
+ .concatWith ( tx .commit () )
93
+ .onErrorResumeNext ( error -> {
94
+ // We rollback and rethrow the error. For a real application, you may want to handle the error directly here
95
+ return Flowable .<String >fromPublisher ( tx .rollback () ).concatWith ( Flowable .error ( error ) );
96
+ } )
97
+ ),
98
+ session -> Observable .fromPublisher (session .close ()).onErrorResumeNext ( Observable .empty () ).subscribe ()
99
+ );
66
100
}
67
101
// end::RxJava-unmanaged-transaction[]
68
102
}
0 commit comments