Skip to content
This repository was archived by the owner on Jun 21, 2022. It is now read-only.

Commit a381929

Browse files
committed
Merge branch 'develop'
2 parents 9108b3c + 529ae26 commit a381929

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

54 files changed

+15839
-0
lines changed

.gitignore

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
.idea
2+
target
3+
*.iml
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
<component name="ProjectRunConfigurationManager">
2+
<configuration default="false" name="Server" type="SpringBootApplicationConfigurationType" factoryName="Spring Boot">
3+
<module name="gateway-rsocket-websocket" />
4+
<option name="SPRING_BOOT_MAIN_CLASS" value="com.nexiles.example.gatewayrsocketwebsocket.GatewayRsocketWebsocketApplication" />
5+
<option name="ALTERNATIVE_JRE_PATH" />
6+
<method v="2">
7+
<option name="Make" enabled="true" />
8+
</method>
9+
</configuration>
10+
</component>

.run/dev.run.xml

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
<component name="ProjectRunConfigurationManager">
2+
<configuration default="false" name="Client" type="js.build_tools.npm">
3+
<package-json value="$PROJECT_DIR$/frontend/package.json" />
4+
<command value="run" />
5+
<scripts>
6+
<script value="dev" />
7+
</scripts>
8+
<node-interpreter value="$USER_HOME$/.nvm/versions/node/v14.16.0/bin/node" />
9+
<envs />
10+
<method v="2" />
11+
</configuration>
12+
</component>

README.md

Lines changed: 238 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,238 @@
1+
# SpringCloud Gateway RSocket Example
2+
3+
## What is RSocket ?
4+
5+
Check out the official docs: [RSocket Docs](https://rsocket.io/docs/)
6+
7+
> Most interesting:
8+
>>Network communication is asynchronous. The RSocket protocol embraces
9+
>>this and models all communication as multiplexed streams of messages
10+
>>over a single network connection, and never synchronously blocks while
11+
>>waiting for a response
12+
13+
In this example I am using a SpringCloud Gateway (reactive) to demonstrate how
14+
RSocket communication works over **WebSocket**.
15+
16+
## Motivation
17+
18+
We'd like to use a **single** websocket *endpoint/broker* for multiple services.
19+
The *normal* spring integration with *STOMP over WebSocket* cannot be used on the
20+
reactive stack. Therefore, I had to take a deeper look into RSocket.
21+
22+
## The Example
23+
24+
The server is creating scheduled *order* events which are added to a stream, those can
25+
be retrieved using a *HTTP GET* or *RSocket Request Stream*.
26+
27+
There are two *kind* of order, LOTR (Lord of the Rings) order and GOT (game of Thrones) order,
28+
to demonstrate how *routes* (& security) can be handled.
29+
30+
The order event is a *order* with random *kind*.
31+
32+
## Test it
33+
34+
Either use the checked in IntelliJ run-configuration in *.run* or launch it manually.
35+
36+
**Server:** (Maven v3.6.3)
37+
38+
```shell
39+
$ mvn clean package
40+
$ cd target/
41+
$ java -jar {{appname-version}}.jar
42+
```
43+
44+
**Client:** (Node v14.16.0 & NPM v6.14.11)
45+
46+
```shell
47+
$ cd frontend
48+
$ npm install
49+
$ npm run dev
50+
```
51+
52+
The web browser will open automatically, and you are ready to test it.
53+
54+
#### Ports used
55+
56+
*Server:* 8070
57+
58+
*Client:* 8080
59+
60+
### Test with other tools
61+
62+
#### RSocket
63+
64+
For RSocket development is used [RSC](https://github.com/making/rsc) installed using
65+
`brew install making/tap/rsc`.
66+
67+
Now you are ready to go. Make sure the server is running and fire:
68+
69+
```shell
70+
# Basic
71+
$ rsc --stream --route=orders.all --debug ws://localhost:8070/server/rsocket
72+
$ rsc --stream --route=orders.lotr --debug ws://localhost:8070/server/rsocket
73+
$ rsc --stream --route=orders.got --debug ws://localhost:8070/server/rsocket
74+
75+
# With data (payload)
76+
$ rsc --stream --route=orders.all --debug --data='{"rscclient":"request"}' ws://localhost:8070/server/rsocket
77+
78+
# With metadata
79+
$ rsc --stream --route=orders.all --debug --metadata='{"data":"custom metadata value from rsc"}' ws://localhost:8070/server/rsocket
80+
```
81+
82+
This will produce output like:
83+
84+
```text
85+
86+
2021-03-12 13:20:57.654 DEBUG 81691 --- [actor-tcp-nio-2] io.rsocket.FrameLogger : receiving ->
87+
Frame => Stream ID: 1 Type: NEXT Flags: 0b100000 Length: 194
88+
Data:
89+
+-------------------------------------------------+
90+
| 0 1 2 3 4 5 6 7 8 9 a b c d e f |
91+
+--------+-------------------------------------------------+----------------+
92+
|00000000| 7b 22 64 61 74 65 54 69 6d 65 22 3a 22 32 30 32 |{"dateTime":"202|
93+
|00000010| 31 2d 30 33 2d 31 32 54 31 33 3a 32 30 3a 35 37 |1-03-12T13:20:57|
94+
|00000020| 2e 36 35 33 35 37 32 2b 30 31 3a 30 30 22 2c 22 |.653572+01:00","|
95+
|00000030| 65 6e 74 72 79 22 3a 37 37 35 2c 22 6e 75 6d 62 |entry":775,"numb|
96+
|00000040| 65 72 22 3a 33 2c 22 6e 61 6d 65 22 3a 22 47 69 |er":3,"name":"Gi|
97+
|00000050| 6e 67 65 72 20 53 6e 61 70 70 22 2c 22 61 64 64 |nger Snapp","add|
98+
|00000060| 72 65 73 73 22 3a 22 39 30 38 33 38 20 59 6f 6c |ress":"90838 Yol|
99+
|00000070| 61 6e 64 61 20 53 74 61 74 69 6f 6e 2c 20 4c 61 |anda Station, La|
100+
|00000080| 6b 65 20 4d 61 75 72 69 63 65 2c 20 4d 41 20 30 |ke Maurice, MA 0|
101+
|00000090| 36 37 31 32 2d 30 36 33 38 22 2c 22 6b 69 6e 64 |6712-0638","kind|
102+
|000000a0| 22 3a 22 4c 4f 54 52 22 2c 22 69 74 65 6d 22 3a |":"LOTR","item":|
103+
|000000b0| 22 53 68 61 64 6f 77 66 61 78 22 7d |"Shadowfax"} |
104+
+--------+-------------------------------------------------+----------------+
105+
{"dateTime":"2021-03-12T13:20:57.653572+01:00","entry":775,"number":3,"name":"Ginger Snapp",
106+
"address":"90838 Yolanda Station, Lake Maurice, MA 06712-0638","kind":"LOTR","item":"Shadowfax"}
107+
2021-03-12 13:21:02.658 DEBUG 81691 --- [actor-tcp-nio-2] io.rsocket.FrameLogger : receiving ->
108+
Frame => Stream ID: 1 Type: NEXT Flags: 0b100000 Length: 204
109+
Data:
110+
+-------------------------------------------------+
111+
| 0 1 2 3 4 5 6 7 8 9 a b c d e f |
112+
+--------+-------------------------------------------------+----------------+
113+
|00000000| 7b 22 64 61 74 65 54 69 6d 65 22 3a 22 32 30 32 |{"dateTime":"202|
114+
|00000010| 31 2d 30 33 2d 31 32 54 31 33 3a 32 31 3a 30 32 |1-03-12T13:21:02|
115+
|00000020| 2e 36 35 37 36 35 33 2b 30 31 3a 30 30 22 2c 22 |.657653+01:00","|
116+
|00000030| 65 6e 74 72 79 22 3a 37 37 36 2c 22 6e 75 6d 62 |entry":776,"numb|
117+
|00000040| 65 72 22 3a 38 2c 22 6e 61 6d 65 22 3a 22 52 79 |er":8,"name":"Ry|
118+
|00000050| 61 6e 20 43 61 72 6e 61 74 69 6f 6e 22 2c 22 61 |an Carnation","a|
119+
|00000060| 64 64 72 65 73 73 22 3a 22 53 75 69 74 65 20 38 |ddress":"Suite 8|
120+
|00000070| 37 33 20 32 32 38 37 20 45 66 66 65 72 74 7a 20 |73 2287 Effertz |
121+
|00000080| 53 70 75 72 2c 20 49 67 6e 61 63 69 61 76 69 65 |Spur, Ignaciavie|
122+
|00000090| 77 2c 20 4e 48 20 31 38 36 35 39 2d 39 31 32 30 |w, NH 18659-9120|
123+
|000000a0| 22 2c 22 6b 69 6e 64 22 3a 22 4c 4f 54 52 22 2c |","kind":"LOTR",|
124+
|000000b0| 22 69 74 65 6d 22 3a 22 54 6f 6d 20 42 6f 6d 62 |"item":"Tom Bomb|
125+
|000000c0| 61 64 69 6c 22 7d |adil"} |
126+
+--------+-------------------------------------------------+----------------+
127+
{"dateTime":"2021-03-12T13:21:02.657653+01:00","entry":776,"number":8,"name":"Ryan Carnation",
128+
"address":"Suite 873 2287 Effertz Spur, Ignaciaview, NH 18659-9120","kind":"LOTR","item":"Tom Bombadil"}
129+
2021-03-12 13:21:07.663 DEBUG 81691 --- [actor-tcp-nio-2] io.rsocket.FrameLogger : receiving ->
130+
Frame => Stream ID: 1 Type: NEXT Flags: 0b100000 Length: 202
131+
Data:
132+
+-------------------------------------------------+
133+
| 0 1 2 3 4 5 6 7 8 9 a b c d e f |
134+
+--------+-------------------------------------------------+----------------+
135+
|00000000| 7b 22 64 61 74 65 54 69 6d 65 22 3a 22 32 30 32 |{"dateTime":"202|
136+
|00000010| 31 2d 30 33 2d 31 32 54 31 33 3a 32 31 3a 30 37 |1-03-12T13:21:07|
137+
|00000020| 2e 36 36 32 38 33 31 2b 30 31 3a 30 30 22 2c 22 |.662831+01:00","|
138+
|00000030| 65 6e 74 72 79 22 3a 37 37 37 2c 22 6e 75 6d 62 |entry":777,"numb|
139+
|00000040| 65 72 22 3a 34 2c 22 6e 61 6d 65 22 3a 22 48 65 |er":4,"name":"He|
140+
|00000050| 61 74 68 65 72 20 4e 2e 20 59 6f 6e 6e 22 2c 22 |ather N. Yonn","|
141+
|00000060| 61 64 64 72 65 73 73 22 3a 22 33 33 34 20 5a 61 |address":"334 Za|
142+
|00000070| 63 68 61 72 79 20 4d 6f 75 6e 74 61 69 6e 2c 20 |chary Mountain, |
143+
|00000080| 43 72 75 69 63 6b 73 68 61 6e 6b 6c 61 6e 64 2c |Cruickshankland,|
144+
|00000090| 20 41 5a 20 34 33 32 32 37 22 2c 22 6b 69 6e 64 | AZ 43227","kind|
145+
|000000a0| 22 3a 22 4c 4f 54 52 22 2c 22 69 74 65 6d 22 3a |":"LOTR","item":|
146+
|000000b0| 22 47 72 c3 ac 6d 61 20 57 6f 72 6d 74 6f 6e 67 |"Gr..ma Wormtong|
147+
|000000c0| 75 65 22 7d |ue"} |
148+
+--------+-------------------------------------------------+----------------+
149+
{"dateTime":"2021-03-12T13:21:07.662831+01:00","entry":777,"number":4,"name":"Heather N. Yonn",
150+
"address":"334 Zachary Mountain, Cruickshankland, AZ 43227","kind":"LOTR","item":"Grìma Wormtongue"}
151+
...
152+
153+
```
154+
155+
**Note:** The whole frames sent are visible, also check out the server logs.
156+
157+
#### HTTP
158+
159+
To retrieve the stream using *HTTP* I used [HTTPIE](https://httpie.io/) using:
160+
161+
````shell
162+
http :8070/server/orders --stream
163+
````
164+
165+
This will produce output like:
166+
167+
```json
168+
{
169+
"address": "456 Herman Turnpike, Sporerchester, VT 49469-0588",
170+
"dateTime": "2021-03-12T13:23:07.754996+01:00",
171+
"entry": 801,
172+
"item": "Bethany Bracken",
173+
"kind": "GOT",
174+
"name": "Val Lay",
175+
"number": 6
176+
}
177+
178+
{
179+
"address": "73538 Morar Well, West Cristobal, OH 28237",
180+
"dateTime": "2021-03-12T13:23:12.760175+01:00",
181+
"entry": 802,
182+
"item": "Kyle Condon",
183+
"kind": "GOT",
184+
"name": "Eli Ondefloor",
185+
"number": 0
186+
}
187+
188+
{
189+
"address": "Suite 931 381 Bernita Lane, Lake Benjamin, TX 93575",
190+
"dateTime": "2021-03-12T13:23:17.765894+01:00",
191+
"entry": 803,
192+
"item": "Samwise Gamgee",
193+
"kind": "LOTR",
194+
"name": "Robin DeCraydle",
195+
"number": 6
196+
}
197+
198+
{
199+
"address": "922 Julene Hollow, Bookermouth, WA 68785-6036",
200+
"dateTime": "2021-03-12T13:23:22.769958+01:00",
201+
"entry": 804,
202+
"item": "Arwen Evenstar",
203+
"kind": "LOTR",
204+
"name": "Ryan Coke",
205+
"number": 5
206+
}
207+
208+
{
209+
"address": "Suite 063 41363 Omer Square, Machellemouth, NE 92997",
210+
"dateTime": "2021-03-12T13:23:27.771213+01:00",
211+
"entry": 805,
212+
"item": "Qezza",
213+
"kind": "GOT",
214+
"name": "Terry Achey",
215+
"number": 3
216+
}
217+
218+
...
219+
220+
```
221+
222+
Use *HTTPie* to create order:
223+
224+
```shell
225+
# Random
226+
http :8070/server/orders/new
227+
# Specific
228+
http :8070/server/orders/new kind==lotr
229+
http :8070/server/orders/new kind==got
230+
```
231+
232+
## Next up
233+
234+
- [X] Payload integration
235+
- [X] Custom metadata
236+
- [X] Route with variable
237+
- [ ] SpringSecurity
238+
- [ ] Multiple routes

frontend/.editorconfig

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
root = true
2+
3+
[*]
4+
charset = utf-8
5+
indent_style = space
6+
indent_size = 2
7+
end_of_line = lf
8+
insert_final_newline = true
9+
trim_trailing_whitespace = true

frontend/.eslintignore

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
/dist
2+
/src-bex/www
3+
/src-capacitor
4+
/src-cordova
5+
/.quasar
6+
/node_modules

frontend/.eslintrc.js

Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,64 @@
1+
module.exports = {
2+
// https://eslint.org/docs/user-guide/configuring#configuration-cascading-and-hierarchy
3+
// This option interrupts the configuration hierarchy at this file
4+
// Remove this if you have an higher level ESLint config file (it usually happens into a monorepos)
5+
root: true,
6+
7+
parserOptions: {
8+
parser: 'babel-eslint',
9+
ecmaVersion: 2018, // Allows for the parsing of modern ECMAScript features
10+
sourceType: 'module' // Allows for the use of imports
11+
},
12+
13+
env: {
14+
browser: true
15+
},
16+
17+
// Rules order is important, please avoid shuffling them
18+
extends: [
19+
// Base ESLint recommended rules
20+
// 'eslint:recommended',
21+
22+
23+
// Uncomment any of the lines below to choose desired strictness,
24+
// but leave only one uncommented!
25+
// See https://eslint.vuejs.org/rules/#available-rules
26+
'plugin:vue/essential', // Priority A: Essential (Error Prevention)
27+
// 'plugin:vue/strongly-recommended', // Priority B: Strongly Recommended (Improving Readability)
28+
// 'plugin:vue/recommended', // Priority C: Recommended (Minimizing Arbitrary Choices and Cognitive Overhead)
29+
30+
// https://github.com/prettier/eslint-config-prettier#installation
31+
// usage with Prettier, provided by 'eslint-config-prettier'.
32+
'prettier',
33+
34+
'prettier/vue'
35+
],
36+
37+
plugins: [
38+
// https://eslint.vuejs.org/user-guide/#why-doesn-t-it-work-on-vue-file
39+
// required to lint *.vue files
40+
'vue',
41+
42+
// https://github.com/typescript-eslint/typescript-eslint/issues/389#issuecomment-509292674
43+
// Prettier has not been included as plugin to avoid performance impact
44+
// add it as an extension for your IDE
45+
],
46+
47+
globals: {
48+
ga: true, // Google Analytics
49+
cordova: true,
50+
__statics: true,
51+
process: true,
52+
Capacitor: true,
53+
chrome: true
54+
},
55+
56+
// add your custom rules here
57+
rules: {
58+
'prefer-promise-reject-errors': 'off',
59+
60+
61+
// allow debugger during development only
62+
'no-debugger': process.env.NODE_ENV === 'production' ? 'error' : 'off'
63+
}
64+
}

frontend/.gitignore

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
.DS_Store
2+
.thumbs.db
3+
node_modules
4+
.vscode
5+
6+
# Quasar core related directories
7+
.quasar
8+
/dist
9+
10+
# Cordova related directories and files
11+
/src-cordova/node_modules
12+
/src-cordova/platforms
13+
/src-cordova/plugins
14+
/src-cordova/www
15+
16+
# Capacitor related directories and files
17+
/src-capacitor/www
18+
/src-capacitor/node_modules
19+
20+
# BEX related directories and files
21+
/src-bex/www
22+
/src-bex/js/core
23+
24+
# Log files
25+
npm-debug.log*
26+
yarn-debug.log*
27+
yarn-error.log*
28+
29+
# Editor directories and files
30+
../../.idea
31+
*.suo
32+
*.ntvs*
33+
*.njsproj
34+
*.sln

frontend/.postcssrc.js

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
// https://github.com/michael-ciniawsky/postcss-load-config
2+
3+
module.exports = {
4+
plugins: [
5+
// to edit target browsers: use "browserslist" field in package.json
6+
require('autoprefixer')
7+
]
8+
}

0 commit comments

Comments
 (0)