├── .gitignore
├── LICENSE
├── README.md
├── crud
├── client
│ ├── .gitignore
│ ├── lombok.config
│ ├── nbactions.xml
│ ├── pom.xml
│ └── src
│ │ ├── main
│ │ ├── java
│ │ │ └── com
│ │ │ │ └── example
│ │ │ │ └── client
│ │ │ │ └── ClientApplication.java
│ │ └── resources
│ │ │ └── application.properties
│ │ └── test
│ │ └── java
│ │ └── com
│ │ └── example
│ │ └── consumer
│ │ └── ConsumerApplicationTests.java
└── server
│ ├── .gitignore
│ ├── .mvn
│ └── wrapper
│ │ ├── maven-wrapper.jar
│ │ └── maven-wrapper.properties
│ ├── mvnw
│ ├── mvnw.cmd
│ ├── pom.xml
│ └── src
│ ├── main
│ ├── java
│ │ └── com
│ │ │ └── example
│ │ │ └── demo
│ │ │ └── DemoApplication.java
│ └── resources
│ │ ├── application.properties
│ │ ├── data.sql
│ │ └── schema.sql
│ └── test
│ ├── java
│ └── com
│ │ └── example
│ │ └── demo
│ │ ├── IntegrationTests.java
│ │ └── PostRepositoryTest.java
│ └── resources
│ └── junit-platform.properties
├── docs
├── GUIDE.md
├── _config.yml
├── crud.md
├── index.md
├── msg.png
├── rsocket.svg
├── run.png
├── spring.jpg
└── springboot.png
├── integration
├── client-regular
│ ├── .gitignore
│ ├── nbactions.xml
│ ├── pom.xml
│ └── src
│ │ └── main
│ │ ├── java
│ │ └── com
│ │ │ └── example
│ │ │ └── demo
│ │ │ └── DemoApplication.java
│ │ └── resources
│ │ └── application.properties
├── client
│ ├── .gitignore
│ ├── nbactions.xml
│ ├── pom.xml
│ └── src
│ │ └── main
│ │ ├── java
│ │ └── com
│ │ │ └── example
│ │ │ └── demo
│ │ │ └── DemoApplication.java
│ │ └── resources
│ │ └── application.properties
├── server-regular
│ ├── .gitignore
│ ├── pom.xml
│ └── src
│ │ └── main
│ │ ├── java
│ │ └── com
│ │ │ └── example
│ │ │ └── demo
│ │ │ └── DemoApplication.java
│ │ └── resources
│ │ └── application.properties
├── server-vanilla
│ ├── .gitignore
│ ├── nbactions.xml
│ ├── pom.xml
│ └── src
│ │ ├── main
│ │ ├── java
│ │ │ └── com
│ │ │ │ └── example
│ │ │ │ └── demo
│ │ │ │ └── DemoApplication.java
│ │ └── resources
│ │ │ └── application.properties
│ │ └── test
│ │ └── java
│ │ └── com
│ │ └── example
│ │ └── demo
│ │ └── DemoApplicationTests.java
└── server
│ ├── .gitignore
│ ├── pom.xml
│ └── src
│ └── main
│ ├── java
│ └── com
│ │ └── example
│ │ └── demo
│ │ └── DemoApplication.java
│ └── resources
│ └── application.properties
├── security
├── .gitignore
├── .mvn
│ └── wrapper
│ │ ├── MavenWrapperDownloader.java
│ │ ├── maven-wrapper.jar
│ │ └── maven-wrapper.properties
├── lombok.config
├── mvnw
├── mvnw.cmd
├── pom.xml
└── src
│ ├── main
│ ├── java
│ │ └── com
│ │ │ └── example
│ │ │ └── demo
│ │ │ └── DemoApplication.java
│ └── resources
│ │ └── application.properties
│ └── test
│ └── java
│ └── com
│ └── example
│ └── demo
│ └── DemoApplicationTests.java
├── server-requester
├── client
│ ├── .gitignore
│ ├── lombok.config
│ ├── nbactions.xml
│ ├── pom.xml
│ └── src
│ │ └── main
│ │ ├── java
│ │ └── com
│ │ │ └── example
│ │ │ └── client
│ │ │ └── ClientApplication.java
│ │ └── resources
│ │ └── application.properties
└── server
│ ├── .gitignore
│ ├── lombok.config
│ ├── nbactions.xml
│ ├── pom.xml
│ └── src
│ └── main
│ ├── java
│ └── com
│ │ └── example
│ │ └── demo
│ │ └── DemoApplication.java
│ └── resources
│ └── application.properties
├── tcp
├── client
│ ├── .gitignore
│ ├── lombok.config
│ ├── nbactions.xml
│ ├── pom.xml
│ └── src
│ │ ├── main
│ │ ├── java
│ │ │ └── com
│ │ │ │ └── example
│ │ │ │ └── client
│ │ │ │ └── ClientApplication.java
│ │ └── resources
│ │ │ └── application.properties
│ │ └── test
│ │ └── java
│ │ └── com
│ │ └── example
│ │ └── consumer
│ │ └── ConsumerApplicationTests.java
└── server
│ ├── .gitignore
│ ├── nbactions.xml
│ ├── pom.xml
│ └── src
│ ├── main
│ ├── java
│ │ └── com
│ │ │ └── example
│ │ │ └── server
│ │ │ └── ServerApplication.java
│ └── resources
│ │ └── application.properties
│ └── test
│ └── java
│ └── com
│ └── example
│ └── producer
│ └── ProducerApplicationTests.java
├── vanilla
├── .gitignore
├── .mvn
│ └── wrapper
│ │ ├── MavenWrapperDownloader.java
│ │ ├── maven-wrapper.jar
│ │ └── maven-wrapper.properties
├── mvnw
├── mvnw.cmd
├── pom.xml
└── src
│ ├── main
│ ├── java
│ │ └── com
│ │ │ └── example
│ │ │ └── demo
│ │ │ ├── DemoApplication.java
│ │ │ ├── FireAndForgetExample.java
│ │ │ ├── RequestChannelExample.java
│ │ │ ├── RequestResponseExample.java
│ │ │ └── RequestStreamExample.java
│ └── resources
│ │ └── application.properties
│ └── test
│ └── java
│ └── com
│ └── example
│ └── demo
│ └── DemoApplicationTests.java
└── websocket
├── client
├── .gitignore
├── lombok.config
├── nbactions.xml
├── pom.xml
└── src
│ ├── main
│ ├── java
│ │ └── com
│ │ │ └── example
│ │ │ └── client
│ │ │ └── ClientApplication.java
│ └── resources
│ │ └── application.properties
│ └── test
│ └── java
│ └── com
│ └── example
│ └── consumer
│ └── ConsumerApplicationTests.java
└── server
├── .gitignore
├── nbactions.xml
├── pom.xml
└── src
├── main
├── java
│ └── com
│ │ └── example
│ │ └── server
│ │ ├── HelloController.java
│ │ └── ServerApplication.java
└── resources
│ └── application.properties
└── test
└── java
└── com
└── example
└── producer
└── ProducerApplicationTests.java
/.gitignore:
--------------------------------------------------------------------------------
1 | # Compiled class file
2 | *.class
3 |
4 | # Log file
5 | *.log
6 |
7 | # BlueJ files
8 | *.ctxt
9 |
10 | # Mobile Tools for Java (J2ME)
11 | .mtj.tmp/
12 |
13 | # Package Files #
14 | *.jar
15 | *.war
16 | *.nar
17 | *.ear
18 | *.zip
19 | *.tar.gz
20 | *.rar
21 |
22 | # virtual machine crash logs, see http://www.java.com/en/download/help/error_hotspot.xml
23 | hs_err_pid*
24 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # RSocket Sandbox
2 |
3 | Sample codes of RSocket Java and Spring RSocket integration.
4 |
5 | ## Docs
6 |
7 | [Using Rsocket with Spring Boot](./docs/GUIDE.md)([medium's link](https://medium.com/@hantsy/using-rsocket-with-spring-boot-cfc67924d06a))
8 |
9 | [Building a CRUD application with RSocket and Spring](./docs/crud.md)
10 |
11 | ## Sample Codes
12 |
13 | * **vanilla** rsocket-java sample
14 |
15 | * **tcp** Spring Boot based application using TCP protocol between client and server
16 |
17 | * **websocket** Using WebSocket as transport protocol instead in a Webflux server.
18 |
19 | * **security** Spring Security RSocket integration.
20 |
21 | * **server-requester** Sending message to client via Server `RSocketRequster`.
22 |
23 | * **integration** Spring Integration RSocket inbound and outbound gateway.
24 |
25 | * **client** Sending messages to server via Spring Integration RSocket OutboundGateay.
26 | * **client-regular** Simple example using Spring Boot RSocket Starter aka `RSocketRequestor`.
27 | * **server-vanilla** Handling messages via Spring Integration RSocket InboundGateway.
28 | * **server** Similar with **server-vanilla**, but reuse Spring Boot RSocket Starter and declare the `ServerRSocketConnecter` bean through `ServerRSocketMessageHandler`.
29 | * **server-regular** Simple example using Spring Boot RSocket Starter aka `@Controller` and `@MessageMapping`.
30 | * **crud** Client and server CRUD interaction sample.
31 | * **client** Sending messages to server via `RSocketRequestor` and TCP protocol.
32 | * **server** Running on Netty/TCP(no web/http support) and handling request via TCP protocol.
33 |
34 | ## References
35 |
36 | * [Spring Framework Reference](https://docs.spring.io/spring-framework/docs/current/spring-framework-reference/web-reactive.html#rsocket)
37 | * [Spring Secuirty Reference](https://docs.spring.io/spring-security/site/docs/current/reference/html/rsocket.html)
38 | * [Spring Boot Reference](https://docs.spring.io/spring-boot/docs/2.2.4.RELEASE/reference/htmlsingle/#boot-features-rsocket)
39 | * [Spring Integration Reference](https://docs.spring.io/spring-integration/reference/html/rsocket.html)
40 | * [RSocket Using Spring Boot](https://www.baeldung.com/spring-boot-rsocket) by Baeldung
41 | * [RSocket Messaging with Spring](https://www.youtube.com/watch?v=iSSrZoGtoSE)
42 | * [Reactive Architectures with RSocket and Spring Cloud Gateway](https://www.youtube.com/watch?v=PfbycN_eqhg)
43 |
44 | * [bclozel/spring-flights](https://github.com/bclozel/spring-flights)
45 | * [spring-projects/spring-security/tree/5.2.2.RELEASE/samples/boot/hellorsocket](https://github.com/spring-projects/spring-security/tree/5.2.2.RELEASE/samples/boot/hellorsocket)
46 | * [spencergibb/rsocket-routing-sample](https://github.com/spencergibb/rsocket-routing-sample)
47 |
48 |
49 |
50 |
51 |
52 |
53 |
54 |
--------------------------------------------------------------------------------
/crud/client/.gitignore:
--------------------------------------------------------------------------------
1 | HELP.md
2 | target/
3 | !.mvn/wrapper/maven-wrapper.jar
4 | !**/src/main/**
5 | !**/src/test/**
6 |
7 | ### STS ###
8 | .apt_generated
9 | .classpath
10 | .factorypath
11 | .project
12 | .settings
13 | .springBeans
14 | .sts4-cache
15 |
16 | ### IntelliJ IDEA ###
17 | .idea
18 | *.iws
19 | *.iml
20 | *.ipr
21 |
22 | ### NetBeans ###
23 | /nbproject/private/
24 | /nbbuild/
25 | /dist/
26 | /nbdist/
27 | /.nb-gradle/
28 | build/
29 |
30 | ### VS Code ###
31 | .vscode/
32 |
--------------------------------------------------------------------------------
/crud/client/lombok.config:
--------------------------------------------------------------------------------
1 | lombok.noArgsConstructor.extraPrivate=true
2 |
--------------------------------------------------------------------------------
/crud/client/nbactions.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | run
5 |
6 | jar
7 |
8 |
9 | spring-boot:run
10 |
11 |
12 | -noverify -XX:TieredStopAtLevel=1
13 | com.example.consumer.ConsumerApplication
14 | always
15 |
16 |
17 |
18 | debug
19 |
20 | jar
21 |
22 |
23 | spring-boot:run
24 |
25 |
26 | -Xdebug -Xrunjdwp:transport=dt_socket,server=n,address=${jpda.address} -noverify -XX:TieredStopAtLevel=1
27 | com.example.consumer.ConsumerApplication
28 | always
29 | true
30 |
31 |
32 |
33 | profile
34 |
35 | jar
36 |
37 |
38 | process-classes
39 | org.codehaus.mojo:exec-maven-plugin:1.2.1:exec
40 |
41 |
42 | -classpath %classpath com.example.consumer.ConsumerApplication
43 | java
44 |
45 |
46 |
47 |
--------------------------------------------------------------------------------
/crud/client/pom.xml:
--------------------------------------------------------------------------------
1 |
2 |
4 | 4.0.0
5 |
6 | org.springframework.boot
7 | spring-boot-starter-parent
8 | 2.3.0.RELEASE
9 |
10 |
11 | com.example
12 | rsocket-sample-boot-crud-client
13 | 0.0.1-SNAPSHOT
14 | rsocket-sample-boot-crud-client
15 | Demo project for Spring Boot
16 |
17 |
18 | 11
19 |
20 |
21 |
22 |
23 | org.springframework.boot
24 | spring-boot-starter-webflux
25 |
26 |
27 | org.springframework.boot
28 | spring-boot-starter-rsocket
29 |
30 |
31 |
32 | org.projectlombok
33 | lombok
34 | true
35 |
36 |
37 | org.springframework.boot
38 | spring-boot-starter-test
39 | test
40 |
41 |
42 | org.junit.vintage
43 | junit-vintage-engine
44 |
45 |
46 |
47 |
48 |
49 |
50 |
51 |
52 | org.springframework.boot
53 | spring-boot-maven-plugin
54 |
55 |
56 |
57 |
58 |
59 |
60 | spring-milestones
61 | Spring Milestones
62 | https://repo.spring.io/milestone
63 |
64 |
65 |
66 |
67 | spring-milestones
68 | Spring Milestones
69 | https://repo.spring.io/milestone
70 |
71 |
72 |
73 |
74 |
--------------------------------------------------------------------------------
/crud/client/src/main/java/com/example/client/ClientApplication.java:
--------------------------------------------------------------------------------
1 | package com.example.client;
2 |
3 | import lombok.*;
4 | import lombok.extern.slf4j.Slf4j;
5 | import org.springframework.boot.SpringApplication;
6 | import org.springframework.boot.autoconfigure.SpringBootApplication;
7 | import org.springframework.context.annotation.Bean;
8 | import org.springframework.messaging.rsocket.RSocketRequester;
9 | import org.springframework.util.MimeTypeUtils;
10 | import org.springframework.util.StringUtils;
11 | import org.springframework.web.bind.annotation.*;
12 | import reactor.core.publisher.Flux;
13 | import reactor.core.publisher.Mono;
14 |
15 | @SpringBootApplication
16 | public class ClientApplication {
17 |
18 | public static void main(String[] args) {
19 | SpringApplication.run(ClientApplication.class, args);
20 | }
21 |
22 | @Bean
23 | public RSocketRequester rSocketRequester(RSocketRequester.Builder b) {
24 | return b.dataMimeType(MimeTypeUtils.APPLICATION_JSON)
25 | .connectTcp("localhost", 7000)
26 | .block();
27 | }
28 |
29 | }
30 |
31 | @Slf4j
32 | @RequiredArgsConstructor
33 | @RestController()
34 | @RequestMapping("/posts")
35 | class PostClientController {
36 |
37 | private final RSocketRequester requester;
38 |
39 | @GetMapping("")
40 | Flux all(@RequestParam(name = "title", required = false) String title) {
41 | if (StringUtils.hasText(title)) {
42 | return this.requester.route("posts.titleContains")
43 | .data(title).retrieveFlux(Post.class);
44 | } else {
45 | return this.requester.route("posts.findAll")
46 | .retrieveFlux(Post.class);
47 | }
48 | }
49 |
50 | @GetMapping("{id}")
51 | Mono findById(@PathVariable Integer id) {
52 | return this.requester.route("posts.findById." + id)
53 | .retrieveMono(Post.class);
54 | }
55 |
56 | @PostMapping("")
57 | Mono save(@RequestBody Post post) {
58 | return this.requester.route("posts.save")
59 | .data(post)
60 | .retrieveMono(Post.class);
61 | }
62 |
63 | @PutMapping("{id}")
64 | Mono update(@PathVariable Integer id, @RequestBody Post post) {
65 | return this.requester.route("posts.update."+ id)
66 | .data(post)
67 | .retrieveMono(Post.class);
68 | }
69 |
70 | @DeleteMapping("{id}")
71 | Mono delete(@PathVariable Integer id) {
72 | return this.requester.route("posts.deleteById."+ id).send();
73 | }
74 |
75 | }
76 |
77 | @Data
78 | @ToString
79 | @Builder
80 | @NoArgsConstructor
81 | @AllArgsConstructor
82 | class Post {
83 | private Integer id;
84 | private String title;
85 | private String content;
86 | }
87 |
--------------------------------------------------------------------------------
/crud/client/src/main/resources/application.properties:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/crud/client/src/test/java/com/example/consumer/ConsumerApplicationTests.java:
--------------------------------------------------------------------------------
1 | package com.example.consumer;
2 |
3 | import org.junit.jupiter.api.Test;
4 | import org.springframework.boot.test.context.SpringBootTest;
5 |
6 | @SpringBootTest
7 | class ConsumerApplicationTests {
8 |
9 | @Test
10 | void contextLoads() {
11 | }
12 |
13 | }
14 |
--------------------------------------------------------------------------------
/crud/server/.gitignore:
--------------------------------------------------------------------------------
1 | /target/
2 | !.mvn/wrapper/maven-wrapper.jar
3 |
4 | ### STS ###
5 | .apt_generated
6 | .classpath
7 | .factorypath
8 | .project
9 | .settings
10 | .springBeans
11 | .sts4-cache
12 |
13 | ### IntelliJ IDEA ###
14 | .idea
15 | *.iws
16 | *.iml
17 | *.ipr
18 |
19 | ### NetBeans ###
20 | /nbproject/private/
21 | /build/
22 | /nbbuild/
23 | /dist/
24 | /nbdist/
25 | /.nb-gradle/
--------------------------------------------------------------------------------
/crud/server/.mvn/wrapper/maven-wrapper.jar:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/hantsy/rsocket-sample/7349fd955764b163ac061b00d30d8a8646a0fcdd/crud/server/.mvn/wrapper/maven-wrapper.jar
--------------------------------------------------------------------------------
/crud/server/.mvn/wrapper/maven-wrapper.properties:
--------------------------------------------------------------------------------
1 | distributionUrl=https://repo.maven.apache.org/maven2/org/apache/maven/apache-maven/3.5.4/apache-maven-3.5.4-bin.zip
2 |
--------------------------------------------------------------------------------
/crud/server/mvnw:
--------------------------------------------------------------------------------
1 | #!/bin/sh
2 | # ----------------------------------------------------------------------------
3 | # Licensed to the Apache Software Foundation (ASF) under one
4 | # or more contributor license agreements. See the NOTICE file
5 | # distributed with this work for additional information
6 | # regarding copyright ownership. The ASF licenses this file
7 | # to you under the Apache License, Version 2.0 (the
8 | # "License"); you may not use this file except in compliance
9 | # with the License. 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,
14 | # software distributed under the License is distributed on an
15 | # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16 | # KIND, either express or implied. See the License for the
17 | # specific language governing permissions and limitations
18 | # under the License.
19 | # ----------------------------------------------------------------------------
20 |
21 | # ----------------------------------------------------------------------------
22 | # Maven2 Start Up Batch script
23 | #
24 | # Required ENV vars:
25 | # ------------------
26 | # JAVA_HOME - location of a JDK home dir
27 | #
28 | # Optional ENV vars
29 | # -----------------
30 | # M2_HOME - location of maven2's installed home dir
31 | # MAVEN_OPTS - parameters passed to the Java VM when running Maven
32 | # e.g. to debug Maven itself, use
33 | # set MAVEN_OPTS=-Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=8000
34 | # MAVEN_SKIP_RC - flag to disable loading of mavenrc files
35 | # ----------------------------------------------------------------------------
36 |
37 | if [ -z "$MAVEN_SKIP_RC" ] ; then
38 |
39 | if [ -f /etc/mavenrc ] ; then
40 | . /etc/mavenrc
41 | fi
42 |
43 | if [ -f "$HOME/.mavenrc" ] ; then
44 | . "$HOME/.mavenrc"
45 | fi
46 |
47 | fi
48 |
49 | # OS specific support. $var _must_ be set to either true or false.
50 | cygwin=false;
51 | darwin=false;
52 | mingw=false
53 | case "`uname`" in
54 | CYGWIN*) cygwin=true ;;
55 | MINGW*) mingw=true;;
56 | Darwin*) darwin=true
57 | # Use /usr/libexec/java_home if available, otherwise fall back to /Library/Java/Home
58 | # See https://developer.apple.com/library/mac/qa/qa1170/_index.html
59 | if [ -z "$JAVA_HOME" ]; then
60 | if [ -x "/usr/libexec/java_home" ]; then
61 | export JAVA_HOME="`/usr/libexec/java_home`"
62 | else
63 | export JAVA_HOME="/Library/Java/Home"
64 | fi
65 | fi
66 | ;;
67 | esac
68 |
69 | if [ -z "$JAVA_HOME" ] ; then
70 | if [ -r /etc/gentoo-release ] ; then
71 | JAVA_HOME=`java-config --jre-home`
72 | fi
73 | fi
74 |
75 | if [ -z "$M2_HOME" ] ; then
76 | ## resolve links - $0 may be a link to maven's home
77 | PRG="$0"
78 |
79 | # need this for relative symlinks
80 | while [ -h "$PRG" ] ; do
81 | ls=`ls -ld "$PRG"`
82 | link=`expr "$ls" : '.*-> \(.*\)$'`
83 | if expr "$link" : '/.*' > /dev/null; then
84 | PRG="$link"
85 | else
86 | PRG="`dirname "$PRG"`/$link"
87 | fi
88 | done
89 |
90 | saveddir=`pwd`
91 |
92 | M2_HOME=`dirname "$PRG"`/..
93 |
94 | # make it fully qualified
95 | M2_HOME=`cd "$M2_HOME" && pwd`
96 |
97 | cd "$saveddir"
98 | # echo Using m2 at $M2_HOME
99 | fi
100 |
101 | # For Cygwin, ensure paths are in UNIX format before anything is touched
102 | if $cygwin ; then
103 | [ -n "$M2_HOME" ] &&
104 | M2_HOME=`cygpath --unix "$M2_HOME"`
105 | [ -n "$JAVA_HOME" ] &&
106 | JAVA_HOME=`cygpath --unix "$JAVA_HOME"`
107 | [ -n "$CLASSPATH" ] &&
108 | CLASSPATH=`cygpath --path --unix "$CLASSPATH"`
109 | fi
110 |
111 | # For Mingw, ensure paths are in UNIX format before anything is touched
112 | if $mingw ; then
113 | [ -n "$M2_HOME" ] &&
114 | M2_HOME="`(cd "$M2_HOME"; pwd)`"
115 | [ -n "$JAVA_HOME" ] &&
116 | JAVA_HOME="`(cd "$JAVA_HOME"; pwd)`"
117 | # TODO classpath?
118 | fi
119 |
120 | if [ -z "$JAVA_HOME" ]; then
121 | javaExecutable="`which javac`"
122 | if [ -n "$javaExecutable" ] && ! [ "`expr \"$javaExecutable\" : '\([^ ]*\)'`" = "no" ]; then
123 | # readlink(1) is not available as standard on Solaris 10.
124 | readLink=`which readlink`
125 | if [ ! `expr "$readLink" : '\([^ ]*\)'` = "no" ]; then
126 | if $darwin ; then
127 | javaHome="`dirname \"$javaExecutable\"`"
128 | javaExecutable="`cd \"$javaHome\" && pwd -P`/javac"
129 | else
130 | javaExecutable="`readlink -f \"$javaExecutable\"`"
131 | fi
132 | javaHome="`dirname \"$javaExecutable\"`"
133 | javaHome=`expr "$javaHome" : '\(.*\)/bin'`
134 | JAVA_HOME="$javaHome"
135 | export JAVA_HOME
136 | fi
137 | fi
138 | fi
139 |
140 | if [ -z "$JAVACMD" ] ; then
141 | if [ -n "$JAVA_HOME" ] ; then
142 | if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
143 | # IBM's JDK on AIX uses strange locations for the executables
144 | JAVACMD="$JAVA_HOME/jre/sh/java"
145 | else
146 | JAVACMD="$JAVA_HOME/bin/java"
147 | fi
148 | else
149 | JAVACMD="`which java`"
150 | fi
151 | fi
152 |
153 | if [ ! -x "$JAVACMD" ] ; then
154 | echo "Error: JAVA_HOME is not defined correctly." >&2
155 | echo " We cannot execute $JAVACMD" >&2
156 | exit 1
157 | fi
158 |
159 | if [ -z "$JAVA_HOME" ] ; then
160 | echo "Warning: JAVA_HOME environment variable is not set."
161 | fi
162 |
163 | CLASSWORLDS_LAUNCHER=org.codehaus.plexus.classworlds.launcher.Launcher
164 |
165 | # traverses directory structure from process work directory to filesystem root
166 | # first directory with .mvn subdirectory is considered project base directory
167 | find_maven_basedir() {
168 |
169 | if [ -z "$1" ]
170 | then
171 | echo "Path not specified to find_maven_basedir"
172 | return 1
173 | fi
174 |
175 | basedir="$1"
176 | wdir="$1"
177 | while [ "$wdir" != '/' ] ; do
178 | if [ -d "$wdir"/.mvn ] ; then
179 | basedir=$wdir
180 | break
181 | fi
182 | # workaround for JBEAP-8937 (on Solaris 10/Sparc)
183 | if [ -d "${wdir}" ]; then
184 | wdir=`cd "$wdir/.."; pwd`
185 | fi
186 | # end of workaround
187 | done
188 | echo "${basedir}"
189 | }
190 |
191 | # concatenates all lines of a file
192 | concat_lines() {
193 | if [ -f "$1" ]; then
194 | echo "$(tr -s '\n' ' ' < "$1")"
195 | fi
196 | }
197 |
198 | BASE_DIR=`find_maven_basedir "$(pwd)"`
199 | if [ -z "$BASE_DIR" ]; then
200 | exit 1;
201 | fi
202 |
203 | ##########################################################################################
204 | # Extension to allow automatically downloading the maven-wrapper.jar from Maven-central
205 | # This allows using the maven wrapper in projects that prohibit checking in binary data.
206 | ##########################################################################################
207 | if [ -r "$BASE_DIR/.mvn/wrapper/maven-wrapper.jar" ]; then
208 | if [ "$MVNW_VERBOSE" = true ]; then
209 | echo "Found .mvn/wrapper/maven-wrapper.jar"
210 | fi
211 | else
212 | if [ "$MVNW_VERBOSE" = true ]; then
213 | echo "Couldn't find .mvn/wrapper/maven-wrapper.jar, downloading it ..."
214 | fi
215 | jarUrl="https://repo.maven.apache.org/maven2/io/takari/maven-wrapper/0.4.2/maven-wrapper-0.4.2.jar"
216 | while IFS="=" read key value; do
217 | case "$key" in (wrapperUrl) jarUrl="$value"; break ;;
218 | esac
219 | done < "$BASE_DIR/.mvn/wrapper/maven-wrapper.properties"
220 | if [ "$MVNW_VERBOSE" = true ]; then
221 | echo "Downloading from: $jarUrl"
222 | fi
223 | wrapperJarPath="$BASE_DIR/.mvn/wrapper/maven-wrapper.jar"
224 |
225 | if command -v wget > /dev/null; then
226 | if [ "$MVNW_VERBOSE" = true ]; then
227 | echo "Found wget ... using wget"
228 | fi
229 | wget "$jarUrl" -O "$wrapperJarPath"
230 | elif command -v curl > /dev/null; then
231 | if [ "$MVNW_VERBOSE" = true ]; then
232 | echo "Found curl ... using curl"
233 | fi
234 | curl -o "$wrapperJarPath" "$jarUrl"
235 | else
236 | if [ "$MVNW_VERBOSE" = true ]; then
237 | echo "Falling back to using Java to download"
238 | fi
239 | javaClass="$BASE_DIR/.mvn/wrapper/MavenWrapperDownloader.java"
240 | if [ -e "$javaClass" ]; then
241 | if [ ! -e "$BASE_DIR/.mvn/wrapper/MavenWrapperDownloader.class" ]; then
242 | if [ "$MVNW_VERBOSE" = true ]; then
243 | echo " - Compiling MavenWrapperDownloader.java ..."
244 | fi
245 | # Compiling the Java class
246 | ("$JAVA_HOME/bin/javac" "$javaClass")
247 | fi
248 | if [ -e "$BASE_DIR/.mvn/wrapper/MavenWrapperDownloader.class" ]; then
249 | # Running the downloader
250 | if [ "$MVNW_VERBOSE" = true ]; then
251 | echo " - Running MavenWrapperDownloader.java ..."
252 | fi
253 | ("$JAVA_HOME/bin/java" -cp .mvn/wrapper MavenWrapperDownloader "$MAVEN_PROJECTBASEDIR")
254 | fi
255 | fi
256 | fi
257 | fi
258 | ##########################################################################################
259 | # End of extension
260 | ##########################################################################################
261 |
262 | export MAVEN_PROJECTBASEDIR=${MAVEN_BASEDIR:-"$BASE_DIR"}
263 | if [ "$MVNW_VERBOSE" = true ]; then
264 | echo $MAVEN_PROJECTBASEDIR
265 | fi
266 | MAVEN_OPTS="$(concat_lines "$MAVEN_PROJECTBASEDIR/.mvn/jvm.config") $MAVEN_OPTS"
267 |
268 | # For Cygwin, switch paths to Windows format before running java
269 | if $cygwin; then
270 | [ -n "$M2_HOME" ] &&
271 | M2_HOME=`cygpath --path --windows "$M2_HOME"`
272 | [ -n "$JAVA_HOME" ] &&
273 | JAVA_HOME=`cygpath --path --windows "$JAVA_HOME"`
274 | [ -n "$CLASSPATH" ] &&
275 | CLASSPATH=`cygpath --path --windows "$CLASSPATH"`
276 | [ -n "$MAVEN_PROJECTBASEDIR" ] &&
277 | MAVEN_PROJECTBASEDIR=`cygpath --path --windows "$MAVEN_PROJECTBASEDIR"`
278 | fi
279 |
280 | WRAPPER_LAUNCHER=org.apache.maven.wrapper.MavenWrapperMain
281 |
282 | exec "$JAVACMD" \
283 | $MAVEN_OPTS \
284 | -classpath "$MAVEN_PROJECTBASEDIR/.mvn/wrapper/maven-wrapper.jar" \
285 | "-Dmaven.home=${M2_HOME}" "-Dmaven.multiModuleProjectDirectory=${MAVEN_PROJECTBASEDIR}" \
286 | ${WRAPPER_LAUNCHER} $MAVEN_CONFIG "$@"
287 |
--------------------------------------------------------------------------------
/crud/server/mvnw.cmd:
--------------------------------------------------------------------------------
1 | @REM ----------------------------------------------------------------------------
2 | @REM Licensed to the Apache Software Foundation (ASF) under one
3 | @REM or more contributor license agreements. See the NOTICE file
4 | @REM distributed with this work for additional information
5 | @REM regarding copyright ownership. The ASF licenses this file
6 | @REM to you under the Apache License, Version 2.0 (the
7 | @REM "License"); you may not use this file except in compliance
8 | @REM with the License. You may obtain a copy of the License at
9 | @REM
10 | @REM http://www.apache.org/licenses/LICENSE-2.0
11 | @REM
12 | @REM Unless required by applicable law or agreed to in writing,
13 | @REM software distributed under the License is distributed on an
14 | @REM "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15 | @REM KIND, either express or implied. See the License for the
16 | @REM specific language governing permissions and limitations
17 | @REM under the License.
18 | @REM ----------------------------------------------------------------------------
19 |
20 | @REM ----------------------------------------------------------------------------
21 | @REM Maven2 Start Up Batch script
22 | @REM
23 | @REM Required ENV vars:
24 | @REM JAVA_HOME - location of a JDK home dir
25 | @REM
26 | @REM Optional ENV vars
27 | @REM M2_HOME - location of maven2's installed home dir
28 | @REM MAVEN_BATCH_ECHO - set to 'on' to enable the echoing of the batch commands
29 | @REM MAVEN_BATCH_PAUSE - set to 'on' to wait for a key stroke before ending
30 | @REM MAVEN_OPTS - parameters passed to the Java VM when running Maven
31 | @REM e.g. to debug Maven itself, use
32 | @REM set MAVEN_OPTS=-Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=8000
33 | @REM MAVEN_SKIP_RC - flag to disable loading of mavenrc files
34 | @REM ----------------------------------------------------------------------------
35 |
36 | @REM Begin all REM lines with '@' in case MAVEN_BATCH_ECHO is 'on'
37 | @echo off
38 | @REM set title of command window
39 | title %0
40 | @REM enable echoing my setting MAVEN_BATCH_ECHO to 'on'
41 | @if "%MAVEN_BATCH_ECHO%" == "on" echo %MAVEN_BATCH_ECHO%
42 |
43 | @REM set %HOME% to equivalent of $HOME
44 | if "%HOME%" == "" (set "HOME=%HOMEDRIVE%%HOMEPATH%")
45 |
46 | @REM Execute a user defined script before this one
47 | if not "%MAVEN_SKIP_RC%" == "" goto skipRcPre
48 | @REM check for pre script, once with legacy .bat ending and once with .cmd ending
49 | if exist "%HOME%\mavenrc_pre.bat" call "%HOME%\mavenrc_pre.bat"
50 | if exist "%HOME%\mavenrc_pre.cmd" call "%HOME%\mavenrc_pre.cmd"
51 | :skipRcPre
52 |
53 | @setlocal
54 |
55 | set ERROR_CODE=0
56 |
57 | @REM To isolate internal variables from possible post scripts, we use another setlocal
58 | @setlocal
59 |
60 | @REM ==== START VALIDATION ====
61 | if not "%JAVA_HOME%" == "" goto OkJHome
62 |
63 | echo.
64 | echo Error: JAVA_HOME not found in your environment. >&2
65 | echo Please set the JAVA_HOME variable in your environment to match the >&2
66 | echo location of your Java installation. >&2
67 | echo.
68 | goto error
69 |
70 | :OkJHome
71 | if exist "%JAVA_HOME%\bin\java.exe" goto init
72 |
73 | echo.
74 | echo Error: JAVA_HOME is set to an invalid directory. >&2
75 | echo JAVA_HOME = "%JAVA_HOME%" >&2
76 | echo Please set the JAVA_HOME variable in your environment to match the >&2
77 | echo location of your Java installation. >&2
78 | echo.
79 | goto error
80 |
81 | @REM ==== END VALIDATION ====
82 |
83 | :init
84 |
85 | @REM Find the project base dir, i.e. the directory that contains the folder ".mvn".
86 | @REM Fallback to current working directory if not found.
87 |
88 | set MAVEN_PROJECTBASEDIR=%MAVEN_BASEDIR%
89 | IF NOT "%MAVEN_PROJECTBASEDIR%"=="" goto endDetectBaseDir
90 |
91 | set EXEC_DIR=%CD%
92 | set WDIR=%EXEC_DIR%
93 | :findBaseDir
94 | IF EXIST "%WDIR%"\.mvn goto baseDirFound
95 | cd ..
96 | IF "%WDIR%"=="%CD%" goto baseDirNotFound
97 | set WDIR=%CD%
98 | goto findBaseDir
99 |
100 | :baseDirFound
101 | set MAVEN_PROJECTBASEDIR=%WDIR%
102 | cd "%EXEC_DIR%"
103 | goto endDetectBaseDir
104 |
105 | :baseDirNotFound
106 | set MAVEN_PROJECTBASEDIR=%EXEC_DIR%
107 | cd "%EXEC_DIR%"
108 |
109 | :endDetectBaseDir
110 |
111 | IF NOT EXIST "%MAVEN_PROJECTBASEDIR%\.mvn\jvm.config" goto endReadAdditionalConfig
112 |
113 | @setlocal EnableExtensions EnableDelayedExpansion
114 | for /F "usebackq delims=" %%a in ("%MAVEN_PROJECTBASEDIR%\.mvn\jvm.config") do set JVM_CONFIG_MAVEN_PROPS=!JVM_CONFIG_MAVEN_PROPS! %%a
115 | @endlocal & set JVM_CONFIG_MAVEN_PROPS=%JVM_CONFIG_MAVEN_PROPS%
116 |
117 | :endReadAdditionalConfig
118 |
119 | SET MAVEN_JAVA_EXE="%JAVA_HOME%\bin\java.exe"
120 | set WRAPPER_JAR="%MAVEN_PROJECTBASEDIR%\.mvn\wrapper\maven-wrapper.jar"
121 | set WRAPPER_LAUNCHER=org.apache.maven.wrapper.MavenWrapperMain
122 |
123 | set DOWNLOAD_URL="https://repo.maven.apache.org/maven2/io/takari/maven-wrapper/0.4.2/maven-wrapper-0.4.2.jar"
124 | FOR /F "tokens=1,2 delims==" %%A IN (%MAVEN_PROJECTBASEDIR%\.mvn\wrapper\maven-wrapper.properties) DO (
125 | IF "%%A"=="wrapperUrl" SET DOWNLOAD_URL=%%B
126 | )
127 |
128 | @REM Extension to allow automatically downloading the maven-wrapper.jar from Maven-central
129 | @REM This allows using the maven wrapper in projects that prohibit checking in binary data.
130 | if exist %WRAPPER_JAR% (
131 | echo Found %WRAPPER_JAR%
132 | ) else (
133 | echo Couldn't find %WRAPPER_JAR%, downloading it ...
134 | echo Downloading from: %DOWNLOAD_URL%
135 | powershell -Command "(New-Object Net.WebClient).DownloadFile('%DOWNLOAD_URL%', '%WRAPPER_JAR%')"
136 | echo Finished downloading %WRAPPER_JAR%
137 | )
138 | @REM End of extension
139 |
140 | %MAVEN_JAVA_EXE% %JVM_CONFIG_MAVEN_PROPS% %MAVEN_OPTS% %MAVEN_DEBUG_OPTS% -classpath %WRAPPER_JAR% "-Dmaven.multiModuleProjectDirectory=%MAVEN_PROJECTBASEDIR%" %WRAPPER_LAUNCHER% %MAVEN_CONFIG% %*
141 | if ERRORLEVEL 1 goto error
142 | goto end
143 |
144 | :error
145 | set ERROR_CODE=1
146 |
147 | :end
148 | @endlocal & set ERROR_CODE=%ERROR_CODE%
149 |
150 | if not "%MAVEN_SKIP_RC%" == "" goto skipRcPost
151 | @REM check for post script, once with legacy .bat ending and once with .cmd ending
152 | if exist "%HOME%\mavenrc_post.bat" call "%HOME%\mavenrc_post.bat"
153 | if exist "%HOME%\mavenrc_post.cmd" call "%HOME%\mavenrc_post.cmd"
154 | :skipRcPost
155 |
156 | @REM pause the script if MAVEN_BATCH_PAUSE is set to 'on'
157 | if "%MAVEN_BATCH_PAUSE%" == "on" pause
158 |
159 | if "%MAVEN_TERMINATE_CMD%" == "on" exit %ERROR_CODE%
160 |
161 | exit /B %ERROR_CODE%
162 |
--------------------------------------------------------------------------------
/crud/server/pom.xml:
--------------------------------------------------------------------------------
1 |
2 |
5 | 4.0.0
6 |
7 | org.springframework.boot
8 | spring-boot-starter-parent
9 | 2.3.0.RELEASE
10 |
11 |
12 | com.example
13 | rsocket-sample-boot-crud-server
14 | 0.0.1-SNAPSHOT
15 | rsocket-sample-boot-crud-server
16 | Demo project for Spring Boot
17 |
18 |
19 | 11
20 |
21 |
22 |
23 | org.springframework.boot
24 | spring-boot-starter-rsocket
25 |
26 |
27 | org.springframework.boot
28 | spring-boot-starter-data-r2dbc
29 |
30 |
31 | io.r2dbc
32 | r2dbc-h2
33 | runtime
34 |
35 |
36 | org.projectlombok
37 | lombok
38 | true
39 |
40 |
41 | org.springframework.boot
42 | spring-boot-starter-test
43 | test
44 |
45 |
46 | org.junit.vintage
47 | junit-vintage-engine
48 |
49 |
50 |
51 |
52 | io.projectreactor
53 | reactor-test
54 | test
55 |
56 |
57 |
58 |
59 |
60 |
61 | org.springframework.boot
62 | spring-boot-maven-plugin
63 |
64 |
65 |
66 |
67 |
68 |
69 | spring-snapshots
70 | Spring Snapshots
71 | https://repo.spring.io/snapshot
72 |
73 | true
74 |
75 |
76 |
77 | spring-milestones
78 | Spring Milestones
79 | https://repo.spring.io/milestone
80 |
81 | false
82 |
83 |
84 |
85 |
86 |
87 |
88 | spring-snapshots
89 | Spring Snapshots
90 | https://repo.spring.io/snapshot
91 |
92 | true
93 |
94 |
95 |
96 | spring-milestones
97 | Spring Milestones
98 | https://repo.spring.io/milestone
99 |
100 | false
101 |
102 |
103 |
104 |
105 |
106 |
107 |
--------------------------------------------------------------------------------
/crud/server/src/main/java/com/example/demo/DemoApplication.java:
--------------------------------------------------------------------------------
1 | package com.example.demo;
2 |
3 | import io.r2dbc.spi.ConnectionFactory;
4 | import lombok.*;
5 | import lombok.extern.slf4j.Slf4j;
6 | import org.springframework.boot.ApplicationArguments;
7 | import org.springframework.boot.ApplicationRunner;
8 | import org.springframework.boot.SpringApplication;
9 | import org.springframework.boot.autoconfigure.SpringBootApplication;
10 | import org.springframework.context.annotation.Bean;
11 | import org.springframework.core.io.ClassPathResource;
12 | import org.springframework.data.annotation.Id;
13 | import org.springframework.data.r2dbc.connectionfactory.init.CompositeDatabasePopulator;
14 | import org.springframework.data.r2dbc.connectionfactory.init.ConnectionFactoryInitializer;
15 | import org.springframework.data.r2dbc.connectionfactory.init.ResourceDatabasePopulator;
16 | import org.springframework.data.r2dbc.repository.Query;
17 | import org.springframework.data.r2dbc.repository.R2dbcRepository;
18 | import org.springframework.data.relational.core.mapping.Column;
19 | import org.springframework.data.relational.core.mapping.Table;
20 | import org.springframework.messaging.handler.annotation.DestinationVariable;
21 | import org.springframework.messaging.handler.annotation.MessageMapping;
22 | import org.springframework.messaging.handler.annotation.Payload;
23 | import org.springframework.stereotype.Component;
24 | import org.springframework.stereotype.Controller;
25 | import reactor.core.publisher.Flux;
26 | import reactor.core.publisher.Mono;
27 |
28 | import java.util.List;
29 |
30 | @SpringBootApplication
31 | public class DemoApplication {
32 |
33 | public static void main(String[] args) {
34 | SpringApplication.run(DemoApplication.class, args);
35 | }
36 |
37 | @Bean
38 | public ConnectionFactoryInitializer initializer(ConnectionFactory connectionFactory) {
39 |
40 | ConnectionFactoryInitializer initializer = new ConnectionFactoryInitializer();
41 | initializer.setConnectionFactory(connectionFactory);
42 |
43 | CompositeDatabasePopulator populator = new CompositeDatabasePopulator();
44 | populator.addPopulators(new ResourceDatabasePopulator(new ClassPathResource("schema.sql")));
45 | populator.addPopulators(new ResourceDatabasePopulator(new ClassPathResource("data.sql")));
46 | initializer.setDatabasePopulator(populator);
47 |
48 | return initializer;
49 | }
50 | }
51 |
52 | @Component
53 | @Slf4j
54 | @RequiredArgsConstructor
55 | class DataInitializer implements ApplicationRunner {
56 |
57 | private final PostRepository posts;
58 |
59 | @Override
60 | public void run(ApplicationArguments args) throws Exception {
61 | log.info("start data initialization...");
62 | this.posts
63 | .saveAll(
64 | List.of(
65 | Post.builder().title("Post one").content("The content of post one").build(),
66 | Post.builder().title("Post tow").content("The content of post tow").build()
67 | )
68 | )
69 | .log()
70 | .thenMany(
71 | this.posts.findAll()
72 | )
73 | .subscribe(
74 | (data) -> log.info("post: " + data),
75 | (err) -> log.error("error: " + err),
76 | () -> log.info("initialization done...")
77 | );
78 | }
79 | }
80 |
81 | @Controller
82 | @RequiredArgsConstructor
83 | class PostController {
84 |
85 | private final PostRepository posts;
86 |
87 | @MessageMapping("posts.findAll")
88 | public Flux all() {
89 | return this.posts.findAll();
90 | }
91 |
92 | @MessageMapping("posts.titleContains")
93 | public Flux titleContains(@Payload String title) {
94 | return this.posts.findByTitleContains(title);
95 | }
96 |
97 | @MessageMapping("posts.findById.{id}")
98 | public Mono get(@DestinationVariable("id") Integer id) {
99 | return this.posts.findById(id);
100 | }
101 |
102 | @MessageMapping("posts.save")
103 | public Mono create(@Payload Post post) {
104 | return this.posts.save(post);
105 | }
106 |
107 | @MessageMapping("posts.update.{id}")
108 | public Mono update(@DestinationVariable("id") Integer id, @Payload Post post) {
109 | return this.posts.findById(id)
110 | .map(p -> {
111 | p.setTitle(post.getTitle());
112 | p.setContent(post.getContent());
113 |
114 | return p;
115 | })
116 | .flatMap(p -> this.posts.save(p));
117 | }
118 |
119 | @MessageMapping("posts.deleteById.{id}")
120 | public Mono delete(@DestinationVariable("id") Integer id) {
121 | return this.posts.deleteById(id);
122 | }
123 |
124 | }
125 |
126 | interface PostRepository extends R2dbcRepository {
127 |
128 | @Query("SELECT * FROM posts WHERE title like $1")
129 | Flux findByTitleContains(String name);
130 |
131 | }
132 |
133 | @Data
134 | @ToString
135 | @Builder
136 | @NoArgsConstructor
137 | @AllArgsConstructor
138 | @Table("posts")
139 | class Post {
140 |
141 | @Id
142 | @Column("id")
143 | private Integer id;
144 |
145 | @Column("title")
146 | private String title;
147 |
148 | @Column("content")
149 | private String content;
150 |
151 | }
152 |
--------------------------------------------------------------------------------
/crud/server/src/main/resources/application.properties:
--------------------------------------------------------------------------------
1 | spring.rsocket.server.port=7000
2 | spring.rsocket.server.transport=tcp
3 |
--------------------------------------------------------------------------------
/crud/server/src/main/resources/data.sql:
--------------------------------------------------------------------------------
1 | DELETE FROM posts;
2 | INSERT INTO posts (title, content) VALUES ('post one in data.sql', 'content of post one in data.sql');
--------------------------------------------------------------------------------
/crud/server/src/main/resources/schema.sql:
--------------------------------------------------------------------------------
1 | CREATE TABLE posts (id SERIAL PRIMARY KEY, title VARCHAR(255), content VARCHAR(255));
--------------------------------------------------------------------------------
/crud/server/src/test/java/com/example/demo/IntegrationTests.java:
--------------------------------------------------------------------------------
1 | package com.example.demo;
2 |
3 | import org.junit.jupiter.api.BeforeAll;
4 | import org.junit.jupiter.api.Test;
5 | import org.springframework.beans.factory.annotation.Autowired;
6 | import org.springframework.boot.rsocket.context.LocalRSocketServerPort;
7 | import org.springframework.boot.test.context.SpringBootTest;
8 | import org.springframework.messaging.rsocket.RSocketRequester;
9 | import reactor.test.StepVerifier;
10 |
11 | import static org.junit.jupiter.api.Assertions.assertEquals;
12 |
13 | @SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
14 | public class IntegrationTests {
15 |
16 | @LocalRSocketServerPort
17 | int port;
18 |
19 | RSocketRequester rSocketRequester;
20 |
21 | @Autowired
22 | RSocketRequester.Builder builder;
23 |
24 | @BeforeAll
25 | public void setup() {
26 | this.rSocketRequester = builder.connectTcp("localhost", port).block();
27 | }
28 |
29 | @Test
30 | public void willLoadPosts() {
31 | this.rSocketRequester.route("posts.findAll")
32 | .retrieveFlux(Post.class)
33 | .as(StepVerifier::create)
34 | .expectNextCount(3)
35 | .verifyComplete();
36 | }
37 |
38 | @Test
39 | public void testTitleContains() {
40 | this.rSocketRequester.route("posts.titleContains")
41 | .data("%data.sql")
42 | .retrieveFlux(Post.class)
43 | .take(1)
44 | .as(StepVerifier::create)
45 | .consumeNextWith(p -> assertEquals("post one in data.sql", p.getTitle()))
46 | .verifyComplete();
47 | }
48 |
49 | }
50 |
51 |
--------------------------------------------------------------------------------
/crud/server/src/test/java/com/example/demo/PostRepositoryTest.java:
--------------------------------------------------------------------------------
1 | package com.example.demo;
2 |
3 |
4 | import org.junit.jupiter.api.Test;
5 | import org.springframework.beans.factory.annotation.Autowired;
6 | import org.springframework.boot.test.autoconfigure.data.r2dbc.DataR2dbcTest;
7 | import org.springframework.data.r2dbc.core.DatabaseClient;
8 | import reactor.test.StepVerifier;
9 |
10 | import java.time.Duration;
11 |
12 | import static org.junit.jupiter.api.Assertions.assertEquals;
13 | import static org.junit.jupiter.api.Assertions.assertNotNull;
14 |
15 | // see: https://github.com/spring-projects-experimental/spring-boot-r2dbc/issues/68
16 | @DataR2dbcTest
17 | public class PostRepositoryTest {
18 |
19 | @Autowired
20 | DatabaseClient client;
21 |
22 | @Autowired
23 | PostRepository posts;
24 |
25 | @Test
26 | public void testDatabaseClientExisted() {
27 | assertNotNull(client);
28 | }
29 |
30 | @Test
31 | public void testPostRepositoryExisted() {
32 | assertNotNull(posts);
33 | }
34 |
35 | @Test
36 | public void testInsertAndQuery() {
37 | this.client.insert()
38 | .into("posts")
39 | //.nullValue("id", Integer.class)
40 | .value("title", "mytesttitle")
41 | .value("content", "testcontent")
42 | .then().block(Duration.ofSeconds(5));
43 |
44 | this.posts.findByTitleContains("%testtitle")
45 | .take(1)
46 | .as(StepVerifier::create)
47 | .consumeNextWith(p -> assertEquals("mytesttitle", p.getTitle()))
48 | .verifyComplete();
49 |
50 | }
51 | }
52 |
--------------------------------------------------------------------------------
/crud/server/src/test/resources/junit-platform.properties:
--------------------------------------------------------------------------------
1 | junit.jupiter.testinstance.lifecycle.default = per_class
2 |
--------------------------------------------------------------------------------
/docs/GUIDE.md:
--------------------------------------------------------------------------------
1 | # Using RSocket with Spring Boot
2 |
3 | [RSocket](https://rsocket.io) is a binary protocol for use on byte stream transports such as TCP, WebSockets, and Aeron.
4 |
5 | It enables the following symmetric interaction models via async message passing over a single connection:
6 |
7 | - request/response (stream of 1)
8 | - request/stream (finite stream of many)
9 | - fire-and-forget (no response)
10 | - channel (bi-directional streams)
11 |
12 | There are several implementations provided now, including Javascript, Java, Kotlin etc. In this post, we will explore the official Java implementation- [rsocket-java](https://github.com/rsocket/rsocket-java), and later we will have a look at the RSocket integration provided in the latest Spring framework (and Spring Boot).
13 |
14 | The following example is showing **request/response** usage with rsocket-java.
15 |
16 | First of all, create a RSocket server and run it on localhost:7000.
17 |
18 | ```java
19 | final AbstractRSocket responseHandler = new AbstractRSocket() {
20 |
21 | @Override
22 | public Mono requestResponse(Payload payload) {
23 | log.info("received request-response payload: {}", payload.getDataUtf8());
24 | return Mono.just(DefaultPayload.create("received (" + payload.getDataUtf8() + ") at " + Instant.now()));
25 | }
26 | };
27 |
28 | RSocketFactory.receive()
29 | .acceptor((setupPayload, reactiveSocket) -> Mono.just(responseHandler))
30 | .transport(TcpServerTransport.create("localhost", PORT))
31 | .start()
32 | .block();
33 | ```
34 |
35 |
36 |
37 | In the above codes:
38 |
39 | * The `receive()` means it will receive the request from client.
40 | * The `acceptor` defines how to process the request, it accept a `SocketAcceptor` class. It is the place we can embed our handler for processing the incoming request. `AbstractRSocket` is a convenient class which provides methods for all interactive models supported in RSocket. As an example, here we only need to handle the **request/response** model by overriding the `requestResponse` method.
41 | * The `transport` specifies the server information, including host, port, protocol, etc. Here we use TCP as protocol, and run it on localhost at port 7000.
42 |
43 | Next create a client to connect the existing server and send some data to it.
44 |
45 | ```java
46 | RSocketFactory.connect()
47 | .transport(TcpClientTransport.create("localhost", PORT))
48 | .start()
49 | .flatMap(r -> r.requestResponse(DefaultPayload.create("Hello")))
50 | .subscribe(r -> log.info("handled result:#" + r.getDataUtf8()));
51 | ```
52 |
53 |
54 |
55 | In the above codes:
56 |
57 | * The `connect` indicates the current client will connect to server.
58 | * The `transport` provides the server info which it will connect to.
59 | * The `start` method returns a `RSocket`, it can be used to interact with server side. Here we send a `requestResponse` type request, it requires a response from server.
60 | * Finally, we can use `subcribe` to display the received response from server.
61 |
62 | Spring integrated RSocket into its messaging infrastructure, and it defines a `RSocketStrategies ` to allow you encode and decode the RSocket payload via Jackson, besides a `RSocketRequester` is used to interact with the server side.
63 |
64 |
65 |
66 | Using [Spring initializr](https://start.spring.io), you can generate a Spring Boot project skeleton in seconds.
67 |
68 | * Project type: Maven
69 | * Spring Boot:2.2.0.M5
70 | * Project Metadata:
71 | * artifact : server
72 | * Options/Java : 11
73 | * Dependencies: RSocket, Lombok
74 |
75 | The generated codes are archived into a zip file for downloading. Download and extract it into your favorite IDE. Open the *pom.xml* in your IDE editor, there are two dependencies added.
76 |
77 | ```xml
78 |
79 | org.springframework.boot
80 | spring-boot-starter-rsocket
81 |
82 |
83 |
84 | org.projectlombok
85 | lombok
86 | true
87 |
88 | ```
89 |
90 | The `spring-boot-starter-rsocket` includes auto-configurations for RSocket integration. For the server side, it will create a Roscket server automatically from `RSocketProperties`. For example, we defines the server info in the *application.properties*.
91 |
92 | ```pro
93 | spring.rsocket.server.port=7000
94 | spring.rsocket.server.transport=tcp
95 | ```
96 |
97 | Start the application in IDE or run `mvn spring-boot:run`, you will see the server is running at localhost:7000.
98 |
99 | 
100 |
101 | > You can also use Rsosket with Webflux , just add extra `spring-boot-starter-webflux` in the project dependencies.
102 |
103 | Create a messaging controller .
104 |
105 | ```java
106 | @Controller
107 | @Slf4j
108 | class GreetingServerController {
109 |
110 | @MessageMapping("hello")
111 | public Mono hello(Greeting p) {
112 | log.info("received: {} at {}", p, Instant.now());
113 | return Mono.empty();
114 | }
115 |
116 | }
117 |
118 | @Data
119 | class Greeting {
120 | String name;
121 | }
122 | ```
123 |
124 |
125 |
126 | It accepts a `Greeting` payload, return an `Mono.empty`. Let's create a client application to shake hands with it. Similarly generate it via [Spring initializr](https://start.spring.io).
127 |
128 | * Project type: Maven
129 | * Spring Boot:2.2.0.M5
130 | * Project Metadata:
131 | * artifact : client
132 | * Options/Java : 11
133 | * Dependencies: RSocket, Reactive Web, Lombok
134 |
135 | An extra `spring-boot-starter-webflux` is added because this client is a reactive web application, and it will run at port 8080.
136 |
137 | Declare a `RSocketRequester` bean firstly. We use `RSocketRequester` to interact the RSocket at port 7000.
138 |
139 | ```java
140 | @Bean
141 | public RSocketRequester rSocketRequester(RSocketRequester.Builder b) {
142 | return b.connectTcp("localhost", 7000).block();
143 | }
144 | ```
145 |
146 | Create a `@RestController` to send a greeting message to the server side.
147 |
148 | ```java
149 | @RestController
150 | @RequiredArgsConstructor
151 | class GreetingController {
152 |
153 | private final RSocketRequester requester;
154 |
155 | @GetMapping
156 | Mono hello() {
157 | return this.requester.route("hello").data(new Greeting("Welcome to Rsocket")).send();
158 | }
159 |
160 | }
161 |
162 | @Data
163 | @AllArgsConstructor
164 | class Greeting {
165 | String name;
166 | }
167 |
168 | ```
169 |
170 | Start the client and server respectively. And try to access `http://localhost:8080` by `curl` .
171 |
172 | ```bash
173 | curl http://localhost:8080
174 | ```
175 |
176 | In the output console of the server application, you can see the information like the following.
177 |
178 | 
179 |
180 | As you see, the sent message is received.
181 |
182 | Check the source codes from [Github](https://github.com/hantsy/rsocket-sample).
183 |
184 |
--------------------------------------------------------------------------------
/docs/_config.yml:
--------------------------------------------------------------------------------
1 | theme: jekyll-theme-cayman
2 | title: Spring RSocket by Examples
3 | description: Tips of using RSocket and Spring RSocket
4 |
--------------------------------------------------------------------------------
/docs/crud.md:
--------------------------------------------------------------------------------
1 | # Building a CRUD application with RSocket and Spring
2 |
3 | In [the last post](https://medium.com/@hantsy/using-rsocket-with-spring-boot-cfc67924d06a), we explored the basic RSocket support in Spring and Spring Boot. In this post, we will create a CRUD application which is closer to the real world applications.
4 |
5 | We will create a *client* and *server* applications to demonstrate the interactions between RSocket client and server side.
6 |
7 | Firstly let's create the server application.
8 |
9 | You can simply generate a project template from [Spring initializr](https://start.spring.io), set the following properties.
10 |
11 |
12 | * Build: Maven
13 | * Java: 11
14 | * Spring Boot version: 2.3.0.M3(I preferred the new version for practicing new techniques)
15 | * Dependencies: RSocket, Spring Data R2dbc, H2 Database, Lombok
16 |
17 | > If you are new to Spring Data R2dbc, check the post [ Accessing RDBMS with Spring Data R2dbc](https://medium.com/@hantsy/reactive-accessing-rdbms-with-spring-data-r2dbc-d6e453f2837e).
18 |
19 | In the server application, we will use RSocket to serve a RSocket server via TCP protocol.
20 |
21 | Open the *src/main/resources/application.properties*, add the following properties.
22 |
23 | ```properties
24 | spring.rsocket.server.port=7000
25 | spring.rsocket.server.transport=tcp
26 | ```
27 |
28 | Like what I have done in the former posts, firstly create a simple POJO.
29 |
30 | ```java
31 | @Data
32 | @ToString
33 | @Builder
34 | @NoArgsConstructor
35 | @AllArgsConstructor
36 | @Table("posts")
37 | class Post {
38 |
39 | @Id
40 | @Column("id")
41 | private Integer id;
42 |
43 | @Column("title")
44 | private String title;
45 |
46 | @Column("content")
47 | private String content;
48 |
49 | }
50 | ```
51 |
52 | And create a simple Repository for `Post`.
53 |
54 | ```java
55 |
56 | interface PostRepository extends R2dbcRepository {
57 | }
58 | ```
59 |
60 | Create a `Controller` class to handle the request messages.
61 |
62 | ```java
63 | @Controller
64 | @RequiredArgsConstructor
65 | class PostController {
66 |
67 | private final PostRepository posts;
68 |
69 | @MessageMapping("posts.findAll")
70 | public Flux all() {
71 | return this.posts.findAll();
72 | }
73 |
74 | @MessageMapping("posts.findById.{id}")
75 | public Mono get(@DestinationVariable("id") Integer id) {
76 | return this.posts.findById(id);
77 | }
78 |
79 | @MessageMapping("posts.save")
80 | public Mono create(@Payload Post post) {
81 | return this.posts.save(post);
82 | }
83 |
84 | @MessageMapping("posts.update.{id}")
85 | public Mono update(@DestinationVariable("id") Integer id, @Payload Post post) {
86 | return this.posts.findById(id)
87 | .map(p -> {
88 | p.setTitle(post.getTitle());
89 | p.setContent(post.getContent());
90 |
91 | return p;
92 | })
93 | .flatMap(p -> this.posts.save(p));
94 | }
95 |
96 | @MessageMapping("posts.deleteById.{id}")
97 | public Mono delete(@DestinationVariable("id") Integer id) {
98 | return this.posts.deleteById(id);
99 | }
100 |
101 | }
102 | ```
103 |
104 | Create a `schema.sql` and a `data.sql` to create tables and initialize the data.
105 |
106 | ```sql
107 | -- schema.sql
108 | CREATE TABLE posts (id SERIAL PRIMARY KEY, title VARCHAR(255), content VARCHAR(255));
109 | ```
110 |
111 | ```sql
112 | -- data.sql
113 | DELETE FROM posts;
114 | INSERT INTO posts (title, content) VALUES ('post one in data.sql', 'content of post one in data.sql');
115 | ```
116 | > Note: In the Spring 2.3.0.M3, Spring Data R2dbc is merged in the Spring Data release train. But unfortunately, the auto-configuration of `ConnectionFactoryInitializer` is NOT ported.
117 |
118 | To make sure the the `schema.sql` and `data.sql` are loaded and executed at the application startup, declare a `ConnectionFactoryInitializer` bean yourself.
119 |
120 | ```java
121 | @Bean
122 | public ConnectionFactoryInitializer initializer(ConnectionFactory connectionFactory) {
123 |
124 | ConnectionFactoryInitializer initializer = new ConnectionFactoryInitializer();
125 | initializer.setConnectionFactory(connectionFactory);
126 |
127 | CompositeDatabasePopulator populator = new CompositeDatabasePopulator();
128 | populator.addPopulators(new ResourceDatabasePopulator(new ClassPathResource("schema.sql")));
129 | populator.addPopulators(new ResourceDatabasePopulator(new ClassPathResource("data.sql")));
130 | initializer.setDatabasePopulator(populator);
131 |
132 | return initializer;
133 | }
134 | ```
135 |
136 | Start the server application.
137 |
138 | ```bash
139 | mvn spring-boot:run
140 | ```
141 |
142 | Now let's move to the client application.
143 |
144 | Similarly, generate a project template from [Spring Initializr](https://start.spring.io), in the *Dependencies* area, ensure you have chosen *WebFlux*, *RSocket*, *Lombok*.
145 |
146 | The client application is a generic Webflux application, but uses `RSocketRequester` to shake hands with the RSocket server.
147 |
148 | Declare a `RSocketRequester` bean to connect localhost:7000 via the TCP protocol.
149 |
150 | ```java
151 | @Bean
152 | public RSocketRequester rSocketRequester(RSocketRequester.Builder b) {
153 | return b.dataMimeType(MimeTypeUtils.APPLICATION_JSON)
154 | .connectTcp("localhost", 7000)
155 | .block();
156 | }
157 | ```
158 |
159 | Create a generic `RestController` and use the `RSocketRequester` bean to communicate with the RSocket server.
160 |
161 | ```java
162 | @Slf4j
163 | @RequiredArgsConstructor
164 | @RestController()
165 | @RequestMapping("/posts")
166 | class PostClientController {
167 |
168 | private final RSocketRequester requester;
169 |
170 | @GetMapping("")
171 | Flux all() {
172 | return this.requester.route("posts.findAll")
173 | .retrieveFlux(Post.class);
174 | }
175 |
176 | @GetMapping("{id}")
177 | Mono findById(@PathVariable Integer id) {
178 | return this.requester.route("posts.findById." + id)
179 | .retrieveMono(Post.class);
180 | }
181 |
182 | @PostMapping("")
183 | Mono save(@RequestBody Post post) {
184 | return this.requester.route("posts.save")
185 | .data(post)
186 | .retrieveMono(Post.class);
187 | }
188 |
189 | @PutMapping("{id}")
190 | Mono update(@PathVariable Integer id, @RequestBody Post post) {
191 | return this.requester.route("posts.update."+ id)
192 | .data(post)
193 | .retrieveMono(Post.class);
194 | }
195 |
196 | @DeleteMapping("{id}")
197 | Mono delete(@PathVariable Integer id) {
198 | return this.requester.route("posts.deleteById."+ id).send();
199 | }
200 |
201 | }
202 | ```
203 |
204 | Create a POJO `Post` to present the RSocket message payload that transferred between the client and server side.
205 |
206 | ```java
207 | @Data
208 | @ToString
209 | @Builder
210 | @NoArgsConstructor
211 | @AllArgsConstructor
212 | class Post {
213 | private Integer id;
214 | private String title;
215 | private String content;
216 | }
217 | ```
218 | Start up the client application.
219 |
220 | Try to test the CRUD operations by curl.
221 |
222 |
223 | ```bash
224 | # curl http://localhost:8080/posts
225 | [{"id":1,"title":"post one in data.sql","content":"content of post one in data.sql"},{"id":2,"title":"Post one","content":"The content of post one"},{"id":3,"title":"Post tow","content":"The content of post tow"}]
226 |
227 | # curl http://localhost:8080/posts/1
228 | {"id":1,"title":"post one in data.sql","content":"content of post one in data.sql"}
229 |
230 | # curl http://localhost:8080/posts/3
231 | {"id":3,"title":"Post tow","content":"The content of post tow"}
232 |
233 | # curl http://localhost:8080/posts/2
234 | {"id":2,"title":"Post one","content":"The content of post one"}
235 |
236 | # curl http://localhost:8080/posts -d "{\"title\":\"my save title\", \"content\":\"my content of my post\"}" -H "Content-Type:application/json" -X POST
237 | {"id":4,"title":"my save title","content":"my content of my post"}
238 |
239 | # curl http://localhost:8080/posts
240 | [{"id":1,"title":"post one in data.sql","content":"content of post one in data.sql"},{"id":2,"title":"Post one","content":"The content of post one"},{"id":3,"title":"Post tow","content":"The content of post tow"},{"id":4,"title":"my save title","content":"update my content of my post"}]
241 |
242 | # curl http://localhost:8080/posts/4 -X DELETE
243 |
244 | # curl http://localhost:8080/posts
245 | [{"id":1,"title":"post one in data.sql","content":"content of post one in data.sql"},{"id":2,"title":"Post one","content":"The content of post one"},{"id":3,"title":"Post tow","content":"The content of post tow"}]
246 | ```
247 |
248 | As a bonus, try to add a filter to find the posts by keyword.
249 |
250 | In the server application, create a new method in the `PostRepository`.
251 |
252 | ```java
253 | @Query("SELECT * FROM posts WHERE title like $1")
254 | Flux findByTitleContains(String name);
255 | ```
256 |
257 | And in the `PostController` , create a new route to handle this request from client.
258 |
259 | ```java
260 | class PostController {
261 | //...
262 | @MessageMapping("posts.titleContains")
263 | public Flux titleContains(@Payload String title) {
264 | return this.posts.findByTitleContains(title);
265 | }
266 | //...
267 | }
268 | ```
269 |
270 | In the client side, change the `PostClientController` 's `all` method to the following:
271 |
272 | ```java
273 | class PostClientController {
274 | //...
275 | Flux all(@RequestParam(name = "title", required = false) String title) {
276 | if (StringUtils.hasText(title)) {
277 | return this.requester.route("posts.titleContains")
278 | .data(title).retrieveFlux(Post.class);
279 | } else {
280 | return this.requester.route("posts.findAll")
281 | .retrieveFlux(Post.class);
282 | }
283 | }
284 | //...
285 | }
286 | ```
287 |
288 | Now, try to add an extra `title` request parameter to access http://localhost:8080/posts.
289 |
290 | Get the [source codes](https://github.com/hantsy/rsocket-sample/tree/master/crud) from my Github.
291 |
292 |
--------------------------------------------------------------------------------
/docs/index.md:
--------------------------------------------------------------------------------
1 | * [Using Rsocket with Spring Boot](./GUIDE.md)([medium's link](https://medium.com/@hantsy/using-rsocket-with-spring-boot-cfc67924d06a))
2 | * [Building a CRUD application with RSocket and Spring](./crud.md)
--------------------------------------------------------------------------------
/docs/msg.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/hantsy/rsocket-sample/7349fd955764b163ac061b00d30d8a8646a0fcdd/docs/msg.png
--------------------------------------------------------------------------------
/docs/rsocket.svg:
--------------------------------------------------------------------------------
1 |
2 |
3 |
--------------------------------------------------------------------------------
/docs/run.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/hantsy/rsocket-sample/7349fd955764b163ac061b00d30d8a8646a0fcdd/docs/run.png
--------------------------------------------------------------------------------
/docs/spring.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/hantsy/rsocket-sample/7349fd955764b163ac061b00d30d8a8646a0fcdd/docs/spring.jpg
--------------------------------------------------------------------------------
/docs/springboot.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/hantsy/rsocket-sample/7349fd955764b163ac061b00d30d8a8646a0fcdd/docs/springboot.png
--------------------------------------------------------------------------------
/integration/client-regular/.gitignore:
--------------------------------------------------------------------------------
1 | HELP.md
2 | target/
3 | !.mvn/wrapper/maven-wrapper.jar
4 | !**/src/main/**
5 | !**/src/test/**
6 |
7 | ### STS ###
8 | .apt_generated
9 | .classpath
10 | .factorypath
11 | .project
12 | .settings
13 | .springBeans
14 | .sts4-cache
15 |
16 | ### IntelliJ IDEA ###
17 | .idea
18 | *.iws
19 | *.iml
20 | *.ipr
21 |
22 | ### NetBeans ###
23 | /nbproject/private/
24 | /nbbuild/
25 | /dist/
26 | /nbdist/
27 | /.nb-gradle/
28 | build/
29 |
30 | ### VS Code ###
31 | .vscode/
32 |
--------------------------------------------------------------------------------
/integration/client-regular/nbactions.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | run
5 |
6 | jar
7 |
8 |
9 | spring-boot:run
10 |
11 |
12 | -noverify -XX:TieredStopAtLevel=1
13 | com.example.demo.ProducerApplication
14 | always
15 |
16 |
17 |
18 | debug
19 |
20 | jar
21 |
22 |
23 | spring-boot:run
24 |
25 |
26 | -Xdebug -Xrunjdwp:transport=dt_socket,server=n,address=${jpda.address} -noverify -XX:TieredStopAtLevel=1
27 | com.example.demo.ProducerApplication
28 | always
29 | true
30 |
31 |
32 |
33 | profile
34 |
35 | jar
36 |
37 |
38 | process-classes
39 | org.codehaus.mojo:exec-maven-plugin:1.2.1:exec
40 |
41 |
42 | -classpath %classpath com.example.demo.ProducerApplication
43 | java
44 |
45 |
46 |
47 |
--------------------------------------------------------------------------------
/integration/client-regular/pom.xml:
--------------------------------------------------------------------------------
1 |
2 |
4 | 4.0.0
5 |
6 | org.springframework.boot
7 | spring-boot-starter-parent
8 | 2.3.0.RELEASE
9 |
10 |
11 | com.example
12 | rsocket-sample-integration-client-regular
13 | 0.0.1-SNAPSHOT
14 | rsocket-sample-integration-client-regular
15 | Demo project for Spring Boot
16 |
17 |
18 | 11
19 |
20 |
21 |
22 |
23 |
24 | org.springframework.boot
25 | spring-boot-starter-webflux
26 |
27 |
28 |
29 | org.springframework.boot
30 | spring-boot-starter-rsocket
31 |
32 |
33 |
34 | org.springframework.boot
35 | spring-boot-starter-test
36 | test
37 |
38 |
39 | org.junit.vintage
40 | junit-vintage-engine
41 |
42 |
43 |
44 |
45 | org.springframework.integration
46 | spring-integration-test
47 | test
48 |
49 |
50 | io.projectreactor
51 | reactor-test
52 | test
53 |
54 |
55 |
56 |
57 |
58 |
59 | org.springframework.boot
60 | spring-boot-maven-plugin
61 |
62 |
63 |
64 |
65 |
66 |
67 | spring-milestones
68 | Spring Milestones
69 | https://repo.spring.io/milestone
70 |
71 |
72 |
73 |
74 | spring-milestones
75 | Spring Milestones
76 | https://repo.spring.io/milestone
77 |
78 |
79 |
80 |
81 |
--------------------------------------------------------------------------------
/integration/client-regular/src/main/java/com/example/demo/DemoApplication.java:
--------------------------------------------------------------------------------
1 | package com.example.demo;
2 |
3 | import org.springframework.boot.SpringApplication;
4 | import org.springframework.boot.autoconfigure.SpringBootApplication;
5 | import org.springframework.http.MediaType;
6 | import org.springframework.messaging.rsocket.RSocketRequester;
7 | import org.springframework.web.bind.annotation.GetMapping;
8 | import org.springframework.web.bind.annotation.RestController;
9 | import reactor.core.publisher.Flux;
10 | import reactor.core.publisher.Mono;
11 |
12 | @SpringBootApplication
13 | public class DemoApplication {
14 |
15 | public static void main(String[] args) {
16 | SpringApplication.run(DemoApplication.class, args);
17 | }
18 |
19 | }
20 |
21 | @RestController
22 | class HelloController {
23 | Mono requesterMono;
24 |
25 | public HelloController(RSocketRequester.Builder builder) {
26 | this.requesterMono = builder.connectTcp("localhost", 7000);
27 | }
28 |
29 | @GetMapping(value = "hello", produces = MediaType.TEXT_EVENT_STREAM_VALUE)
30 | public Flux uppercase() {
31 | return requesterMono.flatMapMany(
32 | rSocketRequester -> rSocketRequester.route("/uppercase")
33 | .data(Flux.just("a", "b", "c", "d"))
34 | .retrieveFlux(String.class)
35 | );
36 | }
37 | }
--------------------------------------------------------------------------------
/integration/client-regular/src/main/resources/application.properties:
--------------------------------------------------------------------------------
1 | logging.level.org.springframework.integration=DEBUG
2 |
3 |
4 |
--------------------------------------------------------------------------------
/integration/client/.gitignore:
--------------------------------------------------------------------------------
1 | HELP.md
2 | target/
3 | !.mvn/wrapper/maven-wrapper.jar
4 | !**/src/main/**
5 | !**/src/test/**
6 |
7 | ### STS ###
8 | .apt_generated
9 | .classpath
10 | .factorypath
11 | .project
12 | .settings
13 | .springBeans
14 | .sts4-cache
15 |
16 | ### IntelliJ IDEA ###
17 | .idea
18 | *.iws
19 | *.iml
20 | *.ipr
21 |
22 | ### NetBeans ###
23 | /nbproject/private/
24 | /nbbuild/
25 | /dist/
26 | /nbdist/
27 | /.nb-gradle/
28 | build/
29 |
30 | ### VS Code ###
31 | .vscode/
32 |
--------------------------------------------------------------------------------
/integration/client/nbactions.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | run
5 |
6 | jar
7 |
8 |
9 | spring-boot:run
10 |
11 |
12 | -noverify -XX:TieredStopAtLevel=1
13 | com.example.demo.ProducerApplication
14 | always
15 |
16 |
17 |
18 | debug
19 |
20 | jar
21 |
22 |
23 | spring-boot:run
24 |
25 |
26 | -Xdebug -Xrunjdwp:transport=dt_socket,server=n,address=${jpda.address} -noverify -XX:TieredStopAtLevel=1
27 | com.example.demo.ProducerApplication
28 | always
29 | true
30 |
31 |
32 |
33 | profile
34 |
35 | jar
36 |
37 |
38 | process-classes
39 | org.codehaus.mojo:exec-maven-plugin:1.2.1:exec
40 |
41 |
42 | -classpath %classpath com.example.demo.ProducerApplication
43 | java
44 |
45 |
46 |
47 |
--------------------------------------------------------------------------------
/integration/client/pom.xml:
--------------------------------------------------------------------------------
1 |
2 |
4 | 4.0.0
5 |
6 | org.springframework.boot
7 | spring-boot-starter-parent
8 | 2.3.0.RELEASE
9 |
10 |
11 | com.example
12 | rsocket-sample-integration-client
13 | 0.0.1-SNAPSHOT
14 | rsocket-sample-integration-client
15 | Demo project for Spring Boot
16 |
17 |
18 | 11
19 |
20 |
21 |
22 |
23 |
24 | org.springframework.boot
25 | spring-boot-starter-webflux
26 |
27 |
28 |
29 | org.springframework.boot
30 | spring-boot-starter-integration
31 |
32 |
33 |
34 | org.springframework.integration
35 | spring-integration-rsocket
36 |
37 |
38 |
39 | org.projectlombok
40 | lombok
41 | true
42 |
43 |
44 | org.springframework.boot
45 | spring-boot-starter-test
46 | test
47 |
48 |
49 | org.junit.vintage
50 | junit-vintage-engine
51 |
52 |
53 |
54 |
55 | org.springframework.integration
56 | spring-integration-test
57 | test
58 |
59 |
60 | io.projectreactor
61 | reactor-test
62 | test
63 |
64 |
65 |
66 |
67 |
68 |
69 | org.springframework.boot
70 | spring-boot-maven-plugin
71 |
72 |
73 |
74 |
75 |
76 |
77 | spring-milestones
78 | Spring Milestones
79 | https://repo.spring.io/milestone
80 |
81 |
82 |
83 |
84 | spring-milestones
85 | Spring Milestones
86 | https://repo.spring.io/milestone
87 |
88 |
89 |
90 |
91 |
--------------------------------------------------------------------------------
/integration/client/src/main/java/com/example/demo/DemoApplication.java:
--------------------------------------------------------------------------------
1 | package com.example.demo;
2 |
3 | import org.springframework.beans.factory.annotation.Autowired;
4 | import org.springframework.beans.factory.annotation.Qualifier;
5 | import org.springframework.boot.SpringApplication;
6 | import org.springframework.boot.autoconfigure.SpringBootApplication;
7 | import org.springframework.context.annotation.Bean;
8 | import org.springframework.context.annotation.Lazy;
9 | import org.springframework.http.MediaType;
10 | import org.springframework.integration.config.EnableIntegration;
11 | import org.springframework.integration.dsl.IntegrationFlow;
12 | import org.springframework.integration.dsl.IntegrationFlows;
13 | import org.springframework.integration.rsocket.ClientRSocketConnector;
14 | import org.springframework.integration.rsocket.RSocketInteractionModel;
15 | import org.springframework.integration.rsocket.dsl.RSockets;
16 | import org.springframework.web.bind.annotation.GetMapping;
17 | import org.springframework.web.bind.annotation.RestController;
18 | import reactor.core.publisher.Flux;
19 |
20 | import java.util.function.Function;
21 |
22 | @SpringBootApplication
23 | @EnableIntegration
24 | public class DemoApplication {
25 |
26 | public static void main(String[] args) {
27 | SpringApplication.run(DemoApplication.class, args);
28 | }
29 |
30 | // see PR: https://github.com/spring-projects/spring-boot/pull/18834
31 | @Bean
32 | public ClientRSocketConnector clientRSocketConnector() {
33 | ClientRSocketConnector clientRSocketConnector = new ClientRSocketConnector("localhost", 7000);
34 | clientRSocketConnector.setAutoStartup(false);
35 | return clientRSocketConnector;
36 | }
37 |
38 | @Bean
39 | public IntegrationFlow rsocketUpperCaseRequestFlow(ClientRSocketConnector clientRSocketConnector) {
40 | return IntegrationFlows
41 | .from(Function.class)
42 | .handle(RSockets.outboundGateway("/uppercase")
43 | .interactionModel((message) -> RSocketInteractionModel.requestChannel)
44 | .expectedResponseType("T(java.lang.String)")
45 | .clientRSocketConnector(clientRSocketConnector))
46 | .get();
47 | }
48 | }
49 |
50 | @RestController
51 | class HelloController {
52 |
53 | @Autowired()
54 | @Lazy
55 | @Qualifier("rsocketUpperCaseRequestFlow.gateway")
56 | private Function, Flux> rsocketUpperCaseFlowFunction;
57 |
58 | @GetMapping(value = "hello", produces = MediaType.TEXT_EVENT_STREAM_VALUE)
59 | public Flux uppercase() {
60 | return rsocketUpperCaseFlowFunction.apply(Flux.just("a", "b", "c", "d"));
61 | }
62 | }
--------------------------------------------------------------------------------
/integration/client/src/main/resources/application.properties:
--------------------------------------------------------------------------------
1 | logging.level.org.springframework.integration=DEBUG
2 |
3 | # auto configure ClientRSocketConnector via tcp
4 | #spring.integration.rsocket.client.port=7000
5 | #spring.integration.rsocket.client.host=localhost
6 |
7 | # auto configure ClientRSocketConnector via websocket
8 | #spring.integration.rsocket.client.uri=ws://localhost:7000/rsocket
9 |
--------------------------------------------------------------------------------
/integration/server-regular/.gitignore:
--------------------------------------------------------------------------------
1 | HELP.md
2 | target/
3 | !.mvn/wrapper/maven-wrapper.jar
4 | !**/src/main/**
5 | !**/src/test/**
6 |
7 | ### STS ###
8 | .apt_generated
9 | .classpath
10 | .factorypath
11 | .project
12 | .settings
13 | .springBeans
14 | .sts4-cache
15 |
16 | ### IntelliJ IDEA ###
17 | .idea
18 | *.iws
19 | *.iml
20 | *.ipr
21 |
22 | ### NetBeans ###
23 | /nbproject/private/
24 | /nbbuild/
25 | /dist/
26 | /nbdist/
27 | /.nb-gradle/
28 | build/
29 |
30 | ### VS Code ###
31 | .vscode/
32 |
--------------------------------------------------------------------------------
/integration/server-regular/pom.xml:
--------------------------------------------------------------------------------
1 |
2 |
4 | 4.0.0
5 |
6 | org.springframework.boot
7 | spring-boot-starter-parent
8 | 2.3.0.RELEASE
9 |
10 |
11 | com.example
12 | rsocket-sample-integration-server-regular
13 | 0.0.1-SNAPSHOT
14 | rsocket-sample-integration-boot-server-regular
15 | Demo project for Spring Boot
16 |
17 |
18 | 11
19 |
20 |
21 |
22 |
23 |
24 | org.springframework.boot
25 | spring-boot-starter-rsocket
26 |
27 |
28 |
29 | org.projectlombok
30 | lombok
31 | true
32 |
33 |
34 | org.springframework.boot
35 | spring-boot-starter-test
36 | test
37 |
38 |
39 | org.junit.vintage
40 | junit-vintage-engine
41 |
42 |
43 |
44 |
45 | io.projectreactor
46 | reactor-test
47 | test
48 |
49 |
50 |
51 |
52 |
53 |
54 | org.springframework.boot
55 | spring-boot-maven-plugin
56 |
57 |
58 |
59 |
60 |
61 |
62 | spring-milestones
63 | Spring Milestones
64 | https://repo.spring.io/milestone
65 |
66 |
67 |
68 |
69 | spring-milestones
70 | Spring Milestones
71 | https://repo.spring.io/milestone
72 |
73 |
74 |
75 |
76 |
--------------------------------------------------------------------------------
/integration/server-regular/src/main/java/com/example/demo/DemoApplication.java:
--------------------------------------------------------------------------------
1 | package com.example.demo;
2 |
3 | import org.springframework.boot.SpringApplication;
4 | import org.springframework.boot.autoconfigure.SpringBootApplication;
5 | import org.springframework.messaging.handler.annotation.MessageMapping;
6 | import org.springframework.stereotype.Controller;
7 | import reactor.core.publisher.Flux;
8 |
9 | @SpringBootApplication
10 | public class DemoApplication {
11 |
12 | public static void main(String[] args) {
13 | SpringApplication.run(DemoApplication.class, args);
14 | }
15 |
16 | }
17 |
18 | @Controller
19 | class UpperCaseHandler {
20 |
21 | @MessageMapping("/uppercase")
22 | public Flux uppercase(Flux input) {
23 | return input.map(String::toUpperCase);
24 | }
25 | }
26 |
27 |
--------------------------------------------------------------------------------
/integration/server-regular/src/main/resources/application.properties:
--------------------------------------------------------------------------------
1 | spring.rsocket.server.transport=tcp
2 | spring.rsocket.server.port=7000
3 | logging.level.org.springframework.messaging.rsocket=DEBUG
4 |
5 |
--------------------------------------------------------------------------------
/integration/server-vanilla/.gitignore:
--------------------------------------------------------------------------------
1 | HELP.md
2 | target/
3 | !.mvn/wrapper/maven-wrapper.jar
4 | !**/src/main/**
5 | !**/src/test/**
6 |
7 | ### STS ###
8 | .apt_generated
9 | .classpath
10 | .factorypath
11 | .project
12 | .settings
13 | .springBeans
14 | .sts4-cache
15 |
16 | ### IntelliJ IDEA ###
17 | .idea
18 | *.iws
19 | *.iml
20 | *.ipr
21 |
22 | ### NetBeans ###
23 | /nbproject/private/
24 | /nbbuild/
25 | /dist/
26 | /nbdist/
27 | /.nb-gradle/
28 | build/
29 |
30 | ### VS Code ###
31 | .vscode/
32 |
--------------------------------------------------------------------------------
/integration/server-vanilla/nbactions.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | run
5 |
6 | jar
7 |
8 |
9 | spring-boot:run
10 |
11 |
12 | -noverify -XX:TieredStopAtLevel=1
13 | com.example.demo.ProducerApplication
14 | always
15 |
16 |
17 |
18 | debug
19 |
20 | jar
21 |
22 |
23 | spring-boot:run
24 |
25 |
26 | -Xdebug -Xrunjdwp:transport=dt_socket,server=n,address=${jpda.address} -noverify -XX:TieredStopAtLevel=1
27 | com.example.demo.ProducerApplication
28 | always
29 | true
30 |
31 |
32 |
33 | profile
34 |
35 | jar
36 |
37 |
38 | process-classes
39 | org.codehaus.mojo:exec-maven-plugin:1.2.1:exec
40 |
41 |
42 | -classpath %classpath com.example.demo.ProducerApplication
43 | java
44 |
45 |
46 |
47 |
--------------------------------------------------------------------------------
/integration/server-vanilla/pom.xml:
--------------------------------------------------------------------------------
1 |
2 |
4 | 4.0.0
5 |
6 | org.springframework.boot
7 | spring-boot-starter-parent
8 | 2.3.0.RELEASE
9 |
10 |
11 | com.example
12 | rsocket-sample-integration-server-vanilla
13 | 0.0.1-SNAPSHOT
14 | rsocket-sample-integration-server-vanilla
15 | Demo project for Spring Boot
16 |
17 |
18 | 11
19 |
20 |
21 |
22 |
23 |
24 | org.springframework.integration
25 | spring-integration-rsocket
26 |
27 |
28 |
29 | org.junit.jupiter
30 | junit-jupiter-engine
31 | test
32 |
33 |
34 | org.springframework.integration
35 | spring-integration-test
36 | test
37 |
38 |
39 | io.projectreactor
40 | reactor-test
41 | test
42 |
43 |
44 |
45 |
46 |
47 |
48 | org.springframework.boot
49 | spring-boot-maven-plugin
50 |
51 |
52 |
53 |
54 |
55 |
56 | spring-milestones
57 | Spring Milestones
58 | https://repo.spring.io/milestone
59 |
60 |
61 |
62 |
63 | spring-milestones
64 | Spring Milestones
65 | https://repo.spring.io/milestone
66 |
67 |
68 |
69 |
70 |
--------------------------------------------------------------------------------
/integration/server-vanilla/src/main/java/com/example/demo/DemoApplication.java:
--------------------------------------------------------------------------------
1 | package com.example.demo;
2 |
3 | import org.springframework.context.ConfigurableApplicationContext;
4 | import org.springframework.context.annotation.AnnotationConfigApplicationContext;
5 | import org.springframework.context.annotation.Bean;
6 | import org.springframework.context.annotation.Configuration;
7 | import org.springframework.core.ResolvableType;
8 | import org.springframework.integration.config.EnableIntegration;
9 | import org.springframework.integration.dsl.IntegrationFlow;
10 | import org.springframework.integration.dsl.IntegrationFlows;
11 | import org.springframework.integration.rsocket.RSocketInteractionModel;
12 | import org.springframework.integration.rsocket.ServerRSocketConnector;
13 | import org.springframework.integration.rsocket.dsl.RSockets;
14 | import reactor.core.publisher.Flux;
15 |
16 | import java.io.IOException;
17 |
18 | @Configuration
19 | @EnableIntegration
20 | public class DemoApplication {
21 |
22 | public static void main(String[] args) throws IOException {
23 | try (ConfigurableApplicationContext ctx = new AnnotationConfigApplicationContext(DemoApplication.class)) {
24 | System.out.println("Press any key to exit.");
25 | System.in.read();
26 | } finally {
27 | System.out.println("Exited.");
28 | }
29 |
30 | }
31 |
32 | @Bean
33 | public ServerRSocketConnector serverRSocketConnector() {
34 | return new ServerRSocketConnector("localhost", 7000);
35 | }
36 |
37 | @Bean
38 | public IntegrationFlow rsocketUpperCaseFlow(ServerRSocketConnector serverRSocketConnector) {
39 | return IntegrationFlows
40 | .from(RSockets.inboundGateway("/uppercase")
41 | .requestElementType(ResolvableType.forClass(String.class))
42 | .interactionModels(RSocketInteractionModel.requestChannel)
43 | .rsocketConnector(serverRSocketConnector)
44 | )
45 | ., Flux>transform((flux) -> flux.map(String::toUpperCase))
46 | .get();
47 | }
48 |
49 | }
50 |
--------------------------------------------------------------------------------
/integration/server-vanilla/src/main/resources/application.properties:
--------------------------------------------------------------------------------
1 | logging.level.org.springframework.integration=DEBUG
2 |
3 |
--------------------------------------------------------------------------------
/integration/server-vanilla/src/test/java/com/example/demo/DemoApplicationTests.java:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | package com.example.demo;
5 |
6 | import org.junit.jupiter.api.AfterEach;
7 | import org.junit.jupiter.api.BeforeEach;
8 | import org.junit.jupiter.api.Test;
9 | import org.springframework.beans.factory.annotation.Autowired;
10 | import org.springframework.beans.factory.annotation.Qualifier;
11 | import org.springframework.context.annotation.AnnotationConfigApplicationContext;
12 | import org.springframework.context.annotation.Bean;
13 | import org.springframework.context.annotation.Configuration;
14 | import org.springframework.integration.dsl.IntegrationFlow;
15 | import org.springframework.integration.dsl.IntegrationFlows;
16 | import org.springframework.integration.rsocket.ClientRSocketConnector;
17 | import org.springframework.integration.rsocket.RSocketInteractionModel;
18 | import org.springframework.integration.rsocket.ServerRSocketConnector;
19 | import org.springframework.integration.rsocket.dsl.RSockets;
20 | import org.springframework.test.annotation.DirtiesContext;
21 | import org.springframework.test.context.junit.jupiter.SpringJUnitConfig;
22 | import reactor.core.publisher.Flux;
23 | import reactor.test.StepVerifier;
24 |
25 | import java.util.function.Function;
26 |
27 | @SpringJUnitConfig(classes = {DemoApplication.class, DemoApplicationTests.TestConfig.class})
28 | @DirtiesContext
29 | public class DemoApplicationTests {
30 |
31 | @Autowired
32 | @Qualifier("rsocketUpperCaseRequestFlow.gateway")
33 | private Function, Flux> rsocketUpperCaseFlowFunction;
34 |
35 | @Test
36 | void testRsocketUpperCaseFlows() {
37 | Flux result = this.rsocketUpperCaseFlowFunction.apply(Flux.just("a\n", "b\n", "c\n"));
38 |
39 | StepVerifier.create(result)
40 | .expectNext("A", "B", "C")
41 | .verifyComplete();
42 | }
43 |
44 | @Configuration
45 | public static class TestConfig {
46 |
47 | @Bean
48 | public ClientRSocketConnector clientRSocketConnector(ServerRSocketConnector serverRSocketConnector) {
49 | int port = serverRSocketConnector.getBoundPort().block();
50 | ClientRSocketConnector clientRSocketConnector = new ClientRSocketConnector("localhost", port);
51 | clientRSocketConnector.setAutoStartup(false);
52 | return clientRSocketConnector;
53 | }
54 |
55 | @Bean
56 | public IntegrationFlow rsocketUpperCaseRequestFlow(ClientRSocketConnector clientRSocketConnector) {
57 | return IntegrationFlows
58 | .from(Function.class)
59 | .handle(RSockets.outboundGateway("/uppercase")
60 | .interactionModel((message) -> RSocketInteractionModel.requestChannel)
61 | .expectedResponseType("T(java.lang.String)")
62 | .clientRSocketConnector(clientRSocketConnector))
63 | .get();
64 | }
65 |
66 | }
67 |
68 | }
--------------------------------------------------------------------------------
/integration/server/.gitignore:
--------------------------------------------------------------------------------
1 | HELP.md
2 | target/
3 | !.mvn/wrapper/maven-wrapper.jar
4 | !**/src/main/**
5 | !**/src/test/**
6 |
7 | ### STS ###
8 | .apt_generated
9 | .classpath
10 | .factorypath
11 | .project
12 | .settings
13 | .springBeans
14 | .sts4-cache
15 |
16 | ### IntelliJ IDEA ###
17 | .idea
18 | *.iws
19 | *.iml
20 | *.ipr
21 |
22 | ### NetBeans ###
23 | /nbproject/private/
24 | /nbbuild/
25 | /dist/
26 | /nbdist/
27 | /.nb-gradle/
28 | build/
29 |
30 | ### VS Code ###
31 | .vscode/
32 |
--------------------------------------------------------------------------------
/integration/server/pom.xml:
--------------------------------------------------------------------------------
1 |
2 |
4 | 4.0.0
5 |
6 | org.springframework.boot
7 | spring-boot-starter-parent
8 | 2.3.0.RELEASE
9 |
10 |
11 | com.example
12 | rsocket-sample-integration-server
13 | 0.0.1-SNAPSHOT
14 | rsocket-sample-integration-server
15 | Demo project for Spring Boot
16 |
17 |
18 | 11
19 |
20 |
21 |
22 |
23 | org.springframework.boot
24 | spring-boot-starter-rsocket
25 |
26 |
27 |
28 | org.springframework.boot
29 | spring-boot-starter-integration
30 |
31 |
32 |
33 | org.springframework.integration
34 | spring-integration-rsocket
35 |
36 |
37 |
38 | org.springframework.boot
39 | spring-boot-starter-test
40 | test
41 |
42 |
43 | org.junit.vintage
44 | junit-vintage-engine
45 |
46 |
47 |
48 |
49 | org.springframework.integration
50 | spring-integration-test
51 | test
52 |
53 |
54 | io.projectreactor
55 | reactor-test
56 | test
57 |
58 |
59 |
60 |
61 |
62 |
63 | org.springframework.boot
64 | spring-boot-maven-plugin
65 |
66 |
67 |
68 |
69 |
70 |
71 | spring-milestones
72 | Spring Milestones
73 | https://repo.spring.io/milestone
74 |
75 |
76 |
77 |
78 | spring-milestones
79 | Spring Milestones
80 | https://repo.spring.io/milestone
81 |
82 |
83 |
84 |
85 |
--------------------------------------------------------------------------------
/integration/server/src/main/java/com/example/demo/DemoApplication.java:
--------------------------------------------------------------------------------
1 | package com.example.demo;
2 |
3 | import org.springframework.boot.SpringApplication;
4 | import org.springframework.boot.autoconfigure.SpringBootApplication;
5 | import org.springframework.context.annotation.Bean;
6 | import org.springframework.core.ResolvableType;
7 | import org.springframework.integration.config.EnableIntegration;
8 | import org.springframework.integration.dsl.IntegrationFlow;
9 | import org.springframework.integration.dsl.IntegrationFlows;
10 | import org.springframework.integration.rsocket.RSocketInteractionModel;
11 | import org.springframework.integration.rsocket.ServerRSocketConnector;
12 | import org.springframework.integration.rsocket.ServerRSocketMessageHandler;
13 | import org.springframework.integration.rsocket.dsl.RSockets;
14 | import org.springframework.messaging.rsocket.RSocketStrategies;
15 | import reactor.core.publisher.Flux;
16 |
17 | import java.io.IOException;
18 |
19 | @SpringBootApplication
20 | @EnableIntegration
21 | public class DemoApplication {
22 |
23 | public static void main(String[] args) throws IOException {
24 | SpringApplication.run(DemoApplication.class, args);
25 | }
26 |
27 | // see PR: https://github.com/spring-projects/spring-boot/pull/18834
28 | @Bean
29 | ServerRSocketMessageHandler serverRSocketMessageHandler(RSocketStrategies rSocketStrategies) {
30 | var handler = new ServerRSocketMessageHandler(true);
31 | handler.setRSocketStrategies(rSocketStrategies);
32 | return handler;
33 | }
34 |
35 | @Bean
36 | public ServerRSocketConnector serverRSocketConnector(ServerRSocketMessageHandler serverRSocketMessageHandler) {
37 | return new ServerRSocketConnector(serverRSocketMessageHandler);
38 | }
39 |
40 | @Bean
41 | public IntegrationFlow rsocketUpperCaseFlow(ServerRSocketConnector serverRSocketConnector) {
42 | return IntegrationFlows
43 | .from(RSockets.inboundGateway("/uppercase")
44 | .requestElementType(ResolvableType.forClass(String.class))
45 | .interactionModels(RSocketInteractionModel.requestChannel)
46 | .rsocketConnector(serverRSocketConnector)
47 | )
48 | ., Flux>transform((flux) -> flux.map(String::toUpperCase))
49 | .get();
50 | }
51 |
52 | }
53 |
--------------------------------------------------------------------------------
/integration/server/src/main/resources/application.properties:
--------------------------------------------------------------------------------
1 | spring.rsocket.server.port=7000
2 | spring.rsocket.server.transport=tcp
3 |
4 | logging.level.org.springframework.integration=DEBUG
5 |
6 | # auto configure spring integration rsocket server.
7 | spring.integration.rsocket.server.messageMappingEnabled=true
8 |
--------------------------------------------------------------------------------
/security/.gitignore:
--------------------------------------------------------------------------------
1 | HELP.md
2 | target/
3 | !.mvn/wrapper/maven-wrapper.jar
4 | !**/src/main/**
5 | !**/src/test/**
6 |
7 | ### STS ###
8 | .apt_generated
9 | .classpath
10 | .factorypath
11 | .project
12 | .settings
13 | .springBeans
14 | .sts4-cache
15 |
16 | ### IntelliJ IDEA ###
17 | .idea
18 | *.iws
19 | *.iml
20 | *.ipr
21 |
22 | ### NetBeans ###
23 | /nbproject/private/
24 | /nbbuild/
25 | /dist/
26 | /nbdist/
27 | /.nb-gradle/
28 | build/
29 |
30 | ### VS Code ###
31 | .vscode/
32 |
--------------------------------------------------------------------------------
/security/.mvn/wrapper/MavenWrapperDownloader.java:
--------------------------------------------------------------------------------
1 | /*
2 | Licensed to the Apache Software Foundation (ASF) under one
3 | or more contributor license agreements. See the NOTICE file
4 | distributed with this work for additional information
5 | regarding copyright ownership. The ASF licenses this file
6 | to you under the Apache License, Version 2.0 (the
7 | "License"); you may not use this file except in compliance
8 | with the License. You may obtain a copy of the License at
9 |
10 | https://www.apache.org/licenses/LICENSE-2.0
11 |
12 | Unless required by applicable law or agreed to in writing,
13 | software distributed under the License is distributed on an
14 | "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15 | KIND, either express or implied. See the License for the
16 | specific language governing permissions and limitations
17 | under the License.
18 | */
19 |
20 | import java.io.File;
21 | import java.io.FileInputStream;
22 | import java.io.FileOutputStream;
23 | import java.io.IOException;
24 | import java.net.URL;
25 | import java.nio.channels.Channels;
26 | import java.nio.channels.ReadableByteChannel;
27 | import java.util.Properties;
28 |
29 | public class MavenWrapperDownloader {
30 |
31 | /**
32 | * Default URL to download the maven-wrapper.jar from, if no 'downloadUrl' is provided.
33 | */
34 | private static final String DEFAULT_DOWNLOAD_URL =
35 | "https://repo.maven.apache.org/maven2/io/takari/maven-wrapper/0.4.2/maven-wrapper-0.4.2.jar";
36 |
37 | /**
38 | * Path to the maven-wrapper.properties file, which might contain a downloadUrl property to
39 | * use instead of the default one.
40 | */
41 | private static final String MAVEN_WRAPPER_PROPERTIES_PATH =
42 | ".mvn/wrapper/maven-wrapper.properties";
43 |
44 | /**
45 | * Path where the maven-wrapper.jar will be saved to.
46 | */
47 | private static final String MAVEN_WRAPPER_JAR_PATH =
48 | ".mvn/wrapper/maven-wrapper.jar";
49 |
50 | /**
51 | * Name of the property which should be used to override the default download url for the wrapper.
52 | */
53 | private static final String PROPERTY_NAME_WRAPPER_URL = "wrapperUrl";
54 |
55 | public static void main(String args[]) {
56 | System.out.println("- Downloader started");
57 | File baseDirectory = new File(args[0]);
58 | System.out.println("- Using base directory: " + baseDirectory.getAbsolutePath());
59 |
60 | // If the maven-wrapper.properties exists, read it and check if it contains a custom
61 | // wrapperUrl parameter.
62 | File mavenWrapperPropertyFile = new File(baseDirectory, MAVEN_WRAPPER_PROPERTIES_PATH);
63 | String url = DEFAULT_DOWNLOAD_URL;
64 | if(mavenWrapperPropertyFile.exists()) {
65 | FileInputStream mavenWrapperPropertyFileInputStream = null;
66 | try {
67 | mavenWrapperPropertyFileInputStream = new FileInputStream(mavenWrapperPropertyFile);
68 | Properties mavenWrapperProperties = new Properties();
69 | mavenWrapperProperties.load(mavenWrapperPropertyFileInputStream);
70 | url = mavenWrapperProperties.getProperty(PROPERTY_NAME_WRAPPER_URL, url);
71 | } catch (IOException e) {
72 | System.out.println("- ERROR loading '" + MAVEN_WRAPPER_PROPERTIES_PATH + "'");
73 | } finally {
74 | try {
75 | if(mavenWrapperPropertyFileInputStream != null) {
76 | mavenWrapperPropertyFileInputStream.close();
77 | }
78 | } catch (IOException e) {
79 | // Ignore ...
80 | }
81 | }
82 | }
83 | System.out.println("- Downloading from: : " + url);
84 |
85 | File outputFile = new File(baseDirectory.getAbsolutePath(), MAVEN_WRAPPER_JAR_PATH);
86 | if(!outputFile.getParentFile().exists()) {
87 | if(!outputFile.getParentFile().mkdirs()) {
88 | System.out.println(
89 | "- ERROR creating output direcrory '" + outputFile.getParentFile().getAbsolutePath() + "'");
90 | }
91 | }
92 | System.out.println("- Downloading to: " + outputFile.getAbsolutePath());
93 | try {
94 | downloadFileFromURL(url, outputFile);
95 | System.out.println("Done");
96 | System.exit(0);
97 | } catch (Throwable e) {
98 | System.out.println("- Error downloading");
99 | e.printStackTrace();
100 | System.exit(1);
101 | }
102 | }
103 |
104 | private static void downloadFileFromURL(String urlString, File destination) throws Exception {
105 | URL website = new URL(urlString);
106 | ReadableByteChannel rbc;
107 | rbc = Channels.newChannel(website.openStream());
108 | FileOutputStream fos = new FileOutputStream(destination);
109 | fos.getChannel().transferFrom(rbc, 0, Long.MAX_VALUE);
110 | fos.close();
111 | rbc.close();
112 | }
113 |
114 | }
115 |
--------------------------------------------------------------------------------
/security/.mvn/wrapper/maven-wrapper.jar:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/hantsy/rsocket-sample/7349fd955764b163ac061b00d30d8a8646a0fcdd/security/.mvn/wrapper/maven-wrapper.jar
--------------------------------------------------------------------------------
/security/.mvn/wrapper/maven-wrapper.properties:
--------------------------------------------------------------------------------
1 | distributionUrl=https://repo.maven.apache.org/maven2/org/apache/maven/apache-maven/3.6.0/apache-maven-3.6.0-bin.zip
2 |
--------------------------------------------------------------------------------
/security/lombok.config:
--------------------------------------------------------------------------------
1 | lombok.noArgsConstructor.extraPrivate=true
2 |
--------------------------------------------------------------------------------
/security/mvnw:
--------------------------------------------------------------------------------
1 | #!/bin/sh
2 | # ----------------------------------------------------------------------------
3 | # Licensed to the Apache Software Foundation (ASF) under one
4 | # or more contributor license agreements. See the NOTICE file
5 | # distributed with this work for additional information
6 | # regarding copyright ownership. The ASF licenses this file
7 | # to you under the Apache License, Version 2.0 (the
8 | # "License"); you may not use this file except in compliance
9 | # with the License. You may obtain a copy of the License at
10 | #
11 | # https://www.apache.org/licenses/LICENSE-2.0
12 | #
13 | # Unless required by applicable law or agreed to in writing,
14 | # software distributed under the License is distributed on an
15 | # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16 | # KIND, either express or implied. See the License for the
17 | # specific language governing permissions and limitations
18 | # under the License.
19 | # ----------------------------------------------------------------------------
20 |
21 | # ----------------------------------------------------------------------------
22 | # Maven2 Start Up Batch script
23 | #
24 | # Required ENV vars:
25 | # ------------------
26 | # JAVA_HOME - location of a JDK home dir
27 | #
28 | # Optional ENV vars
29 | # -----------------
30 | # M2_HOME - location of maven2's installed home dir
31 | # MAVEN_OPTS - parameters passed to the Java VM when running Maven
32 | # e.g. to debug Maven itself, use
33 | # set MAVEN_OPTS=-Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=8000
34 | # MAVEN_SKIP_RC - flag to disable loading of mavenrc files
35 | # ----------------------------------------------------------------------------
36 |
37 | if [ -z "$MAVEN_SKIP_RC" ] ; then
38 |
39 | if [ -f /etc/mavenrc ] ; then
40 | . /etc/mavenrc
41 | fi
42 |
43 | if [ -f "$HOME/.mavenrc" ] ; then
44 | . "$HOME/.mavenrc"
45 | fi
46 |
47 | fi
48 |
49 | # OS specific support. $var _must_ be set to either true or false.
50 | cygwin=false;
51 | darwin=false;
52 | mingw=false
53 | case "`uname`" in
54 | CYGWIN*) cygwin=true ;;
55 | MINGW*) mingw=true;;
56 | Darwin*) darwin=true
57 | # Use /usr/libexec/java_home if available, otherwise fall back to /Library/Java/Home
58 | # See https://developer.apple.com/library/mac/qa/qa1170/_index.html
59 | if [ -z "$JAVA_HOME" ]; then
60 | if [ -x "/usr/libexec/java_home" ]; then
61 | export JAVA_HOME="`/usr/libexec/java_home`"
62 | else
63 | export JAVA_HOME="/Library/Java/Home"
64 | fi
65 | fi
66 | ;;
67 | esac
68 |
69 | if [ -z "$JAVA_HOME" ] ; then
70 | if [ -r /etc/gentoo-release ] ; then
71 | JAVA_HOME=`java-config --jre-home`
72 | fi
73 | fi
74 |
75 | if [ -z "$M2_HOME" ] ; then
76 | ## resolve links - $0 may be a link to maven's home
77 | PRG="$0"
78 |
79 | # need this for relative symlinks
80 | while [ -h "$PRG" ] ; do
81 | ls=`ls -ld "$PRG"`
82 | link=`expr "$ls" : '.*-> \(.*\)$'`
83 | if expr "$link" : '/.*' > /dev/null; then
84 | PRG="$link"
85 | else
86 | PRG="`dirname "$PRG"`/$link"
87 | fi
88 | done
89 |
90 | saveddir=`pwd`
91 |
92 | M2_HOME=`dirname "$PRG"`/..
93 |
94 | # make it fully qualified
95 | M2_HOME=`cd "$M2_HOME" && pwd`
96 |
97 | cd "$saveddir"
98 | # echo Using m2 at $M2_HOME
99 | fi
100 |
101 | # For Cygwin, ensure paths are in UNIX format before anything is touched
102 | if $cygwin ; then
103 | [ -n "$M2_HOME" ] &&
104 | M2_HOME=`cygpath --unix "$M2_HOME"`
105 | [ -n "$JAVA_HOME" ] &&
106 | JAVA_HOME=`cygpath --unix "$JAVA_HOME"`
107 | [ -n "$CLASSPATH" ] &&
108 | CLASSPATH=`cygpath --path --unix "$CLASSPATH"`
109 | fi
110 |
111 | # For Mingw, ensure paths are in UNIX format before anything is touched
112 | if $mingw ; then
113 | [ -n "$M2_HOME" ] &&
114 | M2_HOME="`(cd "$M2_HOME"; pwd)`"
115 | [ -n "$JAVA_HOME" ] &&
116 | JAVA_HOME="`(cd "$JAVA_HOME"; pwd)`"
117 | # TODO classpath?
118 | fi
119 |
120 | if [ -z "$JAVA_HOME" ]; then
121 | javaExecutable="`which javac`"
122 | if [ -n "$javaExecutable" ] && ! [ "`expr \"$javaExecutable\" : '\([^ ]*\)'`" = "no" ]; then
123 | # readlink(1) is not available as standard on Solaris 10.
124 | readLink=`which readlink`
125 | if [ ! `expr "$readLink" : '\([^ ]*\)'` = "no" ]; then
126 | if $darwin ; then
127 | javaHome="`dirname \"$javaExecutable\"`"
128 | javaExecutable="`cd \"$javaHome\" && pwd -P`/javac"
129 | else
130 | javaExecutable="`readlink -f \"$javaExecutable\"`"
131 | fi
132 | javaHome="`dirname \"$javaExecutable\"`"
133 | javaHome=`expr "$javaHome" : '\(.*\)/bin'`
134 | JAVA_HOME="$javaHome"
135 | export JAVA_HOME
136 | fi
137 | fi
138 | fi
139 |
140 | if [ -z "$JAVACMD" ] ; then
141 | if [ -n "$JAVA_HOME" ] ; then
142 | if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
143 | # IBM's JDK on AIX uses strange locations for the executables
144 | JAVACMD="$JAVA_HOME/jre/sh/java"
145 | else
146 | JAVACMD="$JAVA_HOME/bin/java"
147 | fi
148 | else
149 | JAVACMD="`which java`"
150 | fi
151 | fi
152 |
153 | if [ ! -x "$JAVACMD" ] ; then
154 | echo "Error: JAVA_HOME is not defined correctly." >&2
155 | echo " We cannot execute $JAVACMD" >&2
156 | exit 1
157 | fi
158 |
159 | if [ -z "$JAVA_HOME" ] ; then
160 | echo "Warning: JAVA_HOME environment variable is not set."
161 | fi
162 |
163 | CLASSWORLDS_LAUNCHER=org.codehaus.plexus.classworlds.launcher.Launcher
164 |
165 | # traverses directory structure from process work directory to filesystem root
166 | # first directory with .mvn subdirectory is considered project base directory
167 | find_maven_basedir() {
168 |
169 | if [ -z "$1" ]
170 | then
171 | echo "Path not specified to find_maven_basedir"
172 | return 1
173 | fi
174 |
175 | basedir="$1"
176 | wdir="$1"
177 | while [ "$wdir" != '/' ] ; do
178 | if [ -d "$wdir"/.mvn ] ; then
179 | basedir=$wdir
180 | break
181 | fi
182 | # workaround for JBEAP-8937 (on Solaris 10/Sparc)
183 | if [ -d "${wdir}" ]; then
184 | wdir=`cd "$wdir/.."; pwd`
185 | fi
186 | # end of workaround
187 | done
188 | echo "${basedir}"
189 | }
190 |
191 | # concatenates all lines of a file
192 | concat_lines() {
193 | if [ -f "$1" ]; then
194 | echo "$(tr -s '\n' ' ' < "$1")"
195 | fi
196 | }
197 |
198 | BASE_DIR=`find_maven_basedir "$(pwd)"`
199 | if [ -z "$BASE_DIR" ]; then
200 | exit 1;
201 | fi
202 |
203 | ##########################################################################################
204 | # Extension to allow automatically downloading the maven-wrapper.jar from Maven-central
205 | # This allows using the maven wrapper in projects that prohibit checking in binary data.
206 | ##########################################################################################
207 | if [ -r "$BASE_DIR/.mvn/wrapper/maven-wrapper.jar" ]; then
208 | if [ "$MVNW_VERBOSE" = true ]; then
209 | echo "Found .mvn/wrapper/maven-wrapper.jar"
210 | fi
211 | else
212 | if [ "$MVNW_VERBOSE" = true ]; then
213 | echo "Couldn't find .mvn/wrapper/maven-wrapper.jar, downloading it ..."
214 | fi
215 | jarUrl="https://repo.maven.apache.org/maven2/io/takari/maven-wrapper/0.4.2/maven-wrapper-0.4.2.jar"
216 | while IFS="=" read key value; do
217 | case "$key" in (wrapperUrl) jarUrl="$value"; break ;;
218 | esac
219 | done < "$BASE_DIR/.mvn/wrapper/maven-wrapper.properties"
220 | if [ "$MVNW_VERBOSE" = true ]; then
221 | echo "Downloading from: $jarUrl"
222 | fi
223 | wrapperJarPath="$BASE_DIR/.mvn/wrapper/maven-wrapper.jar"
224 |
225 | if command -v wget > /dev/null; then
226 | if [ "$MVNW_VERBOSE" = true ]; then
227 | echo "Found wget ... using wget"
228 | fi
229 | wget "$jarUrl" -O "$wrapperJarPath"
230 | elif command -v curl > /dev/null; then
231 | if [ "$MVNW_VERBOSE" = true ]; then
232 | echo "Found curl ... using curl"
233 | fi
234 | curl -o "$wrapperJarPath" "$jarUrl"
235 | else
236 | if [ "$MVNW_VERBOSE" = true ]; then
237 | echo "Falling back to using Java to download"
238 | fi
239 | javaClass="$BASE_DIR/.mvn/wrapper/MavenWrapperDownloader.java"
240 | if [ -e "$javaClass" ]; then
241 | if [ ! -e "$BASE_DIR/.mvn/wrapper/MavenWrapperDownloader.class" ]; then
242 | if [ "$MVNW_VERBOSE" = true ]; then
243 | echo " - Compiling MavenWrapperDownloader.java ..."
244 | fi
245 | # Compiling the Java class
246 | ("$JAVA_HOME/bin/javac" "$javaClass")
247 | fi
248 | if [ -e "$BASE_DIR/.mvn/wrapper/MavenWrapperDownloader.class" ]; then
249 | # Running the downloader
250 | if [ "$MVNW_VERBOSE" = true ]; then
251 | echo " - Running MavenWrapperDownloader.java ..."
252 | fi
253 | ("$JAVA_HOME/bin/java" -cp .mvn/wrapper MavenWrapperDownloader "$MAVEN_PROJECTBASEDIR")
254 | fi
255 | fi
256 | fi
257 | fi
258 | ##########################################################################################
259 | # End of extension
260 | ##########################################################################################
261 |
262 | export MAVEN_PROJECTBASEDIR=${MAVEN_BASEDIR:-"$BASE_DIR"}
263 | if [ "$MVNW_VERBOSE" = true ]; then
264 | echo $MAVEN_PROJECTBASEDIR
265 | fi
266 | MAVEN_OPTS="$(concat_lines "$MAVEN_PROJECTBASEDIR/.mvn/jvm.config") $MAVEN_OPTS"
267 |
268 | # For Cygwin, switch paths to Windows format before running java
269 | if $cygwin; then
270 | [ -n "$M2_HOME" ] &&
271 | M2_HOME=`cygpath --path --windows "$M2_HOME"`
272 | [ -n "$JAVA_HOME" ] &&
273 | JAVA_HOME=`cygpath --path --windows "$JAVA_HOME"`
274 | [ -n "$CLASSPATH" ] &&
275 | CLASSPATH=`cygpath --path --windows "$CLASSPATH"`
276 | [ -n "$MAVEN_PROJECTBASEDIR" ] &&
277 | MAVEN_PROJECTBASEDIR=`cygpath --path --windows "$MAVEN_PROJECTBASEDIR"`
278 | fi
279 |
280 | WRAPPER_LAUNCHER=org.apache.maven.wrapper.MavenWrapperMain
281 |
282 | exec "$JAVACMD" \
283 | $MAVEN_OPTS \
284 | -classpath "$MAVEN_PROJECTBASEDIR/.mvn/wrapper/maven-wrapper.jar" \
285 | "-Dmaven.home=${M2_HOME}" "-Dmaven.multiModuleProjectDirectory=${MAVEN_PROJECTBASEDIR}" \
286 | ${WRAPPER_LAUNCHER} $MAVEN_CONFIG "$@"
287 |
--------------------------------------------------------------------------------
/security/mvnw.cmd:
--------------------------------------------------------------------------------
1 | @REM ----------------------------------------------------------------------------
2 | @REM Licensed to the Apache Software Foundation (ASF) under one
3 | @REM or more contributor license agreements. See the NOTICE file
4 | @REM distributed with this work for additional information
5 | @REM regarding copyright ownership. The ASF licenses this file
6 | @REM to you under the Apache License, Version 2.0 (the
7 | @REM "License"); you may not use this file except in compliance
8 | @REM with the License. You may obtain a copy of the License at
9 | @REM
10 | @REM https://www.apache.org/licenses/LICENSE-2.0
11 | @REM
12 | @REM Unless required by applicable law or agreed to in writing,
13 | @REM software distributed under the License is distributed on an
14 | @REM "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15 | @REM KIND, either express or implied. See the License for the
16 | @REM specific language governing permissions and limitations
17 | @REM under the License.
18 | @REM ----------------------------------------------------------------------------
19 |
20 | @REM ----------------------------------------------------------------------------
21 | @REM Maven2 Start Up Batch script
22 | @REM
23 | @REM Required ENV vars:
24 | @REM JAVA_HOME - location of a JDK home dir
25 | @REM
26 | @REM Optional ENV vars
27 | @REM M2_HOME - location of maven2's installed home dir
28 | @REM MAVEN_BATCH_ECHO - set to 'on' to enable the echoing of the batch commands
29 | @REM MAVEN_BATCH_PAUSE - set to 'on' to wait for a key stroke before ending
30 | @REM MAVEN_OPTS - parameters passed to the Java VM when running Maven
31 | @REM e.g. to debug Maven itself, use
32 | @REM set MAVEN_OPTS=-Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=8000
33 | @REM MAVEN_SKIP_RC - flag to disable loading of mavenrc files
34 | @REM ----------------------------------------------------------------------------
35 |
36 | @REM Begin all REM lines with '@' in case MAVEN_BATCH_ECHO is 'on'
37 | @echo off
38 | @REM set title of command window
39 | title %0
40 | @REM enable echoing my setting MAVEN_BATCH_ECHO to 'on'
41 | @if "%MAVEN_BATCH_ECHO%" == "on" echo %MAVEN_BATCH_ECHO%
42 |
43 | @REM set %HOME% to equivalent of $HOME
44 | if "%HOME%" == "" (set "HOME=%HOMEDRIVE%%HOMEPATH%")
45 |
46 | @REM Execute a user defined script before this one
47 | if not "%MAVEN_SKIP_RC%" == "" goto skipRcPre
48 | @REM check for pre script, once with legacy .bat ending and once with .cmd ending
49 | if exist "%HOME%\mavenrc_pre.bat" call "%HOME%\mavenrc_pre.bat"
50 | if exist "%HOME%\mavenrc_pre.cmd" call "%HOME%\mavenrc_pre.cmd"
51 | :skipRcPre
52 |
53 | @setlocal
54 |
55 | set ERROR_CODE=0
56 |
57 | @REM To isolate internal variables from possible post scripts, we use another setlocal
58 | @setlocal
59 |
60 | @REM ==== START VALIDATION ====
61 | if not "%JAVA_HOME%" == "" goto OkJHome
62 |
63 | echo.
64 | echo Error: JAVA_HOME not found in your environment. >&2
65 | echo Please set the JAVA_HOME variable in your environment to match the >&2
66 | echo location of your Java installation. >&2
67 | echo.
68 | goto error
69 |
70 | :OkJHome
71 | if exist "%JAVA_HOME%\bin\java.exe" goto init
72 |
73 | echo.
74 | echo Error: JAVA_HOME is set to an invalid directory. >&2
75 | echo JAVA_HOME = "%JAVA_HOME%" >&2
76 | echo Please set the JAVA_HOME variable in your environment to match the >&2
77 | echo location of your Java installation. >&2
78 | echo.
79 | goto error
80 |
81 | @REM ==== END VALIDATION ====
82 |
83 | :init
84 |
85 | @REM Find the project base dir, i.e. the directory that contains the folder ".mvn".
86 | @REM Fallback to current working directory if not found.
87 |
88 | set MAVEN_PROJECTBASEDIR=%MAVEN_BASEDIR%
89 | IF NOT "%MAVEN_PROJECTBASEDIR%"=="" goto endDetectBaseDir
90 |
91 | set EXEC_DIR=%CD%
92 | set WDIR=%EXEC_DIR%
93 | :findBaseDir
94 | IF EXIST "%WDIR%"\.mvn goto baseDirFound
95 | cd ..
96 | IF "%WDIR%"=="%CD%" goto baseDirNotFound
97 | set WDIR=%CD%
98 | goto findBaseDir
99 |
100 | :baseDirFound
101 | set MAVEN_PROJECTBASEDIR=%WDIR%
102 | cd "%EXEC_DIR%"
103 | goto endDetectBaseDir
104 |
105 | :baseDirNotFound
106 | set MAVEN_PROJECTBASEDIR=%EXEC_DIR%
107 | cd "%EXEC_DIR%"
108 |
109 | :endDetectBaseDir
110 |
111 | IF NOT EXIST "%MAVEN_PROJECTBASEDIR%\.mvn\jvm.config" goto endReadAdditionalConfig
112 |
113 | @setlocal EnableExtensions EnableDelayedExpansion
114 | for /F "usebackq delims=" %%a in ("%MAVEN_PROJECTBASEDIR%\.mvn\jvm.config") do set JVM_CONFIG_MAVEN_PROPS=!JVM_CONFIG_MAVEN_PROPS! %%a
115 | @endlocal & set JVM_CONFIG_MAVEN_PROPS=%JVM_CONFIG_MAVEN_PROPS%
116 |
117 | :endReadAdditionalConfig
118 |
119 | SET MAVEN_JAVA_EXE="%JAVA_HOME%\bin\java.exe"
120 | set WRAPPER_JAR="%MAVEN_PROJECTBASEDIR%\.mvn\wrapper\maven-wrapper.jar"
121 | set WRAPPER_LAUNCHER=org.apache.maven.wrapper.MavenWrapperMain
122 |
123 | set DOWNLOAD_URL="https://repo.maven.apache.org/maven2/io/takari/maven-wrapper/0.4.2/maven-wrapper-0.4.2.jar"
124 | FOR /F "tokens=1,2 delims==" %%A IN (%MAVEN_PROJECTBASEDIR%\.mvn\wrapper\maven-wrapper.properties) DO (
125 | IF "%%A"=="wrapperUrl" SET DOWNLOAD_URL=%%B
126 | )
127 |
128 | @REM Extension to allow automatically downloading the maven-wrapper.jar from Maven-central
129 | @REM This allows using the maven wrapper in projects that prohibit checking in binary data.
130 | if exist %WRAPPER_JAR% (
131 | echo Found %WRAPPER_JAR%
132 | ) else (
133 | echo Couldn't find %WRAPPER_JAR%, downloading it ...
134 | echo Downloading from: %DOWNLOAD_URL%
135 | powershell -Command "(New-Object Net.WebClient).DownloadFile('%DOWNLOAD_URL%', '%WRAPPER_JAR%')"
136 | echo Finished downloading %WRAPPER_JAR%
137 | )
138 | @REM End of extension
139 |
140 | %MAVEN_JAVA_EXE% %JVM_CONFIG_MAVEN_PROPS% %MAVEN_OPTS% %MAVEN_DEBUG_OPTS% -classpath %WRAPPER_JAR% "-Dmaven.multiModuleProjectDirectory=%MAVEN_PROJECTBASEDIR%" %WRAPPER_LAUNCHER% %MAVEN_CONFIG% %*
141 | if ERRORLEVEL 1 goto error
142 | goto end
143 |
144 | :error
145 | set ERROR_CODE=1
146 |
147 | :end
148 | @endlocal & set ERROR_CODE=%ERROR_CODE%
149 |
150 | if not "%MAVEN_SKIP_RC%" == "" goto skipRcPost
151 | @REM check for post script, once with legacy .bat ending and once with .cmd ending
152 | if exist "%HOME%\mavenrc_post.bat" call "%HOME%\mavenrc_post.bat"
153 | if exist "%HOME%\mavenrc_post.cmd" call "%HOME%\mavenrc_post.cmd"
154 | :skipRcPost
155 |
156 | @REM pause the script if MAVEN_BATCH_PAUSE is set to 'on'
157 | if "%MAVEN_BATCH_PAUSE%" == "on" pause
158 |
159 | if "%MAVEN_TERMINATE_CMD%" == "on" exit %ERROR_CODE%
160 |
161 | exit /B %ERROR_CODE%
162 |
--------------------------------------------------------------------------------
/security/pom.xml:
--------------------------------------------------------------------------------
1 |
2 |
4 | 4.0.0
5 |
6 | org.springframework.boot
7 | spring-boot-starter-parent
8 | 2.2.5.RELEASE
9 |
10 |
11 | com.example
12 | rsocket-sample-boot-security
13 | 0.0.1-SNAPSHOT
14 | rsocket-sample-boot-security
15 | Demo project for Spring Boot
16 |
17 |
18 | 11
19 |
20 |
21 |
22 |
23 | org.projectlombok
24 | lombok
25 | true
26 |
27 |
28 | org.springframework.boot
29 | spring-boot-starter-rsocket
30 |
31 |
32 | org.springframework.boot
33 | spring-boot-starter-security
34 |
35 |
36 | org.springframework.security
37 | spring-security-rsocket
38 |
39 |
40 |
41 | org.springframework.boot
42 | spring-boot-starter-test
43 | test
44 |
45 |
46 | org.junit.vintage
47 | junit-vintage-engine
48 |
49 |
50 |
51 |
52 | org.springframework.security
53 | spring-security-test
54 | test
55 |
56 |
57 | io.projectreactor
58 | reactor-test
59 | test
60 |
61 |
62 |
63 |
64 |
65 |
66 | org.springframework.boot
67 | spring-boot-maven-plugin
68 |
69 |
70 |
71 |
72 |
73 |
--------------------------------------------------------------------------------
/security/src/main/java/com/example/demo/DemoApplication.java:
--------------------------------------------------------------------------------
1 | package com.example.demo;
2 |
3 | import lombok.AllArgsConstructor;
4 | import lombok.Data;
5 | import lombok.NoArgsConstructor;
6 | import org.springframework.boot.SpringApplication;
7 | import org.springframework.boot.autoconfigure.SpringBootApplication;
8 | import org.springframework.boot.rsocket.messaging.RSocketStrategiesCustomizer;
9 | import org.springframework.boot.rsocket.server.ServerRSocketFactoryProcessor;
10 | import org.springframework.context.annotation.Bean;
11 | import org.springframework.context.annotation.Configuration;
12 | import org.springframework.http.codec.json.Jackson2JsonDecoder;
13 | import org.springframework.http.codec.json.Jackson2JsonEncoder;
14 | import org.springframework.messaging.handler.annotation.MessageMapping;
15 | import org.springframework.security.config.Customizer;
16 | import org.springframework.security.config.annotation.rsocket.EnableRSocketSecurity;
17 | import org.springframework.security.config.annotation.rsocket.RSocketSecurity;
18 | import org.springframework.security.core.userdetails.MapReactiveUserDetailsService;
19 | import org.springframework.security.core.userdetails.User;
20 | import org.springframework.security.core.userdetails.UserDetails;
21 | import org.springframework.security.crypto.factory.PasswordEncoderFactories;
22 | import org.springframework.security.crypto.password.PasswordEncoder;
23 | import org.springframework.security.rsocket.core.PayloadSocketAcceptorInterceptor;
24 | import org.springframework.security.rsocket.core.SecuritySocketAcceptorInterceptor;
25 | import org.springframework.security.rsocket.metadata.BasicAuthenticationDecoder;
26 | import org.springframework.security.rsocket.metadata.BasicAuthenticationEncoder;
27 | import org.springframework.stereotype.Controller;
28 | import reactor.core.publisher.Mono;
29 |
30 | import java.time.Instant;
31 |
32 | @SpringBootApplication
33 | public class DemoApplication {
34 |
35 | public static void main(String[] args) {
36 | SpringApplication.run(DemoApplication.class, args);
37 | }
38 |
39 | }
40 |
41 | @Configuration
42 | @EnableRSocketSecurity
43 | class SecurityConfig {
44 | // @Bean
45 | // RSocketStrategiesCustomizer rSocketStrategiesCustomizer() {
46 | // return (b) -> b.decoder(new BasicAuthenticationDecoder(), new Jackson2JsonDecoder())
47 | // .encoder(new BasicAuthenticationEncoder(), new Jackson2JsonEncoder())
48 | // .build();
49 | // }
50 |
51 | @Bean
52 | public PayloadSocketAcceptorInterceptor rsocketInterceptor(RSocketSecurity rsocket) {
53 | return rsocket
54 | .authorizePayload(
55 | authorize -> {
56 | authorize
57 | // must have ROLE_SETUP to make connection
58 | .setup().hasRole("SETUP")
59 | // must have ROLE_ADMIN for routes starting with "greet."
60 | .route("greet*").hasRole("ADMIN")
61 | // any other request must be authenticated for
62 | .anyRequest().authenticated();
63 | }
64 | )
65 | .basicAuthentication(Customizer.withDefaults())
66 | .build();
67 | }
68 |
69 | @Bean
70 | public MapReactiveUserDetailsService userDetailsService(PasswordEncoder passwordEncoder) {
71 | UserDetails adminUser = User.withUsername("admin")
72 | .passwordEncoder(passwordEncoder::encode)
73 | .password("password")
74 | .roles("ADMIN")
75 | .build();
76 | UserDetails setupUser = User.withUsername("setup")
77 | .passwordEncoder(passwordEncoder::encode)
78 | .password("password")
79 | .roles("SETUP")
80 | .build();
81 |
82 | return new MapReactiveUserDetailsService(adminUser, setupUser);
83 | }
84 |
85 |
86 | @Bean
87 | PasswordEncoder passwordEncoder() {
88 | return PasswordEncoderFactories.createDelegatingPasswordEncoder();
89 | }
90 |
91 | // see: https://github.com/spring-projects/spring-security/issues/7497
92 | // and https://github.com/spring-projects/spring-security/blob/5.2.0.RELEASE/samples/boot/hellorsocket/src/main/java/sample/HelloRSocketSecurityConfig.java
93 | // @Bean
94 | // ServerRSocketFactoryProcessor springSecurityServerRSocketFactoryProcessor(
95 | // SecuritySocketAcceptorInterceptor interceptor) {
96 | // return builder -> builder.addSocketAcceptorPlugin(interceptor);
97 | // }
98 |
99 | }
100 |
101 |
102 | @Controller
103 | class GreetingController {
104 |
105 | @MessageMapping("greet")
106 | Mono greet(GreetingRequest request) {
107 | return Mono.just(new GreetingResponse("Hello " + request.getName() + " @ " + Instant.now()));
108 | }
109 | }
110 |
111 | @Data
112 | @AllArgsConstructor
113 | @NoArgsConstructor
114 | class GreetingRequest {
115 | private String name;
116 |
117 | public static GreetingRequest of(String name) {
118 | var greeting = new GreetingRequest();
119 | greeting.setName(name);
120 | return greeting;
121 | }
122 | }
123 |
124 | @Data
125 | @NoArgsConstructor
126 | @AllArgsConstructor
127 | class GreetingResponse {
128 | private String message;
129 | }
130 |
--------------------------------------------------------------------------------
/security/src/main/resources/application.properties:
--------------------------------------------------------------------------------
1 | spring.rsocket.server.port=7000
2 | spring.rsocket.server.transport=tcp
3 |
--------------------------------------------------------------------------------
/security/src/test/java/com/example/demo/DemoApplicationTests.java:
--------------------------------------------------------------------------------
1 | package com.example.demo;
2 |
3 | import org.junit.jupiter.api.Test;
4 | import org.springframework.beans.factory.annotation.Autowired;
5 | import org.springframework.boot.rsocket.context.LocalRSocketServerPort;
6 | import org.springframework.boot.rsocket.context.RSocketServerInitializedEvent;
7 | import org.springframework.boot.test.context.SpringBootTest;
8 | import org.springframework.boot.test.context.TestConfiguration;
9 | import org.springframework.context.ApplicationListener;
10 | import org.springframework.messaging.rsocket.RSocketRequester;
11 | import org.springframework.security.rsocket.metadata.BasicAuthenticationEncoder;
12 | import org.springframework.security.rsocket.metadata.UsernamePasswordMetadata;
13 | import org.springframework.test.context.TestPropertySource;
14 | import reactor.test.StepVerifier;
15 |
16 | import static org.assertj.core.api.Assertions.assertThat;
17 | import static org.assertj.core.api.Assertions.assertThatThrownBy;
18 | import static org.springframework.security.rsocket.metadata.UsernamePasswordMetadata.BASIC_AUTHENTICATION_MIME_TYPE;
19 |
20 | // see: https://github.com/rwinch/rsocket-security/blob/master/src/test/java/org/springframework/security/rsocket/itests/RSocketMessageHandlerITests.java
21 | // and https://github.com/spring-projects/spring-security/blob/5.2.0.RELEASE/samples/boot/hellorsocket/src/integration-test/java/sample/HelloRSocketApplicationITests.java
22 | @SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
23 | @TestPropertySource(properties = "spring.rsocket.server.port=0")
24 | class DemoApplicationTests {
25 |
26 |
27 | @LocalRSocketServerPort
28 | int port;
29 |
30 | @Autowired
31 | RSocketRequester.Builder requester;
32 |
33 | @Test
34 | public void retrieveMonoWhenSecureThenDenied() throws Exception {
35 | RSocketRequester requester = this.requester
36 | .connectTcp("localhost", this.port)
37 | .block();
38 | String data = "hantsy";
39 | assertThatThrownBy(
40 | () -> requester.route("greet*")
41 | .data(GreetingRequest.of(data))
42 | .retrieveMono(GreetingResponse.class)
43 | .block()
44 | ).isNotNull();
45 | }
46 |
47 |
48 | @Test
49 | public void retrieveMonoWithSetupUserWithoutAdminThenDenied() throws Exception {
50 | UsernamePasswordMetadata credentials = new UsernamePasswordMetadata("setup", "password");
51 |
52 | RSocketRequester requester = this.requester
53 | .rsocketStrategies(builder -> builder.encoder(new BasicAuthenticationEncoder()))
54 | .setupMetadata(credentials, BASIC_AUTHENTICATION_MIME_TYPE)
55 | .connectTcp("localhost", this.port)
56 | .block();
57 | String data = "hantsy";
58 | assertThatThrownBy(
59 | () -> requester.route("greet")
60 | .data(GreetingRequest.of(data))
61 | .retrieveMono(GreetingResponse.class)
62 | .block()
63 | ).isNotNull();
64 | }
65 |
66 |
67 | @Test
68 | public void retrieveMonoWithSetupUserAndAdminUserThenOK() throws Exception {
69 | UsernamePasswordMetadata credentials = new UsernamePasswordMetadata("setup", "password");
70 |
71 | RSocketRequester requester = this.requester
72 | .rsocketStrategies(builder -> builder.encoder(new BasicAuthenticationEncoder()))
73 | .setupMetadata(credentials, BASIC_AUTHENTICATION_MIME_TYPE)
74 | .connectTcp("localhost", this.port)
75 | .block();
76 | UsernamePasswordMetadata adminCredentials = new UsernamePasswordMetadata("admin", "password");
77 |
78 | String data = "hantsy";
79 | requester.route("greet")
80 | .metadata(adminCredentials, BASIC_AUTHENTICATION_MIME_TYPE)
81 | .data(GreetingRequest.of(data))
82 | .retrieveMono(GreetingResponse.class)
83 | .as(StepVerifier::create)
84 | .consumeNextWith(c -> assertThat(c.getMessage()).contains("hantsy"))
85 | .verifyComplete();
86 | }
87 |
88 |
89 | // FIXME: Waiting for @LocalRSocketServerPort
90 | // https://github.com/spring-projects/spring-boot/pull/18287
91 | // @Autowired
92 | // Config config;
93 | //
94 | // private int getPort() {
95 | // return this.config.port;
96 | // }
97 | //
98 | // @TestConfiguration
99 | // static class Config implements ApplicationListener {
100 | // private int port;
101 | //
102 | // @Override
103 | // public void onApplicationEvent(RSocketServerInitializedEvent event) {
104 | // this.port = event.getServer().address().getPort();
105 | // }
106 | // }
107 |
108 | }
109 |
--------------------------------------------------------------------------------
/server-requester/client/.gitignore:
--------------------------------------------------------------------------------
1 | HELP.md
2 | target/
3 | !.mvn/wrapper/maven-wrapper.jar
4 | !**/src/main/**
5 | !**/src/test/**
6 |
7 | ### STS ###
8 | .apt_generated
9 | .classpath
10 | .factorypath
11 | .project
12 | .settings
13 | .springBeans
14 | .sts4-cache
15 |
16 | ### IntelliJ IDEA ###
17 | .idea
18 | *.iws
19 | *.iml
20 | *.ipr
21 |
22 | ### NetBeans ###
23 | /nbproject/private/
24 | /nbbuild/
25 | /dist/
26 | /nbdist/
27 | /.nb-gradle/
28 | build/
29 |
30 | ### VS Code ###
31 | .vscode/
32 |
--------------------------------------------------------------------------------
/server-requester/client/lombok.config:
--------------------------------------------------------------------------------
1 | lombok.noArgsConstructor.extraPrivate=true
2 |
--------------------------------------------------------------------------------
/server-requester/client/nbactions.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | run
5 |
6 | jar
7 |
8 |
9 | spring-boot:run
10 |
11 |
12 | -noverify -XX:TieredStopAtLevel=1
13 | com.example.consumer.ConsumerApplication
14 | always
15 |
16 |
17 |
18 | debug
19 |
20 | jar
21 |
22 |
23 | spring-boot:run
24 |
25 |
26 | -Xdebug -Xrunjdwp:transport=dt_socket,server=n,address=${jpda.address} -noverify -XX:TieredStopAtLevel=1
27 | com.example.consumer.ConsumerApplication
28 | always
29 | true
30 |
31 |
32 |
33 | profile
34 |
35 | jar
36 |
37 |
38 | process-classes
39 | org.codehaus.mojo:exec-maven-plugin:1.2.1:exec
40 |
41 |
42 | -classpath %classpath com.example.consumer.ConsumerApplication
43 | java
44 |
45 |
46 |
47 |
--------------------------------------------------------------------------------
/server-requester/client/pom.xml:
--------------------------------------------------------------------------------
1 |
2 |
4 | 4.0.0
5 |
6 | org.springframework.boot
7 | spring-boot-starter-parent
8 | 2.2.5.RELEASE
9 |
10 |
11 | com.example
12 | rsocket-sample-boot-server-requeter-client
13 | 0.0.1-SNAPSHOT
14 | rsocket-sample-boot-server-requeter-client
15 | Demo project for Spring Boot
16 |
17 |
18 | 11
19 |
20 |
21 |
22 |
23 | org.springframework.boot
24 | spring-boot-starter-webflux
25 |
26 |
27 | org.springframework.boot
28 | spring-boot-starter-rsocket
29 |
30 |
31 |
32 | org.projectlombok
33 | lombok
34 | true
35 |
36 |
37 | org.springframework.boot
38 | spring-boot-starter-test
39 | test
40 |
41 |
42 | org.junit.vintage
43 | junit-vintage-engine
44 |
45 |
46 |
47 |
48 |
49 |
50 |
51 |
52 | org.springframework.boot
53 | spring-boot-maven-plugin
54 |
55 |
56 |
57 |
58 |
59 |
60 | spring-milestones
61 | Spring Milestones
62 | https://repo.spring.io/milestone
63 |
64 |
65 |
66 |
67 | spring-milestones
68 | Spring Milestones
69 | https://repo.spring.io/milestone
70 |
71 |
72 |
73 |
74 |
--------------------------------------------------------------------------------
/server-requester/client/src/main/java/com/example/client/ClientApplication.java:
--------------------------------------------------------------------------------
1 | package com.example.client;
2 |
3 | import lombok.RequiredArgsConstructor;
4 | import lombok.extern.slf4j.Slf4j;
5 | import org.springframework.boot.SpringApplication;
6 | import org.springframework.boot.autoconfigure.SpringBootApplication;
7 | import org.springframework.context.annotation.Bean;
8 | import org.springframework.messaging.handler.annotation.MessageMapping;
9 | import org.springframework.messaging.rsocket.RSocketRequester;
10 | import org.springframework.messaging.rsocket.RSocketStrategies;
11 | import org.springframework.messaging.rsocket.annotation.support.RSocketMessageHandler;
12 | import org.springframework.util.MimeTypeUtils;
13 | import org.springframework.web.bind.annotation.GetMapping;
14 | import org.springframework.web.bind.annotation.RestController;
15 | import reactor.core.publisher.Mono;
16 |
17 | import java.time.Duration;
18 | import java.time.LocalDateTime;
19 |
20 | @SpringBootApplication
21 | public class ClientApplication {
22 |
23 | public static void main(String[] args) {
24 | SpringApplication.run(ClientApplication.class, args);
25 | }
26 |
27 | @Bean
28 | public RSocketRequester rSocketRequester(RSocketRequester.Builder b, RSocketStrategies rSocketStrategies) {
29 | return b.dataMimeType(MimeTypeUtils.APPLICATION_JSON)
30 | .rsocketFactory(RSocketMessageHandler.clientResponder(rSocketStrategies, new ClientHandler()))
31 | .setupRoute("connect")
32 | .setupData("user")
33 | .connectTcp("localhost", 7000)
34 | .block();
35 | }
36 |
37 | }
38 |
39 | @Slf4j
40 | class ClientHandler {
41 |
42 | @MessageMapping("status")
43 | public Mono statusUpdate(String status) {
44 | log.info("Received (" + status + ") at " + LocalDateTime.now());
45 | return Mono.just("confirmed").delayElement(Duration.ofSeconds(1));
46 | }
47 | }
48 |
49 | @Slf4j
50 | @RestController()
51 | @RequiredArgsConstructor
52 | class GreetingController {
53 |
54 | private final RSocketRequester requester;
55 |
56 | @GetMapping("hello")
57 | Mono hello() {
58 | return this.requester.route("hello").data("Hello RSocket").retrieveMono(String.class);
59 | }
60 |
61 | }
--------------------------------------------------------------------------------
/server-requester/client/src/main/resources/application.properties:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/server-requester/server/.gitignore:
--------------------------------------------------------------------------------
1 | HELP.md
2 | target/
3 | !.mvn/wrapper/maven-wrapper.jar
4 | !**/src/main/**
5 | !**/src/test/**
6 |
7 | ### STS ###
8 | .apt_generated
9 | .classpath
10 | .factorypath
11 | .project
12 | .settings
13 | .springBeans
14 | .sts4-cache
15 |
16 | ### IntelliJ IDEA ###
17 | .idea
18 | *.iws
19 | *.iml
20 | *.ipr
21 |
22 | ### NetBeans ###
23 | /nbproject/private/
24 | /nbbuild/
25 | /dist/
26 | /nbdist/
27 | /.nb-gradle/
28 | build/
29 |
30 | ### VS Code ###
31 | .vscode/
32 |
--------------------------------------------------------------------------------
/server-requester/server/lombok.config:
--------------------------------------------------------------------------------
1 | lombok.noArgsConstructor.extraPrivate=true
2 |
--------------------------------------------------------------------------------
/server-requester/server/nbactions.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | run
5 |
6 | jar
7 |
8 |
9 | spring-boot:run
10 |
11 |
12 | -noverify -XX:TieredStopAtLevel=1
13 | com.example.demo.ProducerApplication
14 | always
15 |
16 |
17 |
18 | debug
19 |
20 | jar
21 |
22 |
23 | spring-boot:run
24 |
25 |
26 | -Xdebug -Xrunjdwp:transport=dt_socket,server=n,address=${jpda.address} -noverify -XX:TieredStopAtLevel=1
27 | com.example.demo.ProducerApplication
28 | always
29 | true
30 |
31 |
32 |
33 | profile
34 |
35 | jar
36 |
37 |
38 | process-classes
39 | org.codehaus.mojo:exec-maven-plugin:1.2.1:exec
40 |
41 |
42 | -classpath %classpath com.example.demo.ProducerApplication
43 | java
44 |
45 |
46 |
47 |
--------------------------------------------------------------------------------
/server-requester/server/pom.xml:
--------------------------------------------------------------------------------
1 |
2 |
4 | 4.0.0
5 |
6 | org.springframework.boot
7 | spring-boot-starter-parent
8 | 2.2.5.RELEASE
9 |
10 |
11 | com.example
12 | rsocket-sample-boot-server-requester-server
13 | 0.0.1-SNAPSHOT
14 | rsocket-sample-boot-server-requester-server
15 | Demo project for Spring Boot
16 |
17 |
18 | 11
19 |
20 |
21 |
22 |
23 | org.springframework.boot
24 | spring-boot-starter-rsocket
25 |
26 |
27 |
28 | org.projectlombok
29 | lombok
30 | true
31 |
32 |
33 | org.springframework.boot
34 | spring-boot-starter-test
35 | test
36 |
37 |
38 | org.junit.vintage
39 | junit-vintage-engine
40 |
41 |
42 |
43 |
44 | io.projectreactor
45 | reactor-test
46 | test
47 |
48 |
49 |
50 |
51 |
52 |
53 | org.springframework.boot
54 | spring-boot-maven-plugin
55 |
56 |
57 |
58 |
59 |
60 |
61 | spring-milestones
62 | Spring Milestones
63 | https://repo.spring.io/milestone
64 |
65 |
66 |
67 |
68 | spring-milestones
69 | Spring Milestones
70 | https://repo.spring.io/milestone
71 |
72 |
73 |
74 |
75 |
--------------------------------------------------------------------------------
/server-requester/server/src/main/java/com/example/demo/DemoApplication.java:
--------------------------------------------------------------------------------
1 | package com.example.demo;
2 |
3 | import lombok.Data;
4 | import lombok.extern.slf4j.Slf4j;
5 | import org.springframework.boot.SpringApplication;
6 | import org.springframework.boot.autoconfigure.SpringBootApplication;
7 | import org.springframework.messaging.handler.annotation.MessageMapping;
8 | import org.springframework.messaging.handler.annotation.Payload;
9 | import org.springframework.messaging.rsocket.RSocketRequester;
10 | import org.springframework.messaging.rsocket.annotation.ConnectMapping;
11 | import org.springframework.stereotype.Controller;
12 | import reactor.core.publisher.Flux;
13 | import reactor.core.publisher.Mono;
14 |
15 | import java.time.Duration;
16 | import java.time.LocalDateTime;
17 | import java.util.HashMap;
18 | import java.util.List;
19 | import java.util.Map;
20 | import java.util.Random;
21 |
22 | @SpringBootApplication
23 | public class DemoApplication {
24 |
25 | public static void main(String[] args) {
26 | SpringApplication.run(DemoApplication.class, args);
27 | }
28 |
29 | }
30 |
31 | @Controller
32 | @Slf4j
33 | class GreetingController {
34 | private final Map REQESTER_MAP = new HashMap<>();
35 |
36 | @ConnectMapping("connect")
37 | void setup(RSocketRequester requester, @Payload String user) {
38 | log.info("@ConnectMapping(connect), user:{}", user);
39 | requester.rsocket()
40 | .onClose()
41 | .doFinally(
42 | f -> REQESTER_MAP.remove(user, requester)
43 | );
44 | REQESTER_MAP.put(user, requester);
45 | log.info("send status back to client...");
46 | requester.route("status").data("user:" + user + " is connected!")
47 | .retrieveMono(String.class)
48 | .subscribe(
49 | data -> log.info("received data from the client: {}", data),
50 | error -> log.error("error: {}", error),
51 | () -> log.info("done")
52 | );
53 | }
54 |
55 | @MessageMapping("hello")
56 | Mono ping(@Payload String message) {
57 | log.info("@MessageMapping(hello), payload : {}", message);
58 | return Mono.just("received (" + message + ") at " + LocalDateTime.now());
59 | }
60 | }
61 |
62 |
--------------------------------------------------------------------------------
/server-requester/server/src/main/resources/application.properties:
--------------------------------------------------------------------------------
1 | spring.rsocket.server.port=7000
2 | spring.rsocket.server.transport=tcp
3 | logging.level.com.example=DEBUG
4 |
--------------------------------------------------------------------------------
/tcp/client/.gitignore:
--------------------------------------------------------------------------------
1 | HELP.md
2 | target/
3 | !.mvn/wrapper/maven-wrapper.jar
4 | !**/src/main/**
5 | !**/src/test/**
6 |
7 | ### STS ###
8 | .apt_generated
9 | .classpath
10 | .factorypath
11 | .project
12 | .settings
13 | .springBeans
14 | .sts4-cache
15 |
16 | ### IntelliJ IDEA ###
17 | .idea
18 | *.iws
19 | *.iml
20 | *.ipr
21 |
22 | ### NetBeans ###
23 | /nbproject/private/
24 | /nbbuild/
25 | /dist/
26 | /nbdist/
27 | /.nb-gradle/
28 | build/
29 |
30 | ### VS Code ###
31 | .vscode/
32 |
--------------------------------------------------------------------------------
/tcp/client/lombok.config:
--------------------------------------------------------------------------------
1 | lombok.noArgsConstructor.extraPrivate=true
2 |
--------------------------------------------------------------------------------
/tcp/client/nbactions.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | run
5 |
6 | jar
7 |
8 |
9 | spring-boot:run
10 |
11 |
12 | -noverify -XX:TieredStopAtLevel=1
13 | com.example.consumer.ConsumerApplication
14 | always
15 |
16 |
17 |
18 | debug
19 |
20 | jar
21 |
22 |
23 | spring-boot:run
24 |
25 |
26 | -Xdebug -Xrunjdwp:transport=dt_socket,server=n,address=${jpda.address} -noverify -XX:TieredStopAtLevel=1
27 | com.example.consumer.ConsumerApplication
28 | always
29 | true
30 |
31 |
32 |
33 | profile
34 |
35 | jar
36 |
37 |
38 | process-classes
39 | org.codehaus.mojo:exec-maven-plugin:1.2.1:exec
40 |
41 |
42 | -classpath %classpath com.example.consumer.ConsumerApplication
43 | java
44 |
45 |
46 |
47 |
--------------------------------------------------------------------------------
/tcp/client/pom.xml:
--------------------------------------------------------------------------------
1 |
2 |
4 | 4.0.0
5 |
6 | org.springframework.boot
7 | spring-boot-starter-parent
8 | 2.2.5.RELEASE
9 |
10 |
11 | com.example
12 | rsocket-sample-boot-tcp-client
13 | 0.0.1-SNAPSHOT
14 | rsocket-sample-boot-tcp-client
15 | Demo project for Spring Boot
16 |
17 |
18 | 11
19 |
20 |
21 |
22 |
23 | org.springframework.boot
24 | spring-boot-starter-webflux
25 |
26 |
27 | org.springframework.boot
28 | spring-boot-starter-rsocket
29 |
30 |
31 |
32 | org.projectlombok
33 | lombok
34 | true
35 |
36 |
37 | org.springframework.boot
38 | spring-boot-starter-test
39 | test
40 |
41 |
42 | org.junit.vintage
43 | junit-vintage-engine
44 |
45 |
46 |
47 |
48 |
49 |
50 |
51 |
52 | org.springframework.boot
53 | spring-boot-maven-plugin
54 |
55 |
56 |
57 |
58 |
59 |
60 | spring-milestones
61 | Spring Milestones
62 | https://repo.spring.io/milestone
63 |
64 |
65 |
66 |
67 | spring-milestones
68 | Spring Milestones
69 | https://repo.spring.io/milestone
70 |
71 |
72 |
73 |
74 |
--------------------------------------------------------------------------------
/tcp/client/src/main/java/com/example/client/ClientApplication.java:
--------------------------------------------------------------------------------
1 | package com.example.client;
2 |
3 | import lombok.AllArgsConstructor;
4 | import lombok.Data;
5 | import lombok.RequiredArgsConstructor;
6 | import lombok.extern.slf4j.Slf4j;
7 | import org.springframework.boot.SpringApplication;
8 | import org.springframework.boot.autoconfigure.SpringBootApplication;
9 | import org.springframework.context.annotation.Bean;
10 | import org.springframework.http.MediaType;
11 | import org.springframework.messaging.rsocket.RSocketRequester;
12 | import org.springframework.util.MimeTypeUtils;
13 | import org.springframework.web.bind.annotation.GetMapping;
14 | import org.springframework.web.bind.annotation.PathVariable;
15 | import org.springframework.web.bind.annotation.RestController;
16 | import reactor.core.publisher.Flux;
17 | import reactor.core.publisher.Mono;
18 |
19 | @SpringBootApplication
20 | public class ClientApplication {
21 |
22 | public static void main(String[] args) {
23 | SpringApplication.run(ClientApplication.class, args);
24 | }
25 |
26 | @Bean
27 | public RSocketRequester rSocketRequester(RSocketRequester.Builder b) {
28 | return b.dataMimeType(MimeTypeUtils.APPLICATION_JSON)
29 | .connectTcp("localhost", 7000).block();
30 | }
31 |
32 | }
33 |
34 | @Slf4j
35 | @RestController()
36 | @RequiredArgsConstructor
37 | class GreetingController {
38 |
39 | private final RSocketRequester requester;
40 |
41 | @GetMapping("hello")
42 | Mono hello() {
43 | return this.requester.route("hello").data(new Greeting("Welcome to Rsocket")).send();
44 | }
45 |
46 | @GetMapping("name/{name}")
47 | Mono greet(@PathVariable String name) {
48 | return this.requester.route("greet." + name)
49 | .data(new Greeting("Welcome to RSocket"))
50 | .retrieveMono(String.class)
51 | .doOnNext(msg -> log.info("recevied message::" + msg));
52 | }
53 |
54 | @GetMapping(value = "stream", produces = MediaType.TEXT_EVENT_STREAM_VALUE)
55 | Flux greetStream() {
56 | return this.requester.route("greet-stream").data(new Greeting("Welcome to RSocket"))
57 | .retrieveFlux(String.class)
58 | .doOnNext(msg -> log.info("received messages::" + msg));
59 | }
60 |
61 | @GetMapping(value = "channel", produces = MediaType.TEXT_EVENT_STREAM_VALUE)
62 | Flux greetChannel() {
63 | return this.requester.route("greet-channel")
64 | .data(
65 | Flux.range(0, 10)
66 | .map(i -> new Greeting("Welcome to RSocket #" + i))
67 | )
68 | .retrieveFlux(String.class)
69 | .doOnNext(msg -> log.info("received messages::" + msg));
70 | }
71 | }
72 |
73 | @Data
74 | @AllArgsConstructor
75 | class Greeting {
76 |
77 | String message;
78 | }
79 |
--------------------------------------------------------------------------------
/tcp/client/src/main/resources/application.properties:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/tcp/client/src/test/java/com/example/consumer/ConsumerApplicationTests.java:
--------------------------------------------------------------------------------
1 | package com.example.consumer;
2 |
3 | import org.junit.jupiter.api.Test;
4 | import org.springframework.boot.test.context.SpringBootTest;
5 |
6 | @SpringBootTest
7 | class ConsumerApplicationTests {
8 |
9 | @Test
10 | void contextLoads() {
11 | }
12 |
13 | }
14 |
--------------------------------------------------------------------------------
/tcp/server/.gitignore:
--------------------------------------------------------------------------------
1 | HELP.md
2 | target/
3 | !.mvn/wrapper/maven-wrapper.jar
4 | !**/src/main/**
5 | !**/src/test/**
6 |
7 | ### STS ###
8 | .apt_generated
9 | .classpath
10 | .factorypath
11 | .project
12 | .settings
13 | .springBeans
14 | .sts4-cache
15 |
16 | ### IntelliJ IDEA ###
17 | .idea
18 | *.iws
19 | *.iml
20 | *.ipr
21 |
22 | ### NetBeans ###
23 | /nbproject/private/
24 | /nbbuild/
25 | /dist/
26 | /nbdist/
27 | /.nb-gradle/
28 | build/
29 |
30 | ### VS Code ###
31 | .vscode/
32 |
--------------------------------------------------------------------------------
/tcp/server/nbactions.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | run
5 |
6 | jar
7 |
8 |
9 | spring-boot:run
10 |
11 |
12 | -noverify -XX:TieredStopAtLevel=1
13 | com.example.producer.ProducerApplication
14 | always
15 |
16 |
17 |
18 | debug
19 |
20 | jar
21 |
22 |
23 | spring-boot:run
24 |
25 |
26 | -Xdebug -Xrunjdwp:transport=dt_socket,server=n,address=${jpda.address} -noverify -XX:TieredStopAtLevel=1
27 | com.example.producer.ProducerApplication
28 | always
29 | true
30 |
31 |
32 |
33 | profile
34 |
35 | jar
36 |
37 |
38 | process-classes
39 | org.codehaus.mojo:exec-maven-plugin:1.2.1:exec
40 |
41 |
42 | -classpath %classpath com.example.producer.ProducerApplication
43 | java
44 |
45 |
46 |
47 |
--------------------------------------------------------------------------------
/tcp/server/pom.xml:
--------------------------------------------------------------------------------
1 |
2 |
4 | 4.0.0
5 |
6 | org.springframework.boot
7 | spring-boot-starter-parent
8 | 2.2.5.RELEASE
9 |
10 |
11 | com.example
12 | rsocket-sample-boot-tcp-server
13 | 0.0.1-SNAPSHOT
14 | rsocket-sample-boot-tcp-server
15 | Demo project for Spring Boot
16 |
17 |
18 | 11
19 |
20 |
21 |
22 |
23 | org.springframework.boot
24 | spring-boot-starter-rsocket
25 |
26 |
27 |
28 | org.projectlombok
29 | lombok
30 | true
31 |
32 |
33 | org.springframework.boot
34 | spring-boot-starter-test
35 | test
36 |
37 |
38 | org.junit.vintage
39 | junit-vintage-engine
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 | org.springframework.boot
49 | spring-boot-maven-plugin
50 |
51 |
52 |
53 |
54 |
55 |
56 | spring-milestones
57 | Spring Milestones
58 | https://repo.spring.io/milestone
59 |
60 |
61 |
62 |
63 | spring-milestones
64 | Spring Milestones
65 | https://repo.spring.io/milestone
66 |
67 |
68 |
69 |
70 |
--------------------------------------------------------------------------------
/tcp/server/src/main/java/com/example/server/ServerApplication.java:
--------------------------------------------------------------------------------
1 | package com.example.server;
2 |
3 | import java.time.Duration;
4 | import java.time.Instant;
5 |
6 | import lombok.Data;
7 | import lombok.extern.slf4j.Slf4j;
8 | import org.reactivestreams.Publisher;
9 | import org.springframework.boot.SpringApplication;
10 | import org.springframework.boot.autoconfigure.SpringBootApplication;
11 | import org.springframework.messaging.handler.annotation.DestinationVariable;
12 | import org.springframework.messaging.handler.annotation.MessageMapping;
13 | import org.springframework.messaging.handler.annotation.Payload;
14 | import org.springframework.stereotype.Controller;
15 | import reactor.core.publisher.Flux;
16 | import reactor.core.publisher.Mono;
17 |
18 | @SpringBootApplication
19 | public class ServerApplication {
20 |
21 | public static void main(String[] args) {
22 | SpringApplication.run(ServerApplication.class, args);
23 | }
24 |
25 | }
26 |
27 | @Controller
28 | @Slf4j
29 | class GreetingServerController {
30 |
31 | @MessageMapping("hello")
32 | public Mono hello(Greeting p) {
33 | log.info("received: {} at {}", p, Instant.now());
34 | return Mono.empty();
35 | }
36 |
37 | @MessageMapping("greet.{name}")
38 | public Mono greet(@DestinationVariable String name, @Payload Greeting p) {
39 | log.info("received: {}, {} at {}", name, p, Instant.now());
40 | return Mono.just("Hello " + name + ", " + p.getMessage() + " at " + Instant.now());
41 | }
42 |
43 | @MessageMapping("greet-stream")
44 | public Flux greetStream(@Payload Greeting p) {
45 | log.info("received: {} at {}", p, Instant.now());
46 | return Flux.interval(Duration.ofSeconds(1))
47 | .map(i -> "greet-stream#(Hello #" + i + "," + p.getMessage() + ") at " + Instant.now());
48 | }
49 |
50 | @MessageMapping("greet-channel")
51 | public Flux greetChannel(@Payload Flux p) {
52 | log.info("received: {} at {}", p, Instant.now());
53 | return p.delayElements(Duration.ofSeconds(1))
54 | .map(m -> "greet-channel#(" + m + ") at " + Instant.now());
55 | }
56 |
57 | }
58 |
59 | @Data
60 | class Greeting {
61 | String message;
62 | }
63 |
--------------------------------------------------------------------------------
/tcp/server/src/main/resources/application.properties:
--------------------------------------------------------------------------------
1 | spring.rsocket.server.port=7000
2 | spring.rsocket.server.transport=tcp
3 |
--------------------------------------------------------------------------------
/tcp/server/src/test/java/com/example/producer/ProducerApplicationTests.java:
--------------------------------------------------------------------------------
1 | package com.example.producer;
2 |
3 | import org.junit.jupiter.api.Test;
4 | import org.springframework.boot.test.context.SpringBootTest;
5 |
6 | @SpringBootTest
7 | class ProducerApplicationTests {
8 |
9 | @Test
10 | void contextLoads() {
11 | }
12 |
13 | }
14 |
--------------------------------------------------------------------------------
/vanilla/.gitignore:
--------------------------------------------------------------------------------
1 | HELP.md
2 | target/
3 | !.mvn/wrapper/maven-wrapper.jar
4 | !**/src/main/**
5 | !**/src/test/**
6 |
7 | ### STS ###
8 | .apt_generated
9 | .classpath
10 | .factorypath
11 | .project
12 | .settings
13 | .springBeans
14 | .sts4-cache
15 |
16 | ### IntelliJ IDEA ###
17 | .idea
18 | *.iws
19 | *.iml
20 | *.ipr
21 |
22 | ### NetBeans ###
23 | /nbproject/private/
24 | /nbbuild/
25 | /dist/
26 | /nbdist/
27 | /.nb-gradle/
28 | build/
29 |
30 | ### VS Code ###
31 | .vscode/
32 |
--------------------------------------------------------------------------------
/vanilla/.mvn/wrapper/MavenWrapperDownloader.java:
--------------------------------------------------------------------------------
1 | /*
2 | Licensed to the Apache Software Foundation (ASF) under one
3 | or more contributor license agreements. See the NOTICE file
4 | distributed with this work for additional information
5 | regarding copyright ownership. The ASF licenses this file
6 | to you under the Apache License, Version 2.0 (the
7 | "License"); you may not use this file except in compliance
8 | with the License. You may obtain a copy of the License at
9 |
10 | https://www.apache.org/licenses/LICENSE-2.0
11 |
12 | Unless required by applicable law or agreed to in writing,
13 | software distributed under the License is distributed on an
14 | "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15 | KIND, either express or implied. See the License for the
16 | specific language governing permissions and limitations
17 | under the License.
18 | */
19 |
20 | import java.io.File;
21 | import java.io.FileInputStream;
22 | import java.io.FileOutputStream;
23 | import java.io.IOException;
24 | import java.net.URL;
25 | import java.nio.channels.Channels;
26 | import java.nio.channels.ReadableByteChannel;
27 | import java.util.Properties;
28 |
29 | public class MavenWrapperDownloader {
30 |
31 | /**
32 | * Default URL to download the maven-wrapper.jar from, if no 'downloadUrl' is provided.
33 | */
34 | private static final String DEFAULT_DOWNLOAD_URL =
35 | "https://repo.maven.apache.org/maven2/io/takari/maven-wrapper/0.4.2/maven-wrapper-0.4.2.jar";
36 |
37 | /**
38 | * Path to the maven-wrapper.properties file, which might contain a downloadUrl property to
39 | * use instead of the default one.
40 | */
41 | private static final String MAVEN_WRAPPER_PROPERTIES_PATH =
42 | ".mvn/wrapper/maven-wrapper.properties";
43 |
44 | /**
45 | * Path where the maven-wrapper.jar will be saved to.
46 | */
47 | private static final String MAVEN_WRAPPER_JAR_PATH =
48 | ".mvn/wrapper/maven-wrapper.jar";
49 |
50 | /**
51 | * Name of the property which should be used to override the default download url for the wrapper.
52 | */
53 | private static final String PROPERTY_NAME_WRAPPER_URL = "wrapperUrl";
54 |
55 | public static void main(String args[]) {
56 | System.out.println("- Downloader started");
57 | File baseDirectory = new File(args[0]);
58 | System.out.println("- Using base directory: " + baseDirectory.getAbsolutePath());
59 |
60 | // If the maven-wrapper.properties exists, read it and check if it contains a custom
61 | // wrapperUrl parameter.
62 | File mavenWrapperPropertyFile = new File(baseDirectory, MAVEN_WRAPPER_PROPERTIES_PATH);
63 | String url = DEFAULT_DOWNLOAD_URL;
64 | if(mavenWrapperPropertyFile.exists()) {
65 | FileInputStream mavenWrapperPropertyFileInputStream = null;
66 | try {
67 | mavenWrapperPropertyFileInputStream = new FileInputStream(mavenWrapperPropertyFile);
68 | Properties mavenWrapperProperties = new Properties();
69 | mavenWrapperProperties.load(mavenWrapperPropertyFileInputStream);
70 | url = mavenWrapperProperties.getProperty(PROPERTY_NAME_WRAPPER_URL, url);
71 | } catch (IOException e) {
72 | System.out.println("- ERROR loading '" + MAVEN_WRAPPER_PROPERTIES_PATH + "'");
73 | } finally {
74 | try {
75 | if(mavenWrapperPropertyFileInputStream != null) {
76 | mavenWrapperPropertyFileInputStream.close();
77 | }
78 | } catch (IOException e) {
79 | // Ignore ...
80 | }
81 | }
82 | }
83 | System.out.println("- Downloading from: : " + url);
84 |
85 | File outputFile = new File(baseDirectory.getAbsolutePath(), MAVEN_WRAPPER_JAR_PATH);
86 | if(!outputFile.getParentFile().exists()) {
87 | if(!outputFile.getParentFile().mkdirs()) {
88 | System.out.println(
89 | "- ERROR creating output direcrory '" + outputFile.getParentFile().getAbsolutePath() + "'");
90 | }
91 | }
92 | System.out.println("- Downloading to: " + outputFile.getAbsolutePath());
93 | try {
94 | downloadFileFromURL(url, outputFile);
95 | System.out.println("Done");
96 | System.exit(0);
97 | } catch (Throwable e) {
98 | System.out.println("- Error downloading");
99 | e.printStackTrace();
100 | System.exit(1);
101 | }
102 | }
103 |
104 | private static void downloadFileFromURL(String urlString, File destination) throws Exception {
105 | URL website = new URL(urlString);
106 | ReadableByteChannel rbc;
107 | rbc = Channels.newChannel(website.openStream());
108 | FileOutputStream fos = new FileOutputStream(destination);
109 | fos.getChannel().transferFrom(rbc, 0, Long.MAX_VALUE);
110 | fos.close();
111 | rbc.close();
112 | }
113 |
114 | }
115 |
--------------------------------------------------------------------------------
/vanilla/.mvn/wrapper/maven-wrapper.jar:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/hantsy/rsocket-sample/7349fd955764b163ac061b00d30d8a8646a0fcdd/vanilla/.mvn/wrapper/maven-wrapper.jar
--------------------------------------------------------------------------------
/vanilla/.mvn/wrapper/maven-wrapper.properties:
--------------------------------------------------------------------------------
1 | distributionUrl=https://repo.maven.apache.org/maven2/org/apache/maven/apache-maven/3.6.0/apache-maven-3.6.0-bin.zip
2 |
--------------------------------------------------------------------------------
/vanilla/mvnw.cmd:
--------------------------------------------------------------------------------
1 | @REM ----------------------------------------------------------------------------
2 | @REM Licensed to the Apache Software Foundation (ASF) under one
3 | @REM or more contributor license agreements. See the NOTICE file
4 | @REM distributed with this work for additional information
5 | @REM regarding copyright ownership. The ASF licenses this file
6 | @REM to you under the Apache License, Version 2.0 (the
7 | @REM "License"); you may not use this file except in compliance
8 | @REM with the License. You may obtain a copy of the License at
9 | @REM
10 | @REM https://www.apache.org/licenses/LICENSE-2.0
11 | @REM
12 | @REM Unless required by applicable law or agreed to in writing,
13 | @REM software distributed under the License is distributed on an
14 | @REM "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15 | @REM KIND, either express or implied. See the License for the
16 | @REM specific language governing permissions and limitations
17 | @REM under the License.
18 | @REM ----------------------------------------------------------------------------
19 |
20 | @REM ----------------------------------------------------------------------------
21 | @REM Maven2 Start Up Batch script
22 | @REM
23 | @REM Required ENV vars:
24 | @REM JAVA_HOME - location of a JDK home dir
25 | @REM
26 | @REM Optional ENV vars
27 | @REM M2_HOME - location of maven2's installed home dir
28 | @REM MAVEN_BATCH_ECHO - set to 'on' to enable the echoing of the batch commands
29 | @REM MAVEN_BATCH_PAUSE - set to 'on' to wait for a key stroke before ending
30 | @REM MAVEN_OPTS - parameters passed to the Java VM when running Maven
31 | @REM e.g. to debug Maven itself, use
32 | @REM set MAVEN_OPTS=-Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=8000
33 | @REM MAVEN_SKIP_RC - flag to disable loading of mavenrc files
34 | @REM ----------------------------------------------------------------------------
35 |
36 | @REM Begin all REM lines with '@' in case MAVEN_BATCH_ECHO is 'on'
37 | @echo off
38 | @REM set title of command window
39 | title %0
40 | @REM enable echoing my setting MAVEN_BATCH_ECHO to 'on'
41 | @if "%MAVEN_BATCH_ECHO%" == "on" echo %MAVEN_BATCH_ECHO%
42 |
43 | @REM set %HOME% to equivalent of $HOME
44 | if "%HOME%" == "" (set "HOME=%HOMEDRIVE%%HOMEPATH%")
45 |
46 | @REM Execute a user defined script before this one
47 | if not "%MAVEN_SKIP_RC%" == "" goto skipRcPre
48 | @REM check for pre script, once with legacy .bat ending and once with .cmd ending
49 | if exist "%HOME%\mavenrc_pre.bat" call "%HOME%\mavenrc_pre.bat"
50 | if exist "%HOME%\mavenrc_pre.cmd" call "%HOME%\mavenrc_pre.cmd"
51 | :skipRcPre
52 |
53 | @setlocal
54 |
55 | set ERROR_CODE=0
56 |
57 | @REM To isolate internal variables from possible post scripts, we use another setlocal
58 | @setlocal
59 |
60 | @REM ==== START VALIDATION ====
61 | if not "%JAVA_HOME%" == "" goto OkJHome
62 |
63 | echo.
64 | echo Error: JAVA_HOME not found in your environment. >&2
65 | echo Please set the JAVA_HOME variable in your environment to match the >&2
66 | echo location of your Java installation. >&2
67 | echo.
68 | goto error
69 |
70 | :OkJHome
71 | if exist "%JAVA_HOME%\bin\java.exe" goto init
72 |
73 | echo.
74 | echo Error: JAVA_HOME is set to an invalid directory. >&2
75 | echo JAVA_HOME = "%JAVA_HOME%" >&2
76 | echo Please set the JAVA_HOME variable in your environment to match the >&2
77 | echo location of your Java installation. >&2
78 | echo.
79 | goto error
80 |
81 | @REM ==== END VALIDATION ====
82 |
83 | :init
84 |
85 | @REM Find the project base dir, i.e. the directory that contains the folder ".mvn".
86 | @REM Fallback to current working directory if not found.
87 |
88 | set MAVEN_PROJECTBASEDIR=%MAVEN_BASEDIR%
89 | IF NOT "%MAVEN_PROJECTBASEDIR%"=="" goto endDetectBaseDir
90 |
91 | set EXEC_DIR=%CD%
92 | set WDIR=%EXEC_DIR%
93 | :findBaseDir
94 | IF EXIST "%WDIR%"\.mvn goto baseDirFound
95 | cd ..
96 | IF "%WDIR%"=="%CD%" goto baseDirNotFound
97 | set WDIR=%CD%
98 | goto findBaseDir
99 |
100 | :baseDirFound
101 | set MAVEN_PROJECTBASEDIR=%WDIR%
102 | cd "%EXEC_DIR%"
103 | goto endDetectBaseDir
104 |
105 | :baseDirNotFound
106 | set MAVEN_PROJECTBASEDIR=%EXEC_DIR%
107 | cd "%EXEC_DIR%"
108 |
109 | :endDetectBaseDir
110 |
111 | IF NOT EXIST "%MAVEN_PROJECTBASEDIR%\.mvn\jvm.config" goto endReadAdditionalConfig
112 |
113 | @setlocal EnableExtensions EnableDelayedExpansion
114 | for /F "usebackq delims=" %%a in ("%MAVEN_PROJECTBASEDIR%\.mvn\jvm.config") do set JVM_CONFIG_MAVEN_PROPS=!JVM_CONFIG_MAVEN_PROPS! %%a
115 | @endlocal & set JVM_CONFIG_MAVEN_PROPS=%JVM_CONFIG_MAVEN_PROPS%
116 |
117 | :endReadAdditionalConfig
118 |
119 | SET MAVEN_JAVA_EXE="%JAVA_HOME%\bin\java.exe"
120 | set WRAPPER_JAR="%MAVEN_PROJECTBASEDIR%\.mvn\wrapper\maven-wrapper.jar"
121 | set WRAPPER_LAUNCHER=org.apache.maven.wrapper.MavenWrapperMain
122 |
123 | set DOWNLOAD_URL="https://repo.maven.apache.org/maven2/io/takari/maven-wrapper/0.4.2/maven-wrapper-0.4.2.jar"
124 | FOR /F "tokens=1,2 delims==" %%A IN (%MAVEN_PROJECTBASEDIR%\.mvn\wrapper\maven-wrapper.properties) DO (
125 | IF "%%A"=="wrapperUrl" SET DOWNLOAD_URL=%%B
126 | )
127 |
128 | @REM Extension to allow automatically downloading the maven-wrapper.jar from Maven-central
129 | @REM This allows using the maven wrapper in projects that prohibit checking in binary data.
130 | if exist %WRAPPER_JAR% (
131 | echo Found %WRAPPER_JAR%
132 | ) else (
133 | echo Couldn't find %WRAPPER_JAR%, downloading it ...
134 | echo Downloading from: %DOWNLOAD_URL%
135 | powershell -Command "(New-Object Net.WebClient).DownloadFile('%DOWNLOAD_URL%', '%WRAPPER_JAR%')"
136 | echo Finished downloading %WRAPPER_JAR%
137 | )
138 | @REM End of extension
139 |
140 | %MAVEN_JAVA_EXE% %JVM_CONFIG_MAVEN_PROPS% %MAVEN_OPTS% %MAVEN_DEBUG_OPTS% -classpath %WRAPPER_JAR% "-Dmaven.multiModuleProjectDirectory=%MAVEN_PROJECTBASEDIR%" %WRAPPER_LAUNCHER% %MAVEN_CONFIG% %*
141 | if ERRORLEVEL 1 goto error
142 | goto end
143 |
144 | :error
145 | set ERROR_CODE=1
146 |
147 | :end
148 | @endlocal & set ERROR_CODE=%ERROR_CODE%
149 |
150 | if not "%MAVEN_SKIP_RC%" == "" goto skipRcPost
151 | @REM check for post script, once with legacy .bat ending and once with .cmd ending
152 | if exist "%HOME%\mavenrc_post.bat" call "%HOME%\mavenrc_post.bat"
153 | if exist "%HOME%\mavenrc_post.cmd" call "%HOME%\mavenrc_post.cmd"
154 | :skipRcPost
155 |
156 | @REM pause the script if MAVEN_BATCH_PAUSE is set to 'on'
157 | if "%MAVEN_BATCH_PAUSE%" == "on" pause
158 |
159 | if "%MAVEN_TERMINATE_CMD%" == "on" exit %ERROR_CODE%
160 |
161 | exit /B %ERROR_CODE%
162 |
--------------------------------------------------------------------------------
/vanilla/pom.xml:
--------------------------------------------------------------------------------
1 |
2 |
4 | 4.0.0
5 |
6 | org.springframework.boot
7 | spring-boot-starter-parent
8 | 2.2.0.RELEASE
9 |
10 |
11 | com.example
12 | rsocket-sample-vanilla
13 | 0.0.1-SNAPSHOT
14 | rsocket-sample-vanilla
15 | Demo project for Spring Boot
16 |
17 |
18 | 11
19 |
20 |
21 |
22 |
23 | org.springframework.boot
24 | spring-boot-starter-webflux
25 |
26 |
27 |
28 | io.rsocket
29 | rsocket-core
30 |
31 |
32 |
33 | io.rsocket
34 | rsocket-transport-netty
35 |
36 |
37 |
38 | org.projectlombok
39 | lombok
40 |
41 |
42 |
43 | org.springframework.boot
44 | spring-boot-starter-test
45 | test
46 |
47 |
48 | org.junit.vintage
49 | junit-vintage-engine
50 |
51 |
52 | junit
53 | junit
54 |
55 |
56 |
57 |
58 |
59 |
60 |
61 |
62 | org.springframework.boot
63 | spring-boot-maven-plugin
64 |
65 |
66 |
67 |
68 |
69 |
70 | spring-milestones
71 | Spring Milestones
72 | https://repo.spring.io/milestone
73 |
74 |
75 |
76 |
77 | spring-milestones
78 | Spring Milestones
79 | https://repo.spring.io/milestone
80 |
81 |
82 |
83 |
84 |
--------------------------------------------------------------------------------
/vanilla/src/main/java/com/example/demo/DemoApplication.java:
--------------------------------------------------------------------------------
1 | /*
2 | * To change this license header, choose License Headers in Project Properties.
3 | * To change this template file, choose Tools | Templates
4 | * and open the template in the editor.
5 | */
6 | package com.example.demo;
7 |
8 | import static com.example.demo.DemoApplication.PORT;
9 | import io.rsocket.AbstractRSocket;
10 | import io.rsocket.Payload;
11 | import io.rsocket.RSocketFactory;
12 | import io.rsocket.transport.netty.client.TcpClientTransport;
13 | import io.rsocket.transport.netty.server.TcpServerTransport;
14 | import io.rsocket.util.DefaultPayload;
15 | import java.time.Instant;
16 | import lombok.extern.slf4j.Slf4j;
17 | import org.springframework.boot.SpringApplication;
18 | import org.springframework.boot.autoconfigure.SpringBootApplication;
19 | import org.springframework.boot.context.event.ApplicationReadyEvent;
20 | import org.springframework.context.event.EventListener;
21 | import org.springframework.core.annotation.Order;
22 | import org.springframework.stereotype.Component;
23 | import reactor.core.publisher.Mono;
24 |
25 | /**
26 | *
27 | * @author hantsy
28 | */
29 | @SpringBootApplication
30 | @Slf4j
31 | public class DemoApplication {
32 |
33 | final static int PORT = 7000;
34 |
35 | public static void main(String[] args) {
36 | SpringApplication.run(DemoApplication.class, args);
37 | }
38 | }
39 |
40 | @Component
41 | @Order(0)
42 | @Slf4j
43 | class Producer {
44 |
45 | @EventListener(value = ApplicationReadyEvent.class)
46 | void init() {
47 |
48 | final AbstractRSocket responseHandler = new AbstractRSocket() {
49 |
50 | @Override
51 | public Mono requestResponse(Payload payload) {
52 | log.info("received request-response payload: {}", payload.getDataUtf8());
53 | return Mono.just(DefaultPayload.create("received (" + payload.getDataUtf8() + ") at " + Instant.now()));
54 | }
55 | };
56 |
57 | RSocketFactory.receive()
58 | .acceptor(
59 | (setupPayload, reactiveSocket)
60 | -> Mono.just(responseHandler)
61 | )
62 | .transport(TcpServerTransport.create("localhost", PORT))
63 | .start()
64 | .block();
65 | }
66 | }
67 |
68 | @Component
69 | @Slf4j
70 | class Consumer {
71 |
72 | @EventListener(value = ApplicationReadyEvent.class)
73 | void init() {
74 | RSocketFactory.connect()
75 | .transport(TcpClientTransport.create("localhost", PORT))
76 | .start()
77 | .flatMap(r -> r.requestResponse(DefaultPayload.create("Hello")))
78 | .subscribe(r -> log.info("handled result:#" + r.getDataUtf8()));
79 | }
80 | }
81 |
--------------------------------------------------------------------------------
/vanilla/src/main/java/com/example/demo/FireAndForgetExample.java:
--------------------------------------------------------------------------------
1 | package com.example.demo;
2 |
3 | import io.rsocket.AbstractRSocket;
4 | import io.rsocket.Payload;
5 | import io.rsocket.RSocket;
6 | import io.rsocket.RSocketFactory;
7 | import io.rsocket.transport.netty.client.TcpClientTransport;
8 | import io.rsocket.transport.netty.server.TcpServerTransport;
9 | import io.rsocket.util.DefaultPayload;
10 | import reactor.core.Disposable;
11 | import reactor.core.publisher.Mono;
12 |
13 | public class FireAndForgetExample {
14 |
15 | public static void main(String[] args) throws InterruptedException {
16 | final int port = 7000;
17 |
18 | final AbstractRSocket responseHandler = new AbstractRSocket() {
19 | @Override
20 | public Mono fireAndForget(Payload payload) {
21 | System.out.printf("received fire-forget payload: %s%n", payload.getDataUtf8());
22 | return Mono.empty();
23 | }
24 | };
25 |
26 | Disposable server = RSocketFactory.receive()
27 | .acceptor(
28 | (setupPayload, reactiveSocket)
29 | -> Mono.just(responseHandler)
30 | )
31 | .transport(TcpServerTransport.create("localhost", port))
32 | .start()
33 | .subscribe();
34 |
35 | System.out.printf("server is started on port:%d%n", port);
36 |
37 | RSocket socket
38 | = RSocketFactory.connect()
39 | .transport(TcpClientTransport.create("localhost", port))
40 | .start()
41 | .block();
42 | System.out.printf("client is connecting to port:%d%n", port);
43 | socket.fireAndForget(DefaultPayload.create("Hello"))
44 | .block();
45 |
46 | Thread.sleep(2_000);
47 | socket.dispose();
48 | server.dispose();
49 | }
50 | }
51 |
--------------------------------------------------------------------------------
/vanilla/src/main/java/com/example/demo/RequestChannelExample.java:
--------------------------------------------------------------------------------
1 | package com.example.demo;
2 |
3 | import io.rsocket.AbstractRSocket;
4 | import io.rsocket.Payload;
5 | import io.rsocket.RSocket;
6 | import io.rsocket.RSocketFactory;
7 | import io.rsocket.transport.netty.client.TcpClientTransport;
8 | import io.rsocket.transport.netty.server.TcpServerTransport;
9 | import io.rsocket.util.DefaultPayload;
10 | import java.time.Duration;
11 | import java.time.Instant;
12 | import org.reactivestreams.Publisher;
13 | import reactor.core.Disposable;
14 | import reactor.core.publisher.Flux;
15 | import reactor.core.publisher.Mono;
16 |
17 | public class RequestChannelExample {
18 |
19 | public static void main(String[] args) throws InterruptedException {
20 | final int port = 7000;
21 |
22 | final AbstractRSocket responseHandler = new AbstractRSocket() {
23 | @Override
24 | public Flux requestChannel(Publisher payloads) {
25 | return Flux.from(payloads)
26 | .map(p->p.getDataUtf8())
27 | .map(i -> DefaultPayload.create("received(" + i + ") at " + Instant.now()));
28 | }
29 |
30 | };
31 |
32 | Disposable server = RSocketFactory.receive()
33 | .acceptor(
34 | (setupPayload, reactiveSocket)
35 | -> Mono.just(responseHandler)
36 | )
37 | .transport(TcpServerTransport.create("localhost", port))
38 | .start()
39 | .subscribe();
40 | System.out.printf("server is started on port:%d%n", port);
41 |
42 | RSocket socket = RSocketFactory.connect()
43 | .transport(TcpClientTransport.create("localhost", port))
44 | .start()
45 | .block();
46 | System.out.printf("client is connecting to port:%d%n", port);
47 | socket.requestChannel(
48 | Flux.interval(Duration.ofSeconds(1))
49 | .map(i -> DefaultPayload.create("message #" + i)))
50 | .map(p -> p.getDataUtf8())
51 | .doOnNext(System.out::println)
52 | .take(10)
53 | .then()
54 | .doFinally(s -> socket.dispose())
55 | .then().block();
56 |
57 | server.dispose();
58 | }
59 | }
60 |
--------------------------------------------------------------------------------
/vanilla/src/main/java/com/example/demo/RequestResponseExample.java:
--------------------------------------------------------------------------------
1 | package com.example.demo;
2 |
3 | import io.rsocket.AbstractRSocket;
4 | import io.rsocket.Payload;
5 | import io.rsocket.RSocket;
6 | import io.rsocket.RSocketFactory;
7 | import io.rsocket.transport.netty.client.TcpClientTransport;
8 | import io.rsocket.transport.netty.server.TcpServerTransport;
9 | import io.rsocket.util.DefaultPayload;
10 | import java.time.Instant;
11 | import reactor.core.Disposable;
12 | import reactor.core.publisher.Mono;
13 |
14 | public class RequestResponseExample {
15 |
16 | public static void main(String[] args) throws InterruptedException {
17 | final int port = 7000;
18 |
19 | final AbstractRSocket responseHandler = new AbstractRSocket() {
20 |
21 | @Override
22 | public Mono requestResponse(Payload payload) {
23 |
24 | System.out.printf("received request-response payload: %s%n", payload.getDataUtf8());
25 | return Mono.just(DefaultPayload.create(payload.getDataUtf8() + " at "+ Instant.now()));
26 | }
27 | };
28 |
29 | Disposable server = RSocketFactory.receive()
30 | .acceptor(
31 | (setupPayload, reactiveSocket)
32 | -> Mono.just(responseHandler)
33 | )
34 | .transport(TcpServerTransport.create("localhost", port))
35 | .start()
36 | .subscribe();
37 | System.out.printf("server is started on port:%d%n", port);
38 |
39 | RSocket socket = RSocketFactory.connect()
40 | .transport(TcpClientTransport.create("localhost", port))
41 | .start()
42 | .block();
43 | System.out.printf("client is connecting to port:%d%n", port);
44 | socket.requestResponse(DefaultPayload.create("Hello"))
45 | .map(p -> p.getDataUtf8())
46 | .doOnNext(System.out::println)
47 | .block();
48 |
49 | socket.dispose();
50 | server.dispose();
51 | }
52 | }
53 |
--------------------------------------------------------------------------------
/vanilla/src/main/java/com/example/demo/RequestStreamExample.java:
--------------------------------------------------------------------------------
1 | package com.example.demo;
2 |
3 | import io.rsocket.AbstractRSocket;
4 | import io.rsocket.Payload;
5 | import io.rsocket.RSocket;
6 | import io.rsocket.RSocketFactory;
7 | import io.rsocket.transport.netty.client.TcpClientTransport;
8 | import io.rsocket.transport.netty.server.TcpServerTransport;
9 | import io.rsocket.util.DefaultPayload;
10 | import java.time.Duration;
11 | import java.time.Instant;
12 | import reactor.core.Disposable;
13 | import reactor.core.publisher.Flux;
14 | import reactor.core.publisher.Mono;
15 |
16 | public class RequestStreamExample {
17 |
18 | public static void main(String[] args) throws InterruptedException {
19 | final int port = 7000;
20 |
21 | final AbstractRSocket responseHandler = new AbstractRSocket() {
22 | @Override
23 | public Flux requestStream(Payload payload) {
24 | System.out.printf("received request-stream payload: %s%n", payload.getDataUtf8());
25 | return Flux.interval(Duration.ofMillis(100))
26 | .map(i -> DefaultPayload.create("message #" + i + " at " + Instant.now()));
27 | }
28 |
29 | };
30 |
31 | Disposable server = RSocketFactory.receive()
32 | .acceptor(
33 | (setupPayload, reactiveSocket)
34 | -> Mono.just(responseHandler)
35 | )
36 | .transport(TcpServerTransport.create("localhost", port))
37 | .start()
38 | .subscribe();
39 | System.out.printf("server is started on port:%d%n", port);
40 |
41 | RSocket socket = RSocketFactory.connect()
42 | .transport(TcpClientTransport.create("localhost", port))
43 | .start()
44 | .block();
45 | System.out.printf("client is connecting to port:%d%n", port);
46 | socket.requestStream(DefaultPayload.create("Hello"))
47 | .map(p -> p.getDataUtf8())
48 | .doOnNext(System.out::println)
49 | .take(10)
50 | .then()
51 | .doFinally(s-> socket.dispose())
52 | .then().block();
53 |
54 | //Thread.sleep(5_000);
55 | //socket.dispose();
56 | server.dispose();
57 | }
58 | }
59 |
--------------------------------------------------------------------------------
/vanilla/src/main/resources/application.properties:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/vanilla/src/test/java/com/example/demo/DemoApplicationTests.java:
--------------------------------------------------------------------------------
1 | package com.example.demo;
2 |
3 | import org.junit.jupiter.api.Test;
4 | import org.springframework.boot.test.context.SpringBootTest;
5 |
6 | @SpringBootTest
7 | class DemoApplicationTests {
8 |
9 | @Test
10 | void contextLoads() {
11 | }
12 |
13 | }
14 |
--------------------------------------------------------------------------------
/websocket/client/.gitignore:
--------------------------------------------------------------------------------
1 | HELP.md
2 | target/
3 | !.mvn/wrapper/maven-wrapper.jar
4 | !**/src/main/**
5 | !**/src/test/**
6 |
7 | ### STS ###
8 | .apt_generated
9 | .classpath
10 | .factorypath
11 | .project
12 | .settings
13 | .springBeans
14 | .sts4-cache
15 |
16 | ### IntelliJ IDEA ###
17 | .idea
18 | *.iws
19 | *.iml
20 | *.ipr
21 |
22 | ### NetBeans ###
23 | /nbproject/private/
24 | /nbbuild/
25 | /dist/
26 | /nbdist/
27 | /.nb-gradle/
28 | build/
29 |
30 | ### VS Code ###
31 | .vscode/
32 |
--------------------------------------------------------------------------------
/websocket/client/lombok.config:
--------------------------------------------------------------------------------
1 | lombok.noArgsConstructor.extraPrivate=true
2 |
--------------------------------------------------------------------------------
/websocket/client/nbactions.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | run
5 |
6 | jar
7 |
8 |
9 | spring-boot:run
10 |
11 |
12 | -noverify -XX:TieredStopAtLevel=1
13 | com.example.consumer.ConsumerApplication
14 | always
15 |
16 |
17 |
18 | debug
19 |
20 | jar
21 |
22 |
23 | spring-boot:run
24 |
25 |
26 | -Xdebug -Xrunjdwp:transport=dt_socket,server=n,address=${jpda.address} -noverify -XX:TieredStopAtLevel=1
27 | com.example.consumer.ConsumerApplication
28 | always
29 | true
30 |
31 |
32 |
33 | profile
34 |
35 | jar
36 |
37 |
38 | process-classes
39 | org.codehaus.mojo:exec-maven-plugin:1.2.1:exec
40 |
41 |
42 | -classpath %classpath com.example.consumer.ConsumerApplication
43 | java
44 |
45 |
46 |
47 |
--------------------------------------------------------------------------------
/websocket/client/pom.xml:
--------------------------------------------------------------------------------
1 |
2 |
4 | 4.0.0
5 |
6 | org.springframework.boot
7 | spring-boot-starter-parent
8 | 2.2.5.RELEASE
9 |
10 |
11 | com.example
12 | rsocket-sample-boot-ws-client
13 | 0.0.1-SNAPSHOT
14 | rsocket-sample-boot-ws-client
15 | Demo project for Spring Boot
16 |
17 |
18 | 11
19 |
20 |
21 |
22 |
23 | org.springframework.boot
24 | spring-boot-starter-webflux
25 |
26 |
27 | org.springframework.boot
28 | spring-boot-starter-rsocket
29 |
30 |
31 |
32 | org.projectlombok
33 | lombok
34 | true
35 |
36 |
37 | org.springframework.boot
38 | spring-boot-starter-test
39 | test
40 |
41 |
42 | org.junit.vintage
43 | junit-vintage-engine
44 |
45 |
46 |
47 |
48 |
49 |
50 |
51 |
52 | org.springframework.boot
53 | spring-boot-maven-plugin
54 |
55 |
56 |
57 |
58 |
59 |
60 | spring-milestones
61 | Spring Milestones
62 | https://repo.spring.io/milestone
63 |
64 |
65 |
66 |
67 | spring-milestones
68 | Spring Milestones
69 | https://repo.spring.io/milestone
70 |
71 |
72 |
73 |
74 |
--------------------------------------------------------------------------------
/websocket/client/src/main/java/com/example/client/ClientApplication.java:
--------------------------------------------------------------------------------
1 | package com.example.client;
2 |
3 | import java.net.URI;
4 | import java.time.Duration;
5 | import lombok.AllArgsConstructor;
6 | import lombok.Data;
7 | import lombok.RequiredArgsConstructor;
8 | import lombok.extern.slf4j.Slf4j;
9 | import org.springframework.boot.SpringApplication;
10 | import org.springframework.boot.autoconfigure.SpringBootApplication;
11 | import org.springframework.context.annotation.Bean;
12 | import org.springframework.http.MediaType;
13 | import org.springframework.messaging.rsocket.RSocketRequester;
14 | import org.springframework.util.MimeType;
15 | import org.springframework.util.MimeTypeUtils;
16 | import org.springframework.web.bind.annotation.GetMapping;
17 | import org.springframework.web.bind.annotation.PathVariable;
18 | import org.springframework.web.bind.annotation.RestController;
19 | import reactor.core.publisher.Flux;
20 | import reactor.core.publisher.Mono;
21 |
22 | @SpringBootApplication
23 | public class ClientApplication {
24 |
25 | public static void main(String[] args) {
26 | SpringApplication.run(ClientApplication.class, args);
27 | }
28 |
29 | @Bean
30 | public RSocketRequester rSocketRequester(RSocketRequester.Builder b) {
31 | return b.dataMimeType(MimeTypeUtils.APPLICATION_JSON)
32 | .connectWebSocket(URI.create("ws://localhost:8081/rsocket")).block();
33 | }
34 |
35 | }
36 |
37 | @Slf4j
38 | @RestController()
39 | @RequiredArgsConstructor
40 | class GreetingController {
41 |
42 | private final RSocketRequester requester;
43 |
44 | @GetMapping("hello")
45 | Mono hello() {
46 | return this.requester.route("hello").data(new Greeting("Welcome to Rsocket")).send();
47 | }
48 |
49 | @GetMapping("name/{name}")
50 | Mono greet(@PathVariable String name) {
51 | return this.requester.route("greet." + name).data(new Greeting("Welcome to Rsocket")).retrieveMono(String.class);
52 | }
53 |
54 | @GetMapping(value = "stream", produces = MediaType.TEXT_EVENT_STREAM_VALUE)
55 | Flux greetStream() {
56 | return this.requester.route("greet-stream").data(new Greeting("Welcome to Rsocket"))
57 | .retrieveFlux(String.class)
58 | .doOnNext(msg -> log.info("received messages::" + msg));
59 | }
60 |
61 | @GetMapping(value = "channel", produces = MediaType.TEXT_EVENT_STREAM_VALUE)
62 | Flux greetChannel() {
63 | return this.requester.route("greet-channel")
64 | .data(
65 | Flux.range(0, 10)
66 | .map(i -> new Greeting("Welcome to Rsocket #" + i))
67 | )
68 | .retrieveFlux(String.class)
69 | .doOnNext(msg -> log.info("received messages::" + msg));
70 | }
71 | }
72 |
73 | @Data
74 | @AllArgsConstructor
75 | class Greeting {
76 |
77 | String message;
78 | }
79 |
--------------------------------------------------------------------------------
/websocket/client/src/main/resources/application.properties:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/websocket/client/src/test/java/com/example/consumer/ConsumerApplicationTests.java:
--------------------------------------------------------------------------------
1 | package com.example.consumer;
2 |
3 | import org.junit.jupiter.api.Test;
4 | import org.springframework.boot.test.context.SpringBootTest;
5 |
6 | @SpringBootTest
7 | class ConsumerApplicationTests {
8 |
9 | @Test
10 | void contextLoads() {
11 | }
12 |
13 | }
14 |
--------------------------------------------------------------------------------
/websocket/server/.gitignore:
--------------------------------------------------------------------------------
1 | HELP.md
2 | target/
3 | !.mvn/wrapper/maven-wrapper.jar
4 | !**/src/main/**
5 | !**/src/test/**
6 |
7 | ### STS ###
8 | .apt_generated
9 | .classpath
10 | .factorypath
11 | .project
12 | .settings
13 | .springBeans
14 | .sts4-cache
15 |
16 | ### IntelliJ IDEA ###
17 | .idea
18 | *.iws
19 | *.iml
20 | *.ipr
21 |
22 | ### NetBeans ###
23 | /nbproject/private/
24 | /nbbuild/
25 | /dist/
26 | /nbdist/
27 | /.nb-gradle/
28 | build/
29 |
30 | ### VS Code ###
31 | .vscode/
32 |
--------------------------------------------------------------------------------
/websocket/server/nbactions.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | run
5 |
6 | jar
7 |
8 |
9 | spring-boot:run
10 |
11 |
12 | -noverify -XX:TieredStopAtLevel=1
13 | com.example.producer.ProducerApplication
14 | always
15 |
16 |
17 |
18 | debug
19 |
20 | jar
21 |
22 |
23 | spring-boot:run
24 |
25 |
26 | -Xdebug -Xrunjdwp:transport=dt_socket,server=n,address=${jpda.address} -noverify -XX:TieredStopAtLevel=1
27 | com.example.producer.ProducerApplication
28 | always
29 | true
30 |
31 |
32 |
33 | profile
34 |
35 | jar
36 |
37 |
38 | process-classes
39 | org.codehaus.mojo:exec-maven-plugin:1.2.1:exec
40 |
41 |
42 | -classpath %classpath com.example.producer.ProducerApplication
43 | java
44 |
45 |
46 |
47 |
--------------------------------------------------------------------------------
/websocket/server/pom.xml:
--------------------------------------------------------------------------------
1 |
2 |
4 | 4.0.0
5 |
6 | org.springframework.boot
7 | spring-boot-starter-parent
8 | 2.2.5.RELEASE
9 |
10 |
11 | com.example
12 | rsocket-sample-boot-ws-server
13 | 0.0.1-SNAPSHOT
14 | rsocket-sample-boot-ws-server
15 | Demo project for Spring Boot
16 |
17 |
18 | 11
19 |
20 |
21 |
22 |
23 | org.springframework.boot
24 | spring-boot-starter-webflux
25 |
26 |
27 | org.springframework.boot
28 | spring-boot-starter-rsocket
29 |
30 |
31 |
32 | org.projectlombok
33 | lombok
34 | true
35 |
36 |
37 | org.springframework.boot
38 | spring-boot-starter-test
39 | test
40 |
41 |
42 | org.junit.vintage
43 | junit-vintage-engine
44 |
45 |
46 |
47 |
48 |
49 |
50 |
51 |
52 | org.springframework.boot
53 | spring-boot-maven-plugin
54 |
55 |
56 |
57 |
58 |
59 |
60 | spring-milestones
61 | Spring Milestones
62 | https://repo.spring.io/milestone
63 |
64 |
65 |
66 |
67 | spring-milestones
68 | Spring Milestones
69 | https://repo.spring.io/milestone
70 |
71 |
72 |
73 |
74 |
--------------------------------------------------------------------------------
/websocket/server/src/main/java/com/example/server/HelloController.java:
--------------------------------------------------------------------------------
1 | package com.example.server;
2 |
3 | import org.springframework.web.bind.annotation.GetMapping;
4 | import org.springframework.web.bind.annotation.RestController;
5 |
6 | import java.time.Instant;
7 |
8 | @RestController
9 | public class HelloController {
10 |
11 | @GetMapping
12 | public String get() {
13 | return "server greeting at :" + Instant.now();
14 | }
15 | }
16 |
--------------------------------------------------------------------------------
/websocket/server/src/main/java/com/example/server/ServerApplication.java:
--------------------------------------------------------------------------------
1 | package com.example.server;
2 |
3 | import java.time.Duration;
4 | import java.time.Instant;
5 | import lombok.Data;
6 | import lombok.extern.slf4j.Slf4j;
7 | import org.reactivestreams.Publisher;
8 | import org.springframework.boot.SpringApplication;
9 | import org.springframework.boot.autoconfigure.SpringBootApplication;
10 | import org.springframework.messaging.handler.annotation.DestinationVariable;
11 | import org.springframework.messaging.handler.annotation.MessageMapping;
12 | import org.springframework.messaging.handler.annotation.Payload;
13 | import org.springframework.stereotype.Controller;
14 | import reactor.core.publisher.Flux;
15 | import reactor.core.publisher.Mono;
16 |
17 | @SpringBootApplication
18 | public class ServerApplication {
19 |
20 | public static void main(String[] args) {
21 | SpringApplication.run(ServerApplication.class, args);
22 | }
23 |
24 | }
25 |
26 | @Controller
27 | @Slf4j
28 | class GreetingServerController {
29 |
30 | @MessageMapping("hello")
31 | public Mono hello(Greeting p) {
32 | log.info("received: {} at {}", p, Instant.now());
33 | return Mono.empty();
34 | }
35 |
36 | @MessageMapping("greet.{name}")
37 | public Mono greet(@DestinationVariable String name, @Payload Greeting p) {
38 | log.info("received: {}, {} at {}", name, p, Instant.now());
39 | return Mono.just("Hello " + name + ", " + p.getMessage() + " at " + Instant.now());
40 | }
41 |
42 | @MessageMapping("greet-stream")
43 | public Flux greetStream(@Payload Greeting p) {
44 | log.info("received: {} at {}", p, Instant.now());
45 | return Flux.interval(Duration.ofSeconds(1))
46 | .map(i -> "greet-stream#(Hello #" + i + "," + p.getMessage() + ") at " + Instant.now());
47 | }
48 |
49 | @MessageMapping("greet-channel")
50 | public Flux greetChannel(@Payload Flux p) {
51 | log.info("received: {} at {}", p, Instant.now());
52 | return p.delayElements(Duration.ofSeconds(1))
53 | .map(m -> "greet-channel#(" + m + ") at " + Instant.now());
54 | }
55 |
56 | }
57 |
58 | @Data
59 | class Greeting {
60 |
61 | String message;
62 | }
63 |
--------------------------------------------------------------------------------
/websocket/server/src/main/resources/application.properties:
--------------------------------------------------------------------------------
1 | # a mapping path is defined
2 | spring.rsocket.server.mapping-path=/rsocket
3 | # websocket is chosen as a transport
4 | spring.rsocket.server.transport=websocket
5 | server.port=8081
--------------------------------------------------------------------------------
/websocket/server/src/test/java/com/example/producer/ProducerApplicationTests.java:
--------------------------------------------------------------------------------
1 | package com.example.producer;
2 |
3 | import org.junit.jupiter.api.Test;
4 | import org.springframework.boot.test.context.SpringBootTest;
5 |
6 | @SpringBootTest
7 | class ProducerApplicationTests {
8 |
9 | @Test
10 | void contextLoads() {
11 | }
12 |
13 | }
14 |
--------------------------------------------------------------------------------