Skip to content

Commit 1d00a53

Browse files
authored
Merge pull request #586 from zhenlineo/2.0-rx-examples
Added more examples to show how to use the new React API
2 parents 390f59e + 875f327 commit 1d00a53

File tree

6 files changed

+316
-1
lines changed

6 files changed

+316
-1
lines changed

examples/pom.xml

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,14 @@
2828
<artifactId>neo4j-java-driver</artifactId>
2929
<version>${project.version}</version>
3030
</dependency>
31+
<dependency>
32+
<groupId>io.projectreactor</groupId>
33+
<artifactId>reactor-core</artifactId>
34+
</dependency>
35+
<dependency>
36+
<groupId>io.reactivex.rxjava2</groupId>
37+
<artifactId>rxjava</artifactId>
38+
</dependency>
3139

3240
<!-- Test dependencies -->
3341
<dependency>
Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
1+
/*
2+
* Copyright (c) 2002-2019 "Neo4j,"
3+
* Neo4j Sweden AB [http://neo4j.com]
4+
*
5+
* This file is part of Neo4j.
6+
*
7+
* Licensed under the Apache License, Version 2.0 (the "License");
8+
* you may not use this file except in compliance with the License.
9+
* You may obtain a copy of the License at
10+
*
11+
* http://www.apache.org/licenses/LICENSE-2.0
12+
*
13+
* Unless required by applicable law or agreed to in writing, software
14+
* distributed under the License is distributed on an "AS IS" BASIS,
15+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16+
* See the License for the specific language governing permissions and
17+
* limitations under the License.
18+
*/
19+
package org.neo4j.docs.driver;
20+
21+
import io.reactivex.Flowable;
22+
import reactor.core.publisher.Flux;
23+
24+
import java.util.Collections;
25+
import java.util.Map;
26+
27+
import org.neo4j.driver.reactive.RxSession;
28+
29+
public class RxAutocommitTransactionExample extends BaseApplication
30+
{
31+
public RxAutocommitTransactionExample( String uri, String user, String password )
32+
{
33+
super( uri, user, password );
34+
}
35+
36+
public Flux<String> readProductTitlesReactor()
37+
{
38+
// tag::reactor-autocommit-transaction[]
39+
String query = "MATCH (p:Product) WHERE p.id = $id RETURN p.title";
40+
Map<String,Object> parameters = Collections.singletonMap( "id", 0 );
41+
42+
return Flux.using( driver::rxSession,
43+
session -> Flux.from( session.run( query, parameters ).records() ).map( record -> record.get( 0 ).asString() ),
44+
RxSession::close );
45+
// end::reactor-autocommit-transaction[]
46+
}
47+
48+
public Flowable<String> readProductTitlesRxJava()
49+
{
50+
// tag::RxJava-autocommit-transaction[]
51+
String query = "MATCH (p:Product) WHERE p.id = $id RETURN p.title";
52+
Map<String,Object> parameters = Collections.singletonMap( "id", 0 );
53+
54+
return Flowable.using( driver::rxSession,
55+
session -> Flowable.fromPublisher( session.run( query, parameters ).records() ).map( record -> record.get( 0 ).asString() ),
56+
RxSession::close );
57+
// end::RxJava-autocommit-transaction[]
58+
}
59+
}
Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,66 @@
1+
/*
2+
* Copyright (c) 2002-2019 "Neo4j,"
3+
* Neo4j Sweden AB [http://neo4j.com]
4+
*
5+
* This file is part of Neo4j.
6+
*
7+
* Licensed under the Apache License, Version 2.0 (the "License");
8+
* you may not use this file except in compliance with the License.
9+
* You may obtain a copy of the License at
10+
*
11+
* http://www.apache.org/licenses/LICENSE-2.0
12+
*
13+
* Unless required by applicable law or agreed to in writing, software
14+
* distributed under the License is distributed on an "AS IS" BASIS,
15+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16+
* See the License for the specific language governing permissions and
17+
* limitations under the License.
18+
*/
19+
package org.neo4j.docs.driver;
20+
21+
import io.reactivex.Flowable;
22+
import reactor.core.publisher.Flux;
23+
24+
import java.util.Collections;
25+
import java.util.Map;
26+
27+
import org.neo4j.driver.reactive.RxSession;
28+
import org.neo4j.driver.reactive.RxTransaction;
29+
30+
public class RxExplicitTransactionExample extends BaseApplication
31+
{
32+
public RxExplicitTransactionExample( String uri, String user, String password )
33+
{
34+
super( uri, user, password );
35+
}
36+
37+
public Flux<String> readSingleProductReactor()
38+
{
39+
// tag::reactor-explicit-transaction[]
40+
String query = "MATCH (p:Product) WHERE p.id = $id RETURN p.title";
41+
Map<String,Object> parameters = Collections.singletonMap( "id", 0 );
42+
43+
RxSession session = driver.rxSession();
44+
// It is recommended to use Flux.usingWhen for explicit transactions and Flux.using for autocommit transactions (session).
45+
// This is because an explicit transaction needs to be supplied via a another resource publisher session.beginTransaction.
46+
return Flux.usingWhen( session.beginTransaction(),
47+
tx -> Flux.from( tx.run( query, parameters ).records() ).map( record -> record.get( 0 ).asString() ),
48+
RxTransaction::commit,
49+
RxTransaction::rollback );
50+
// end::reactor-explicit-transaction[]
51+
}
52+
53+
public Flowable<String> readSingleProductRxJava()
54+
{
55+
// tag::RxJava-explicit-transaction[]
56+
String query = "MATCH (p:Product) WHERE p.id = $id RETURN p.title";
57+
Map<String,Object> parameters = Collections.singletonMap( "id", 0 );
58+
59+
RxSession session = driver.rxSession();
60+
return Flowable.fromPublisher( session.beginTransaction() )
61+
.flatMap( tx -> Flowable.fromPublisher( tx.run( query, parameters ).records() ).map( record -> record.get( 0 ).asString() )
62+
.doOnComplete( tx::commit )
63+
.doOnError( error -> tx.rollback() ) );
64+
// end::RxJava-explicit-transaction[]
65+
}
66+
}
Lines changed: 70 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,70 @@
1+
/*
2+
* Copyright (c) 2002-2019 "Neo4j,"
3+
* Neo4j Sweden AB [http://neo4j.com]
4+
*
5+
* This file is part of Neo4j.
6+
*
7+
* Licensed under the Apache License, Version 2.0 (the "License");
8+
* you may not use this file except in compliance with the License.
9+
* You may obtain a copy of the License at
10+
*
11+
* http://www.apache.org/licenses/LICENSE-2.0
12+
*
13+
* Unless required by applicable law or agreed to in writing, software
14+
* distributed under the License is distributed on an "AS IS" BASIS,
15+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16+
* See the License for the specific language governing permissions and
17+
* limitations under the License.
18+
*/
19+
package org.neo4j.docs.driver;
20+
21+
import io.reactivex.Flowable;
22+
import reactor.core.publisher.Flux;
23+
import reactor.core.publisher.Mono;
24+
25+
import java.util.Collections;
26+
import java.util.Map;
27+
28+
import org.neo4j.driver.reactive.RxResult;
29+
import org.neo4j.driver.reactive.RxSession;
30+
import org.neo4j.driver.summary.ResultSummary;
31+
32+
public class RxTransactionFunctionExample extends BaseApplication
33+
{
34+
public RxTransactionFunctionExample( String uri, String user, String password )
35+
{
36+
super( uri, user, password );
37+
}
38+
39+
public Flux<ResultSummary> printAllProductsReactor()
40+
{
41+
// tag::reactor-transaction-function[]
42+
String query = "MATCH (p:Product) WHERE p.id = $id RETURN p.title";
43+
Map<String,Object> parameters = Collections.singletonMap( "id", 0 );
44+
45+
46+
return Flux.using( driver::rxSession, session -> session.readTransaction( tx -> {
47+
RxResult result = tx.run( query, parameters );
48+
return Flux.from( result.records() )
49+
.doOnNext( record -> System.out.println( record.get( 0 ).asString() ) ).then( Mono.from( result.summary() ) );
50+
}
51+
), RxSession::close );
52+
// end::reactor-transaction-function[]
53+
}
54+
55+
public Flowable<ResultSummary> printAllProductsRxJava()
56+
{
57+
// tag::RxJava-transaction-function[]
58+
String query = "MATCH (p:Product) WHERE p.id = $id RETURN p.title";
59+
Map<String,Object> parameters = Collections.singletonMap( "id", 0 );
60+
61+
62+
return Flowable.using( driver::rxSession, session -> session.readTransaction( tx -> {
63+
RxResult result = tx.run( query, parameters );
64+
return Flowable.fromPublisher( result.records() )
65+
.doOnNext( record -> System.out.println( record.get( 0 ).asString() ) ).ignoreElements().andThen( result.summary() );
66+
}
67+
), RxSession::close );
68+
// end::RxJava-transaction-function[]
69+
}
70+
}

examples/src/test/java/org/neo4j/docs/driver/ExamplesIT.java

Lines changed: 106 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@
2323
import org.junit.jupiter.api.extension.RegisterExtension;
2424
import org.junit.jupiter.api.parallel.Execution;
2525
import org.junit.jupiter.api.parallel.ExecutionMode;
26+
import reactor.core.publisher.Flux;
2627

2728
import java.nio.file.Files;
2829
import java.nio.file.Path;
@@ -32,9 +33,10 @@
3233
import java.util.Set;
3334
import java.util.UUID;
3435

35-
import org.neo4j.driver.internal.util.ServerVersion;
3636
import org.neo4j.driver.Session;
3737
import org.neo4j.driver.Value;
38+
import org.neo4j.driver.internal.util.EnabledOnNeo4jWith;
39+
import org.neo4j.driver.internal.util.ServerVersion;
3840
import org.neo4j.driver.summary.ResultSummary;
3941
import org.neo4j.driver.summary.StatementType;
4042
import org.neo4j.driver.util.DatabaseExtension;
@@ -54,6 +56,7 @@
5456
import static org.junit.jupiter.api.Assertions.assertEquals;
5557
import static org.junit.jupiter.api.Assertions.assertTrue;
5658
import static org.neo4j.driver.Values.parameters;
59+
import static org.neo4j.driver.internal.util.Neo4jFeature.BOLT_V4;
5760
import static org.neo4j.driver.util.Neo4jRunner.PASSWORD;
5861
import static org.neo4j.driver.util.Neo4jRunner.USER;
5962
import static org.neo4j.driver.util.TestUtil.await;
@@ -488,4 +491,106 @@ void testHostnameVerificationExample()
488491
assertTrue( example.canConnect() );
489492
}
490493
}
494+
495+
@Test
496+
@EnabledOnNeo4jWith( BOLT_V4 )
497+
void testShouldRunRxAutocommitTransactionExample() throws Exception
498+
{
499+
try ( RxAutocommitTransactionExample example = new RxAutocommitTransactionExample( uri, USER, PASSWORD ) )
500+
{
501+
// create some 'Product' nodes
502+
try ( Session session = neo4j.driver().session() )
503+
{
504+
session.run(
505+
"UNWIND ['Tesseract', 'Orb', 'Eye of Agamotto'] AS item " +
506+
"CREATE (:Product {id: 0, title: item})" );
507+
}
508+
509+
// read all 'Product' nodes
510+
List<String> titles = await( example.readProductTitlesReactor() );
511+
assertEquals( new HashSet<>( asList( "Tesseract", "Orb", "Eye of Agamotto" ) ), new HashSet<>( titles ) );
512+
513+
titles = await( example.readProductTitlesRxJava() );
514+
assertEquals( new HashSet<>( asList( "Tesseract", "Orb", "Eye of Agamotto" ) ), new HashSet<>( titles ) );
515+
}
516+
}
517+
518+
@Test
519+
@EnabledOnNeo4jWith( BOLT_V4 )
520+
void testRxExplicitTransactionExample() throws Exception
521+
{
522+
try ( RxExplicitTransactionExample example = new RxExplicitTransactionExample( uri, USER, PASSWORD ) )
523+
{
524+
// create a 'Product' node
525+
try ( Session session = neo4j.driver().session() )
526+
{
527+
session.run( "CREATE (:Product {id: 0, title: 'Mind Gem'})" );
528+
}
529+
530+
List<String> products = await( example.readSingleProductReactor() );
531+
assertEquals( 1, products.size() );
532+
assertEquals( "Mind Gem", products.get( 0 ) );
533+
534+
products = await( example.readSingleProductRxJava() );
535+
assertEquals( 1, products.size() );
536+
assertEquals( "Mind Gem", products.get( 0 ) );
537+
538+
}
539+
}
540+
541+
@Test
542+
@EnabledOnNeo4jWith( BOLT_V4 )
543+
void testShouldRunRxTransactionFunctionExampleReactor() throws Exception
544+
{
545+
try ( RxTransactionFunctionExample example = new RxTransactionFunctionExample( uri, USER, PASSWORD ) )
546+
{
547+
// create some 'Product' nodes
548+
try ( Session session = neo4j.driver().session() )
549+
{
550+
session.run(
551+
"UNWIND ['Infinity Gauntlet', 'Mjölnir'] AS item " +
552+
"CREATE (:Product {id: 0, title: item})" );
553+
}
554+
555+
StdIOCapture stdIOCapture = new StdIOCapture();
556+
557+
// print all 'Product' nodes to fake stdout
558+
try ( AutoCloseable ignore = stdIOCapture.capture() )
559+
{
560+
ResultSummary summary = await( Flux.from( example.printAllProductsReactor() ).single() );
561+
assertEquals( StatementType.READ_ONLY, summary.statementType() );
562+
}
563+
564+
Set<String> capturedOutput = new HashSet<>( stdIOCapture.stdout() );
565+
assertEquals( new HashSet<>( asList( "Infinity Gauntlet", "Mjölnir" ) ), capturedOutput );
566+
}
567+
}
568+
569+
@Test
570+
@EnabledOnNeo4jWith( BOLT_V4 )
571+
void testShouldRunRxTransactionFunctionExampleRxJava() throws Exception
572+
{
573+
try ( RxTransactionFunctionExample example = new RxTransactionFunctionExample( uri, USER, PASSWORD ) )
574+
{
575+
// create some 'Product' nodes
576+
try ( Session session = neo4j.driver().session() )
577+
{
578+
session.run(
579+
"UNWIND ['Infinity Gauntlet', 'Mjölnir'] AS item " +
580+
"CREATE (:Product {id: 0, title: item})" );
581+
}
582+
583+
StdIOCapture stdIOCapture = new StdIOCapture();
584+
585+
// print all 'Product' nodes to fake stdout
586+
try ( AutoCloseable ignore = stdIOCapture.capture() )
587+
{
588+
ResultSummary summary = await( Flux.from( example.printAllProductsRxJava() ).single() );
589+
assertEquals( StatementType.READ_ONLY, summary.statementType() );
590+
}
591+
592+
Set<String> capturedOutput = new HashSet<>( stdIOCapture.stdout() );
593+
assertEquals( new HashSet<>( asList( "Infinity Gauntlet", "Mjölnir" ) ), capturedOutput );
594+
}
595+
}
491596
}

pom.xml

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -71,6 +71,13 @@
7171
<artifactId>reactor-core</artifactId>
7272
<version>3.2.6.RELEASE</version>
7373
</dependency>
74+
<!--Compile dependencies only used by Examples-->
75+
<dependency>
76+
<groupId>io.reactivex.rxjava2</groupId>
77+
<artifactId>rxjava</artifactId>
78+
<version>2.2.8</version>
79+
</dependency>
80+
7481
<!-- Optional dependencies -->
7582
<dependency>
7683
<groupId>org.slf4j</groupId>

0 commit comments

Comments
 (0)