├── 1.0
└── demo
│ ├── .mvn
│ └── wrapper
│ │ ├── MavenWrapperDownloader.java
│ │ ├── maven-wrapper.jar
│ │ └── maven-wrapper.properties
│ ├── mvnw
│ ├── mvnw.cmd
│ ├── pom.xml
│ └── src
│ ├── main
│ ├── java
│ │ └── com
│ │ │ └── example
│ │ │ └── demo
│ │ │ └── DemoApplication.java
│ └── resources
│ │ └── application.properties
│ └── test
│ └── java
│ └── com
│ └── example
│ └── demo
│ └── DemoApplicationTests.java
├── 2.0
└── data
│ ├── .mvn
│ └── wrapper
│ │ ├── MavenWrapperDownloader.java
│ │ ├── maven-wrapper.jar
│ │ └── maven-wrapper.properties
│ ├── mvnw
│ ├── mvnw.cmd
│ ├── pom.xml
│ └── src
│ ├── main
│ ├── java
│ │ └── com
│ │ │ └── example
│ │ │ └── data
│ │ │ └── DataApplication.java
│ └── resources
│ │ └── application.properties
│ └── test
│ └── java
│ └── com
│ └── example
│ └── data
│ └── DataApplicationTests.java
├── 3.0
├── .mvn
│ └── wrapper
│ │ ├── MavenWrapperDownloader.java
│ │ ├── maven-wrapper.jar
│ │ └── maven-wrapper.properties
├── mvnw
├── mvnw.cmd
├── pom.xml
└── src
│ ├── main
│ ├── java
│ │ └── com
│ │ │ └── example
│ │ │ └── http
│ │ │ └── HttpApplication.java
│ └── resources
│ │ └── application.properties
│ └── test
│ └── java
│ └── com
│ └── example
│ └── http
│ └── HttpApplicationTests.java
├── 4.0
├── .mvn
│ └── wrapper
│ │ ├── MavenWrapperDownloader.java
│ │ ├── maven-wrapper.jar
│ │ └── maven-wrapper.properties
├── mvnw
├── mvnw.cmd
├── pom.xml
└── src
│ ├── main
│ ├── java
│ │ └── com
│ │ │ └── example
│ │ │ └── websockets
│ │ │ └── WebsocketsApplication.java
│ └── resources
│ │ ├── application.properties
│ │ └── static
│ │ └── ws.html
│ └── test
│ └── java
│ └── com
│ └── example
│ └── websockets
│ └── WebsocketsApplicationTests.java
├── 5.0
├── greeting-client
│ ├── .mvn
│ │ └── wrapper
│ │ │ ├── MavenWrapperDownloader.java
│ │ │ ├── maven-wrapper.jar
│ │ │ └── maven-wrapper.properties
│ ├── mvnw
│ ├── mvnw.cmd
│ ├── pom.xml
│ └── src
│ │ ├── main
│ │ ├── java
│ │ │ └── com
│ │ │ │ └── example
│ │ │ │ └── greetingclient
│ │ │ │ └── GreetingClientApplication.java
│ │ └── resources
│ │ │ └── application.properties
│ │ └── test
│ │ └── java
│ │ └── com
│ │ └── example
│ │ └── greetingclient
│ │ └── GreetingClientApplicationTests.java
└── greeting-service
│ ├── .mvn
│ └── wrapper
│ │ ├── MavenWrapperDownloader.java
│ │ ├── maven-wrapper.jar
│ │ └── maven-wrapper.properties
│ ├── mvnw
│ ├── mvnw.cmd
│ ├── pom.xml
│ └── src
│ ├── main
│ ├── java
│ │ └── com
│ │ │ └── example
│ │ │ └── greetingservice
│ │ │ └── GreetingServiceApplication.java
│ └── resources
│ │ └── application.properties
│ └── test
│ └── java
│ └── com
│ └── example
│ └── greetingservice
│ └── GreetingServiceApplicationTests.java
├── 6.0
├── raw-rsocket-client
│ ├── .mvn
│ │ └── wrapper
│ │ │ ├── MavenWrapperDownloader.java
│ │ │ ├── maven-wrapper.jar
│ │ │ └── maven-wrapper.properties
│ ├── HELP.md
│ ├── mvnw
│ ├── mvnw.cmd
│ ├── pom.xml
│ └── src
│ │ ├── main
│ │ ├── java
│ │ │ └── com
│ │ │ │ └── example
│ │ │ │ └── rawrsocketclient
│ │ │ │ └── RawRsocketClientApplication.java
│ │ └── resources
│ │ │ └── application.properties
│ │ └── test
│ │ └── java
│ │ └── com
│ │ └── example
│ │ └── rawrsocketclient
│ │ └── RawRsocketClientApplicationTests.java
├── raw-rsocket-service
│ ├── .mvn
│ │ └── wrapper
│ │ │ ├── MavenWrapperDownloader.java
│ │ │ ├── maven-wrapper.jar
│ │ │ └── maven-wrapper.properties
│ ├── HELP.md
│ ├── mvnw
│ ├── mvnw.cmd
│ ├── pom.xml
│ └── src
│ │ ├── main
│ │ ├── java
│ │ │ └── com
│ │ │ │ └── example
│ │ │ │ └── rawrsocketservice
│ │ │ │ └── RawRsocketServiceApplication.java
│ │ └── resources
│ │ │ └── application.properties
│ │ └── test
│ │ └── java
│ │ └── com
│ │ └── example
│ │ └── rawrsocketservice
│ │ └── RawRsocketServiceApplicationTests.java
├── rsocket-client
│ ├── .mvn
│ │ └── wrapper
│ │ │ ├── MavenWrapperDownloader.java
│ │ │ ├── maven-wrapper.jar
│ │ │ └── maven-wrapper.properties
│ ├── HELP.md
│ ├── mvnw
│ ├── mvnw.cmd
│ ├── pom.xml
│ └── src
│ │ ├── main
│ │ ├── java
│ │ │ └── com
│ │ │ │ └── example
│ │ │ │ └── rsocketclient
│ │ │ │ └── RsocketClientApplication.java
│ │ └── resources
│ │ │ └── application.properties
│ │ └── test
│ │ └── java
│ │ └── com
│ │ └── example
│ │ └── rsocketclient
│ │ └── RsocketClientApplicationTests.java
└── rsocket-service
│ ├── .mvn
│ └── wrapper
│ │ ├── MavenWrapperDownloader.java
│ │ ├── maven-wrapper.jar
│ │ └── maven-wrapper.properties
│ ├── HELP.md
│ ├── mvnw
│ ├── mvnw.cmd
│ ├── pom.xml
│ └── src
│ ├── main
│ ├── java
│ │ └── com
│ │ │ └── example
│ │ │ └── rsocketservice
│ │ │ └── RsocketServiceApplication.java
│ └── resources
│ │ └── application.properties
│ └── test
│ └── java
│ └── com
│ └── example
│ └── rsocketservice
│ └── RsocketServiceApplicationTests.java
├── 7.0
├── secure-http-client
│ ├── .mvn
│ │ └── wrapper
│ │ │ ├── MavenWrapperDownloader.java
│ │ │ ├── maven-wrapper.jar
│ │ │ └── maven-wrapper.properties
│ ├── mvnw
│ ├── mvnw.cmd
│ ├── pom.xml
│ └── src
│ │ ├── main
│ │ ├── java
│ │ │ └── com
│ │ │ │ └── example
│ │ │ │ └── http
│ │ │ │ └── HttpApplication.java
│ │ └── resources
│ │ │ └── application.properties
│ │ └── test
│ │ └── java
│ │ └── com
│ │ └── example
│ │ └── http
│ │ └── HttpApplicationTests.java
├── secure-http-service
│ ├── .mvn
│ │ └── wrapper
│ │ │ ├── MavenWrapperDownloader.java
│ │ │ ├── maven-wrapper.jar
│ │ │ └── maven-wrapper.properties
│ ├── mvnw
│ ├── mvnw.cmd
│ ├── pom.xml
│ └── src
│ │ ├── main
│ │ ├── java
│ │ │ └── com
│ │ │ │ └── example
│ │ │ │ └── http
│ │ │ │ └── HttpApplication.java
│ │ └── resources
│ │ │ └── application.properties
│ │ └── test
│ │ └── java
│ │ └── com
│ │ └── example
│ │ └── http
│ │ └── HttpApplicationTests.java
├── secure-rsocket-client
│ ├── .mvn
│ │ └── wrapper
│ │ │ ├── MavenWrapperDownloader.java
│ │ │ ├── maven-wrapper.jar
│ │ │ └── maven-wrapper.properties
│ ├── HELP.md
│ ├── mvnw
│ ├── mvnw.cmd
│ ├── pom.xml
│ └── src
│ │ ├── main
│ │ ├── java
│ │ │ └── com
│ │ │ │ └── example
│ │ │ │ └── rsocketclient
│ │ │ │ └── RsocketClientApplication.java
│ │ └── resources
│ │ │ └── application.properties
│ │ └── test
│ │ └── java
│ │ └── com
│ │ └── example
│ │ └── rsocketclient
│ │ └── RsocketClientApplicationTests.java
└── secure-rsocket-service
│ ├── .mvn
│ └── wrapper
│ │ ├── MavenWrapperDownloader.java
│ │ ├── maven-wrapper.jar
│ │ └── maven-wrapper.properties
│ ├── HELP.md
│ ├── mvnw
│ ├── mvnw.cmd
│ ├── pom.xml
│ └── src
│ ├── main
│ ├── java
│ │ └── com
│ │ │ └── example
│ │ │ └── rsocketservice
│ │ │ └── RsocketServiceApplication.java
│ └── resources
│ │ └── application.properties
│ └── test
│ └── java
│ └── com
│ └── example
│ └── rsocketservice
│ └── RsocketServiceApplicationTests.java
├── 8.0
├── http
│ ├── http-gateway
│ │ ├── .mvn
│ │ │ └── wrapper
│ │ │ │ ├── MavenWrapperDownloader.java
│ │ │ │ ├── maven-wrapper.jar
│ │ │ │ └── maven-wrapper.properties
│ │ ├── HELP.md
│ │ ├── mvnw
│ │ ├── mvnw.cmd
│ │ ├── pom.xml
│ │ └── src
│ │ │ ├── main
│ │ │ ├── java
│ │ │ │ └── com
│ │ │ │ │ └── example
│ │ │ │ │ └── httpgateway
│ │ │ │ │ └── HttpGatewayApplication.java
│ │ │ └── resources
│ │ │ │ └── application.properties
│ │ │ └── test
│ │ │ └── java
│ │ │ └── com
│ │ │ └── example
│ │ │ └── httpgateway
│ │ │ └── HttpGatewayApplicationTests.java
│ └── reservation-service
│ │ ├── .mvn
│ │ └── wrapper
│ │ │ ├── MavenWrapperDownloader.java
│ │ │ ├── maven-wrapper.jar
│ │ │ └── maven-wrapper.properties
│ │ ├── HELP.md
│ │ ├── mvnw
│ │ ├── mvnw.cmd
│ │ ├── pom.xml
│ │ └── src
│ │ ├── main
│ │ ├── java
│ │ │ └── com
│ │ │ │ └── example
│ │ │ │ └── reservationservice
│ │ │ │ └── ReservationServiceApplication.java
│ │ └── resources
│ │ │ └── application.properties
│ │ └── test
│ │ └── java
│ │ └── com
│ │ └── example
│ │ └── reservationservice
│ │ └── ReservationServiceApplicationTests.java
├── rsocket-gateway-deps.md
└── rsocket
│ ├── greetings-client
│ ├── .mvn
│ │ └── wrapper
│ │ │ ├── MavenWrapperDownloader.java
│ │ │ ├── maven-wrapper.jar
│ │ │ └── maven-wrapper.properties
│ ├── HELP.md
│ ├── mvnw
│ ├── mvnw.cmd
│ ├── pom.xml
│ └── src
│ │ ├── main
│ │ ├── java
│ │ │ └── com
│ │ │ │ └── example
│ │ │ │ └── greetingsclient
│ │ │ │ └── GreetingsClientApplication.java
│ │ └── resources
│ │ │ └── application.properties
│ │ └── test
│ │ └── java
│ │ └── com
│ │ └── example
│ │ └── greetingsservice
│ │ └── GreetingsServiceApplicationTests.java
│ ├── greetings-service
│ ├── .mvn
│ │ └── wrapper
│ │ │ ├── MavenWrapperDownloader.java
│ │ │ ├── maven-wrapper.jar
│ │ │ └── maven-wrapper.properties
│ ├── HELP.md
│ ├── mvnw
│ ├── mvnw.cmd
│ ├── pom.xml
│ └── src
│ │ ├── main
│ │ ├── java
│ │ │ └── com
│ │ │ │ └── example
│ │ │ │ └── greetingsservice
│ │ │ │ └── GreetingsServiceApplication.java
│ │ └── resources
│ │ │ └── application.properties
│ │ └── test
│ │ └── java
│ │ └── com
│ │ └── example
│ │ └── greetingsservice
│ │ └── GreetingsServiceApplicationTests.java
│ └── rsocket-gateway
│ ├── .mvn
│ └── wrapper
│ │ ├── MavenWrapperDownloader.java
│ │ ├── maven-wrapper.jar
│ │ └── maven-wrapper.properties
│ ├── HELP.md
│ ├── mvnw
│ ├── mvnw.cmd
│ ├── pom.xml
│ └── src
│ ├── main
│ ├── java
│ │ └── com
│ │ │ └── example
│ │ │ └── rsocketgateway
│ │ │ └── RsocketGatewayApplication.java
│ └── resources
│ │ └── application.properties
│ └── test
│ └── java
│ └── com
│ └── example
│ └── rsocketgateway
│ └── RsocketGatewayApplicationTests.java
├── 9.0
├── consumer
│ ├── .gitignore
│ ├── .mvn
│ │ └── wrapper
│ │ │ ├── MavenWrapperDownloader.java
│ │ │ ├── maven-wrapper.jar
│ │ │ └── maven-wrapper.properties
│ ├── mvnw
│ ├── mvnw.cmd
│ ├── pom.xml
│ └── src
│ │ ├── main
│ │ ├── java
│ │ │ └── com
│ │ │ │ └── example
│ │ │ │ └── consumer
│ │ │ │ ├── ConsumerApplication.java
│ │ │ │ ├── Reservation.java
│ │ │ │ └── ReservationClient.java
│ │ └── resources
│ │ │ └── application.properties
│ │ └── test
│ │ └── java
│ │ └── com
│ │ └── example
│ │ └── consumer
│ │ └── ConsumerApplicationTests.java
└── producer
│ ├── .gitignore
│ ├── .mvn
│ └── wrapper
│ │ ├── MavenWrapperDownloader.java
│ │ ├── maven-wrapper.jar
│ │ └── maven-wrapper.properties
│ ├── mvnw
│ ├── mvnw.cmd
│ ├── pom.xml
│ └── src
│ ├── main
│ ├── java
│ │ └── com
│ │ │ └── example
│ │ │ └── producer
│ │ │ ├── ProducerApplication.java
│ │ │ ├── Reservation.java
│ │ │ ├── ReservationHttpConfiguration.java
│ │ │ └── ReservationRepository.java
│ └── resources
│ │ └── application.properties
│ └── test
│ ├── java
│ └── com
│ │ └── example
│ │ └── producer
│ │ ├── BaseClass.java
│ │ ├── ReservationEntityTest.java
│ │ ├── ReservationHttpTest.java
│ │ ├── ReservationPojoTest.java
│ │ └── ReservationRepositoryTest.java
│ └── resources
│ └── contracts
│ └── shouldReturnAllReservations.groovy
└── reactive-spring.md
/1.0/demo/.mvn/wrapper/MavenWrapperDownloader.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2012-2019 the original author or authors.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * https://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 | import java.net.*;
17 | import java.io.*;
18 | import java.nio.channels.*;
19 | import java.util.Properties;
20 |
21 | public class MavenWrapperDownloader {
22 |
23 | private static final String WRAPPER_VERSION = "0.5.5";
24 | /**
25 | * Default URL to download the maven-wrapper.jar from, if no 'downloadUrl' is provided.
26 | */
27 | private static final String DEFAULT_DOWNLOAD_URL = "https://repo.maven.apache.org/maven2/io/takari/maven-wrapper/"
28 | + WRAPPER_VERSION + "/maven-wrapper-" + WRAPPER_VERSION + ".jar";
29 |
30 | /**
31 | * Path to the maven-wrapper.properties file, which might contain a downloadUrl property to
32 | * use instead of the default one.
33 | */
34 | private static final String MAVEN_WRAPPER_PROPERTIES_PATH =
35 | ".mvn/wrapper/maven-wrapper.properties";
36 |
37 | /**
38 | * Path where the maven-wrapper.jar will be saved to.
39 | */
40 | private static final String MAVEN_WRAPPER_JAR_PATH =
41 | ".mvn/wrapper/maven-wrapper.jar";
42 |
43 | /**
44 | * Name of the property which should be used to override the default download url for the wrapper.
45 | */
46 | private static final String PROPERTY_NAME_WRAPPER_URL = "wrapperUrl";
47 |
48 | public static void main(String args[]) {
49 | System.out.println("- Downloader started");
50 | File baseDirectory = new File(args[0]);
51 | System.out.println("- Using base directory: " + baseDirectory.getAbsolutePath());
52 |
53 | // If the maven-wrapper.properties exists, read it and check if it contains a custom
54 | // wrapperUrl parameter.
55 | File mavenWrapperPropertyFile = new File(baseDirectory, MAVEN_WRAPPER_PROPERTIES_PATH);
56 | String url = DEFAULT_DOWNLOAD_URL;
57 | if(mavenWrapperPropertyFile.exists()) {
58 | FileInputStream mavenWrapperPropertyFileInputStream = null;
59 | try {
60 | mavenWrapperPropertyFileInputStream = new FileInputStream(mavenWrapperPropertyFile);
61 | Properties mavenWrapperProperties = new Properties();
62 | mavenWrapperProperties.load(mavenWrapperPropertyFileInputStream);
63 | url = mavenWrapperProperties.getProperty(PROPERTY_NAME_WRAPPER_URL, url);
64 | } catch (IOException e) {
65 | System.out.println("- ERROR loading '" + MAVEN_WRAPPER_PROPERTIES_PATH + "'");
66 | } finally {
67 | try {
68 | if(mavenWrapperPropertyFileInputStream != null) {
69 | mavenWrapperPropertyFileInputStream.close();
70 | }
71 | } catch (IOException e) {
72 | // Ignore ...
73 | }
74 | }
75 | }
76 | System.out.println("- Downloading from: " + url);
77 |
78 | File outputFile = new File(baseDirectory.getAbsolutePath(), MAVEN_WRAPPER_JAR_PATH);
79 | if(!outputFile.getParentFile().exists()) {
80 | if(!outputFile.getParentFile().mkdirs()) {
81 | System.out.println(
82 | "- ERROR creating output directory '" + outputFile.getParentFile().getAbsolutePath() + "'");
83 | }
84 | }
85 | System.out.println("- Downloading to: " + outputFile.getAbsolutePath());
86 | try {
87 | downloadFileFromURL(url, outputFile);
88 | System.out.println("Done");
89 | System.exit(0);
90 | } catch (Throwable e) {
91 | System.out.println("- Error downloading");
92 | e.printStackTrace();
93 | System.exit(1);
94 | }
95 | }
96 |
97 | private static void downloadFileFromURL(String urlString, File destination) throws Exception {
98 | if (System.getenv("MVNW_USERNAME") != null && System.getenv("MVNW_PASSWORD") != null) {
99 | String username = System.getenv("MVNW_USERNAME");
100 | char[] password = System.getenv("MVNW_PASSWORD").toCharArray();
101 | Authenticator.setDefault(new Authenticator() {
102 | @Override
103 | protected PasswordAuthentication getPasswordAuthentication() {
104 | return new PasswordAuthentication(username, password);
105 | }
106 | });
107 | }
108 | URL website = new URL(urlString);
109 | ReadableByteChannel rbc;
110 | rbc = Channels.newChannel(website.openStream());
111 | FileOutputStream fos = new FileOutputStream(destination);
112 | fos.getChannel().transferFrom(rbc, 0, Long.MAX_VALUE);
113 | fos.close();
114 | rbc.close();
115 | }
116 |
117 | }
118 |
--------------------------------------------------------------------------------
/1.0/demo/.mvn/wrapper/maven-wrapper.jar:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/joshlong/reactive-spring-livelessons-2e/f10c568102d0634a050639973ba99f632580392f/1.0/demo/.mvn/wrapper/maven-wrapper.jar
--------------------------------------------------------------------------------
/1.0/demo/.mvn/wrapper/maven-wrapper.properties:
--------------------------------------------------------------------------------
1 | distributionUrl=https://repo.maven.apache.org/maven2/org/apache/maven/apache-maven/3.6.2/apache-maven-3.6.2-bin.zip
2 | wrapperUrl=https://repo.maven.apache.org/maven2/io/takari/maven-wrapper/0.5.5/maven-wrapper-0.5.5.jar
3 |
--------------------------------------------------------------------------------
/1.0/demo/pom.xml:
--------------------------------------------------------------------------------
1 |
2 |
4 | 4.0.0
5 |
6 | org.springframework.boot
7 | spring-boot-starter-parent
8 | 2.2.2.RELEASE
9 |
10 |
11 | com.example
12 | demo
13 | 0.0.1-SNAPSHOT
14 | demo
15 | Demo project for Spring Boot
16 |
17 |
18 | 13
19 | Hoxton.RELEASE
20 |
21 |
22 |
23 |
24 | org.springframework.boot.experimental
25 | spring-boot-actuator-autoconfigure-r2dbc
26 |
27 |
28 | org.springframework.boot
29 | spring-boot-starter-actuator
30 |
31 |
32 | org.springframework.boot
33 | spring-boot-starter-data-mongodb-reactive
34 |
35 |
36 | org.springframework.boot.experimental
37 | spring-boot-starter-data-r2dbc
38 |
39 |
40 | org.springframework.boot
41 | spring-boot-starter-rsocket
42 |
43 |
44 | org.springframework.boot
45 | spring-boot-starter-webflux
46 |
47 |
48 | org.springframework.cloud
49 | spring-cloud-starter-gateway
50 |
51 |
52 |
53 | org.projectlombok
54 | lombok
55 | true
56 |
57 |
58 | org.springframework.boot
59 | spring-boot-starter-test
60 | test
61 |
62 |
63 | org.junit.vintage
64 | junit-vintage-engine
65 |
66 |
67 |
68 |
69 | org.springframework.boot.experimental
70 | spring-boot-test-autoconfigure-r2dbc
71 | test
72 |
73 |
74 | io.projectreactor
75 | reactor-test
76 | test
77 |
78 |
79 |
80 |
81 |
82 |
83 | org.springframework.cloud
84 | spring-cloud-dependencies
85 | ${spring-cloud.version}
86 | pom
87 | import
88 |
89 |
90 | org.springframework.boot.experimental
91 | spring-boot-bom-r2dbc
92 | 0.1.0.M3
93 | pom
94 | import
95 |
96 |
97 |
98 |
99 |
100 |
101 |
102 | org.springframework.boot
103 | spring-boot-maven-plugin
104 |
105 |
106 |
107 |
108 |
109 |
110 | spring-milestones
111 | Spring Milestones
112 | https://repo.spring.io/milestone
113 |
114 |
115 |
116 |
117 |
--------------------------------------------------------------------------------
/1.0/demo/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 |
6 | @SpringBootApplication
7 | public class DemoApplication {
8 |
9 | public static void main(String[] args) {
10 | SpringApplication.run(DemoApplication.class, args);
11 | }
12 |
13 | }
14 |
--------------------------------------------------------------------------------
/1.0/demo/src/main/resources/application.properties:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/1.0/demo/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 |
--------------------------------------------------------------------------------
/2.0/data/.mvn/wrapper/MavenWrapperDownloader.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2012-2019 the original author or authors.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * https://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 | import java.net.*;
17 | import java.io.*;
18 | import java.nio.channels.*;
19 | import java.util.Properties;
20 |
21 | public class MavenWrapperDownloader {
22 |
23 | private static final String WRAPPER_VERSION = "0.5.5";
24 | /**
25 | * Default URL to download the maven-wrapper.jar from, if no 'downloadUrl' is provided.
26 | */
27 | private static final String DEFAULT_DOWNLOAD_URL = "https://repo.maven.apache.org/maven2/io/takari/maven-wrapper/"
28 | + WRAPPER_VERSION + "/maven-wrapper-" + WRAPPER_VERSION + ".jar";
29 |
30 | /**
31 | * Path to the maven-wrapper.properties file, which might contain a downloadUrl property to
32 | * use instead of the default one.
33 | */
34 | private static final String MAVEN_WRAPPER_PROPERTIES_PATH =
35 | ".mvn/wrapper/maven-wrapper.properties";
36 |
37 | /**
38 | * Path where the maven-wrapper.jar will be saved to.
39 | */
40 | private static final String MAVEN_WRAPPER_JAR_PATH =
41 | ".mvn/wrapper/maven-wrapper.jar";
42 |
43 | /**
44 | * Name of the property which should be used to override the default download url for the wrapper.
45 | */
46 | private static final String PROPERTY_NAME_WRAPPER_URL = "wrapperUrl";
47 |
48 | public static void main(String args[]) {
49 | System.out.println("- Downloader started");
50 | File baseDirectory = new File(args[0]);
51 | System.out.println("- Using base directory: " + baseDirectory.getAbsolutePath());
52 |
53 | // If the maven-wrapper.properties exists, read it and check if it contains a custom
54 | // wrapperUrl parameter.
55 | File mavenWrapperPropertyFile = new File(baseDirectory, MAVEN_WRAPPER_PROPERTIES_PATH);
56 | String url = DEFAULT_DOWNLOAD_URL;
57 | if(mavenWrapperPropertyFile.exists()) {
58 | FileInputStream mavenWrapperPropertyFileInputStream = null;
59 | try {
60 | mavenWrapperPropertyFileInputStream = new FileInputStream(mavenWrapperPropertyFile);
61 | Properties mavenWrapperProperties = new Properties();
62 | mavenWrapperProperties.load(mavenWrapperPropertyFileInputStream);
63 | url = mavenWrapperProperties.getProperty(PROPERTY_NAME_WRAPPER_URL, url);
64 | } catch (IOException e) {
65 | System.out.println("- ERROR loading '" + MAVEN_WRAPPER_PROPERTIES_PATH + "'");
66 | } finally {
67 | try {
68 | if(mavenWrapperPropertyFileInputStream != null) {
69 | mavenWrapperPropertyFileInputStream.close();
70 | }
71 | } catch (IOException e) {
72 | // Ignore ...
73 | }
74 | }
75 | }
76 | System.out.println("- Downloading from: " + url);
77 |
78 | File outputFile = new File(baseDirectory.getAbsolutePath(), MAVEN_WRAPPER_JAR_PATH);
79 | if(!outputFile.getParentFile().exists()) {
80 | if(!outputFile.getParentFile().mkdirs()) {
81 | System.out.println(
82 | "- ERROR creating output directory '" + outputFile.getParentFile().getAbsolutePath() + "'");
83 | }
84 | }
85 | System.out.println("- Downloading to: " + outputFile.getAbsolutePath());
86 | try {
87 | downloadFileFromURL(url, outputFile);
88 | System.out.println("Done");
89 | System.exit(0);
90 | } catch (Throwable e) {
91 | System.out.println("- Error downloading");
92 | e.printStackTrace();
93 | System.exit(1);
94 | }
95 | }
96 |
97 | private static void downloadFileFromURL(String urlString, File destination) throws Exception {
98 | if (System.getenv("MVNW_USERNAME") != null && System.getenv("MVNW_PASSWORD") != null) {
99 | String username = System.getenv("MVNW_USERNAME");
100 | char[] password = System.getenv("MVNW_PASSWORD").toCharArray();
101 | Authenticator.setDefault(new Authenticator() {
102 | @Override
103 | protected PasswordAuthentication getPasswordAuthentication() {
104 | return new PasswordAuthentication(username, password);
105 | }
106 | });
107 | }
108 | URL website = new URL(urlString);
109 | ReadableByteChannel rbc;
110 | rbc = Channels.newChannel(website.openStream());
111 | FileOutputStream fos = new FileOutputStream(destination);
112 | fos.getChannel().transferFrom(rbc, 0, Long.MAX_VALUE);
113 | fos.close();
114 | rbc.close();
115 | }
116 |
117 | }
118 |
--------------------------------------------------------------------------------
/2.0/data/.mvn/wrapper/maven-wrapper.jar:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/joshlong/reactive-spring-livelessons-2e/f10c568102d0634a050639973ba99f632580392f/2.0/data/.mvn/wrapper/maven-wrapper.jar
--------------------------------------------------------------------------------
/2.0/data/.mvn/wrapper/maven-wrapper.properties:
--------------------------------------------------------------------------------
1 | distributionUrl=https://repo.maven.apache.org/maven2/org/apache/maven/apache-maven/3.6.2/apache-maven-3.6.2-bin.zip
2 | wrapperUrl=https://repo.maven.apache.org/maven2/io/takari/maven-wrapper/0.5.5/maven-wrapper-0.5.5.jar
3 |
--------------------------------------------------------------------------------
/2.0/data/pom.xml:
--------------------------------------------------------------------------------
1 |
2 |
4 | 4.0.0
5 |
6 | org.springframework.boot
7 | spring-boot-starter-parent
8 | 2.2.2.RELEASE
9 |
10 |
11 | com.example
12 | data
13 | 0.0.1-SNAPSHOT
14 | data
15 | Demo project for Spring Boot
16 |
17 |
18 | 13
19 |
20 |
21 |
22 |
26 |
27 |
28 | io.r2dbc
29 | r2dbc-postgresql
30 | runtime
31 |
32 |
33 | org.springframework.boot.experimental
34 | spring-boot-starter-data-r2dbc
35 |
36 |
37 |
38 | org.springframework.boot
39 | spring-boot-starter-webflux
40 |
41 |
42 |
43 | org.projectlombok
44 | lombok
45 | true
46 |
47 |
48 | org.springframework.boot
49 | spring-boot-starter-test
50 | test
51 |
52 |
53 | org.junit.vintage
54 | junit-vintage-engine
55 |
56 |
57 |
58 |
59 | org.springframework.boot.experimental
60 | spring-boot-test-autoconfigure-r2dbc
61 | test
62 |
63 |
64 | io.projectreactor
65 | reactor-test
66 | test
67 |
68 |
69 |
70 |
71 |
72 |
73 | org.springframework.boot.experimental
74 | spring-boot-bom-r2dbc
75 | 0.1.0.M3
76 | pom
77 | import
78 |
79 |
80 |
81 |
82 |
83 |
84 |
85 | org.springframework.boot
86 | spring-boot-maven-plugin
87 |
88 |
89 |
90 |
91 |
92 |
93 | spring-milestones
94 | Spring Milestones
95 | https://repo.spring.io/milestone
96 |
97 |
98 |
99 |
100 |
--------------------------------------------------------------------------------
/2.0/data/src/main/java/com/example/data/DataApplication.java:
--------------------------------------------------------------------------------
1 | package com.example.data;
2 |
3 | import io.r2dbc.spi.ConnectionFactory;
4 | import lombok.AllArgsConstructor;
5 | import lombok.Data;
6 | import lombok.NoArgsConstructor;
7 | import lombok.RequiredArgsConstructor;
8 | import lombok.extern.log4j.Log4j2;
9 | import org.springframework.boot.SpringApplication;
10 | import org.springframework.boot.autoconfigure.SpringBootApplication;
11 | import org.springframework.boot.context.event.ApplicationReadyEvent;
12 | import org.springframework.context.annotation.Bean;
13 | import org.springframework.context.event.EventListener;
14 | import org.springframework.data.annotation.Id;
15 | import org.springframework.data.r2dbc.connectionfactory.R2dbcTransactionManager;
16 | import org.springframework.data.r2dbc.core.DatabaseClient;
17 | import org.springframework.data.r2dbc.repository.Query;
18 | import org.springframework.data.repository.reactive.ReactiveCrudRepository;
19 | import org.springframework.stereotype.Component;
20 | import org.springframework.stereotype.Service;
21 | import org.springframework.transaction.ReactiveTransactionManager;
22 | import org.springframework.transaction.annotation.EnableTransactionManagement;
23 | import org.springframework.transaction.annotation.Transactional;
24 | import org.springframework.transaction.reactive.TransactionalOperator;
25 | import org.springframework.util.Assert;
26 | import reactor.core.publisher.Flux;
27 | import reactor.util.context.Context;
28 |
29 | import java.util.UUID;
30 |
31 | @SpringBootApplication
32 | @EnableTransactionManagement
33 | public class DataApplication {
34 |
35 | @Bean
36 | TransactionalOperator transactionalOperator(ReactiveTransactionManager rtm) {
37 | return TransactionalOperator.create(rtm);
38 | }
39 |
40 | @Bean
41 | ReactiveTransactionManager r2dbcTransactionManager(ConnectionFactory cf) {
42 | return new R2dbcTransactionManager(cf);
43 | }
44 |
45 | public static void main(String[] args) {
46 | SpringApplication.run(DataApplication.class, args);
47 | }
48 |
49 | }
50 |
51 | @Service
52 | @Transactional
53 | @RequiredArgsConstructor
54 | class ReservationService {
55 |
56 | private final ReservationRepository reservationRepository;
57 | private final TransactionalOperator transactionalOperator;
58 |
59 | public Flux saveAll(String... names) {
60 | Flux reservations = Flux
61 | .fromArray(names)
62 | .map(name -> new Reservation(null, name))
63 | .flatMap(this.reservationRepository::save)
64 | .doOnNext(this::assertValid);
65 | return reservations;
66 | }
67 |
68 | private void assertValid(Reservation r) {
69 | Assert.isTrue(r.getName() != null && r.getName().length() > 0
70 | && Character.isUpperCase(r.getName().charAt(0)), "the name must start with a capital letter");
71 | }
72 | }
73 |
74 | @Component
75 | @RequiredArgsConstructor
76 | @Log4j2
77 | class SampleDataInitializer {
78 |
79 | private final ReservationRepository reservationRepository;
80 | private final ReservationService reservationService;
81 | private final DatabaseClient databaseClient;
82 |
83 | @EventListener(ApplicationReadyEvent.class)
84 | public void ready() {
85 |
86 | Flux reservations = reservationService
87 | .saveAll("Madhura", "josh", "Olga", "Marcin", "Ria", "Stéphane", "Violetta", "Dr. Syer");
88 |
89 | this.reservationRepository
90 | .deleteAll()
91 | .thenMany(reservations)
92 | .thenMany(this.reservationRepository.findAll())
93 | .subscribe(log::info);
94 | }
95 | }
96 |
97 | interface ReservationRepository extends ReactiveCrudRepository {
98 |
99 | // @Query("select * from reservation where name = $1 ")
100 | // Flux findByName(String name);
101 | }
102 |
103 |
104 | @Data
105 | @AllArgsConstructor
106 | @NoArgsConstructor
107 | class Reservation {
108 |
109 | @Id
110 | private Integer id;
111 | private String name;
112 | }
--------------------------------------------------------------------------------
/2.0/data/src/main/resources/application.properties:
--------------------------------------------------------------------------------
1 | spring.r2dbc.url=r2dbc:postgres://localhost/orders
2 | spring.r2dbc.username=orders
3 | spring.r2dbc.password=orders
4 |
--------------------------------------------------------------------------------
/2.0/data/src/test/java/com/example/data/DataApplicationTests.java:
--------------------------------------------------------------------------------
1 | package com.example.data;
2 |
3 | import org.junit.jupiter.api.Test;
4 | import org.springframework.boot.test.context.SpringBootTest;
5 |
6 | @SpringBootTest
7 | class DataApplicationTests {
8 |
9 | @Test
10 | void contextLoads() {
11 | }
12 |
13 | }
14 |
--------------------------------------------------------------------------------
/3.0/.mvn/wrapper/MavenWrapperDownloader.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2012-2019 the original author or authors.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * https://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 | import java.net.*;
17 | import java.io.*;
18 | import java.nio.channels.*;
19 | import java.util.Properties;
20 |
21 | public class MavenWrapperDownloader {
22 |
23 | private static final String WRAPPER_VERSION = "0.5.5";
24 | /**
25 | * Default URL to download the maven-wrapper.jar from, if no 'downloadUrl' is provided.
26 | */
27 | private static final String DEFAULT_DOWNLOAD_URL = "https://repo.maven.apache.org/maven2/io/takari/maven-wrapper/"
28 | + WRAPPER_VERSION + "/maven-wrapper-" + WRAPPER_VERSION + ".jar";
29 |
30 | /**
31 | * Path to the maven-wrapper.properties file, which might contain a downloadUrl property to
32 | * use instead of the default one.
33 | */
34 | private static final String MAVEN_WRAPPER_PROPERTIES_PATH =
35 | ".mvn/wrapper/maven-wrapper.properties";
36 |
37 | /**
38 | * Path where the maven-wrapper.jar will be saved to.
39 | */
40 | private static final String MAVEN_WRAPPER_JAR_PATH =
41 | ".mvn/wrapper/maven-wrapper.jar";
42 |
43 | /**
44 | * Name of the property which should be used to override the default download url for the wrapper.
45 | */
46 | private static final String PROPERTY_NAME_WRAPPER_URL = "wrapperUrl";
47 |
48 | public static void main(String args[]) {
49 | System.out.println("- Downloader started");
50 | File baseDirectory = new File(args[0]);
51 | System.out.println("- Using base directory: " + baseDirectory.getAbsolutePath());
52 |
53 | // If the maven-wrapper.properties exists, read it and check if it contains a custom
54 | // wrapperUrl parameter.
55 | File mavenWrapperPropertyFile = new File(baseDirectory, MAVEN_WRAPPER_PROPERTIES_PATH);
56 | String url = DEFAULT_DOWNLOAD_URL;
57 | if(mavenWrapperPropertyFile.exists()) {
58 | FileInputStream mavenWrapperPropertyFileInputStream = null;
59 | try {
60 | mavenWrapperPropertyFileInputStream = new FileInputStream(mavenWrapperPropertyFile);
61 | Properties mavenWrapperProperties = new Properties();
62 | mavenWrapperProperties.load(mavenWrapperPropertyFileInputStream);
63 | url = mavenWrapperProperties.getProperty(PROPERTY_NAME_WRAPPER_URL, url);
64 | } catch (IOException e) {
65 | System.out.println("- ERROR loading '" + MAVEN_WRAPPER_PROPERTIES_PATH + "'");
66 | } finally {
67 | try {
68 | if(mavenWrapperPropertyFileInputStream != null) {
69 | mavenWrapperPropertyFileInputStream.close();
70 | }
71 | } catch (IOException e) {
72 | // Ignore ...
73 | }
74 | }
75 | }
76 | System.out.println("- Downloading from: " + url);
77 |
78 | File outputFile = new File(baseDirectory.getAbsolutePath(), MAVEN_WRAPPER_JAR_PATH);
79 | if(!outputFile.getParentFile().exists()) {
80 | if(!outputFile.getParentFile().mkdirs()) {
81 | System.out.println(
82 | "- ERROR creating output directory '" + outputFile.getParentFile().getAbsolutePath() + "'");
83 | }
84 | }
85 | System.out.println("- Downloading to: " + outputFile.getAbsolutePath());
86 | try {
87 | downloadFileFromURL(url, outputFile);
88 | System.out.println("Done");
89 | System.exit(0);
90 | } catch (Throwable e) {
91 | System.out.println("- Error downloading");
92 | e.printStackTrace();
93 | System.exit(1);
94 | }
95 | }
96 |
97 | private static void downloadFileFromURL(String urlString, File destination) throws Exception {
98 | if (System.getenv("MVNW_USERNAME") != null && System.getenv("MVNW_PASSWORD") != null) {
99 | String username = System.getenv("MVNW_USERNAME");
100 | char[] password = System.getenv("MVNW_PASSWORD").toCharArray();
101 | Authenticator.setDefault(new Authenticator() {
102 | @Override
103 | protected PasswordAuthentication getPasswordAuthentication() {
104 | return new PasswordAuthentication(username, password);
105 | }
106 | });
107 | }
108 | URL website = new URL(urlString);
109 | ReadableByteChannel rbc;
110 | rbc = Channels.newChannel(website.openStream());
111 | FileOutputStream fos = new FileOutputStream(destination);
112 | fos.getChannel().transferFrom(rbc, 0, Long.MAX_VALUE);
113 | fos.close();
114 | rbc.close();
115 | }
116 |
117 | }
118 |
--------------------------------------------------------------------------------
/3.0/.mvn/wrapper/maven-wrapper.jar:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/joshlong/reactive-spring-livelessons-2e/f10c568102d0634a050639973ba99f632580392f/3.0/.mvn/wrapper/maven-wrapper.jar
--------------------------------------------------------------------------------
/3.0/.mvn/wrapper/maven-wrapper.properties:
--------------------------------------------------------------------------------
1 | distributionUrl=https://repo.maven.apache.org/maven2/org/apache/maven/apache-maven/3.6.2/apache-maven-3.6.2-bin.zip
2 | wrapperUrl=https://repo.maven.apache.org/maven2/io/takari/maven-wrapper/0.5.5/maven-wrapper-0.5.5.jar
3 |
--------------------------------------------------------------------------------
/3.0/pom.xml:
--------------------------------------------------------------------------------
1 |
2 |
4 | 4.0.0
5 |
6 | org.springframework.boot
7 | spring-boot-starter-parent
8 | 2.2.2.RELEASE
9 |
10 |
11 | com.example
12 | http
13 | 0.0.1-SNAPSHOT
14 | http
15 | Demo project for Spring Boot
16 |
17 |
18 | 13
19 |
20 |
21 |
22 |
23 | org.springframework.boot
24 | spring-boot-starter-webflux
25 |
26 |
27 | org.projectlombok
28 | lombok
29 | true
30 |
31 |
32 | org.springframework.boot
33 | spring-boot-starter-test
34 | test
35 |
36 |
37 | org.junit.vintage
38 | junit-vintage-engine
39 |
40 |
41 |
42 |
43 | io.projectreactor
44 | reactor-test
45 | test
46 |
47 |
48 |
49 |
50 |
51 |
52 | org.springframework.boot
53 | spring-boot-maven-plugin
54 |
55 |
56 |
57 |
58 |
59 |
--------------------------------------------------------------------------------
/3.0/src/main/java/com/example/http/HttpApplication.java:
--------------------------------------------------------------------------------
1 | package com.example.http;
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.context.annotation.Bean;
9 | import org.springframework.http.MediaType;
10 | import org.springframework.stereotype.Service;
11 | import org.springframework.web.reactive.function.server.*;
12 | import reactor.core.publisher.Flux;
13 | import reactor.core.publisher.Mono;
14 | import reactor.core.scheduler.Scheduler;
15 | import reactor.core.scheduler.Schedulers;
16 |
17 | import java.time.Duration;
18 | import java.time.Instant;
19 | import java.util.function.Supplier;
20 | import java.util.stream.Stream;
21 |
22 | import static org.springframework.web.reactive.function.server.RouterFunctions.route;
23 | import static org.springframework.web.reactive.function.server.ServerResponse.*;
24 |
25 | @SpringBootApplication
26 | public class HttpApplication {
27 |
28 | @Bean
29 | RouterFunction routes(GreetingService gs) {
30 | return route()
31 | .GET("/greeting/{name}", r -> ok().body(gs.greetOnce(new GreetingRequest(r.pathVariable("name"))), GreetingResponse.class))
32 | .GET("/greetings/{name}", r -> ok().contentType(MediaType.TEXT_EVENT_STREAM).body(gs.greetMany(new GreetingRequest(r.pathVariable("name"))), GreetingResponse.class)
33 | )
34 | .build();
35 | }
36 |
37 | public static void main(String[] args) {
38 | SpringApplication.run(HttpApplication.class, args);
39 | }
40 | }
41 |
42 | /*
43 | @RestController
44 | @RequiredArgsConstructor
45 | class GreetingsRestController {
46 |
47 | private final GreetingService greetingService;
48 |
49 | @GetMapping("/greeting/{name}")
50 | Mono greet(@PathVariable String name) {
51 | return this.greetingService.greet(new GreetingRequest(name));
52 | }
53 | }
54 |
55 | */
56 | @Service
57 | class GreetingService {
58 |
59 | Flux greetMany(GreetingRequest request) {
60 | return Flux
61 | .fromStream(Stream.generate(() -> greet(request.getName())))
62 | .delayElements(Duration.ofSeconds(1))
63 | .subscribeOn(Schedulers.elastic());
64 | }
65 |
66 | Mono greetOnce(GreetingRequest request) {
67 | return Mono.just(greet(request.getName()));
68 | }
69 |
70 | private GreetingResponse greet(String name) {
71 | return new GreetingResponse("Hello " + name + " @ " + Instant.now());
72 | }
73 | }
74 |
75 | @Data
76 | @AllArgsConstructor
77 | @NoArgsConstructor
78 | class GreetingResponse {
79 | private String message;
80 | }
81 |
82 | @Data
83 | @AllArgsConstructor
84 | @NoArgsConstructor
85 | class GreetingRequest {
86 | private String name;
87 | }
88 |
89 |
--------------------------------------------------------------------------------
/3.0/src/main/resources/application.properties:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/3.0/src/test/java/com/example/http/HttpApplicationTests.java:
--------------------------------------------------------------------------------
1 | package com.example.http;
2 |
3 | import org.junit.jupiter.api.Test;
4 | import org.springframework.boot.test.context.SpringBootTest;
5 |
6 | @SpringBootTest
7 | class HttpApplicationTests {
8 |
9 | @Test
10 | void contextLoads() {
11 | }
12 |
13 | }
14 |
--------------------------------------------------------------------------------
/4.0/.mvn/wrapper/MavenWrapperDownloader.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2012-2019 the original author or authors.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * https://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 | import java.net.*;
17 | import java.io.*;
18 | import java.nio.channels.*;
19 | import java.util.Properties;
20 |
21 | public class MavenWrapperDownloader {
22 |
23 | private static final String WRAPPER_VERSION = "0.5.5";
24 | /**
25 | * Default URL to download the maven-wrapper.jar from, if no 'downloadUrl' is provided.
26 | */
27 | private static final String DEFAULT_DOWNLOAD_URL = "https://repo.maven.apache.org/maven2/io/takari/maven-wrapper/"
28 | + WRAPPER_VERSION + "/maven-wrapper-" + WRAPPER_VERSION + ".jar";
29 |
30 | /**
31 | * Path to the maven-wrapper.properties file, which might contain a downloadUrl property to
32 | * use instead of the default one.
33 | */
34 | private static final String MAVEN_WRAPPER_PROPERTIES_PATH =
35 | ".mvn/wrapper/maven-wrapper.properties";
36 |
37 | /**
38 | * Path where the maven-wrapper.jar will be saved to.
39 | */
40 | private static final String MAVEN_WRAPPER_JAR_PATH =
41 | ".mvn/wrapper/maven-wrapper.jar";
42 |
43 | /**
44 | * Name of the property which should be used to override the default download url for the wrapper.
45 | */
46 | private static final String PROPERTY_NAME_WRAPPER_URL = "wrapperUrl";
47 |
48 | public static void main(String args[]) {
49 | System.out.println("- Downloader started");
50 | File baseDirectory = new File(args[0]);
51 | System.out.println("- Using base directory: " + baseDirectory.getAbsolutePath());
52 |
53 | // If the maven-wrapper.properties exists, read it and check if it contains a custom
54 | // wrapperUrl parameter.
55 | File mavenWrapperPropertyFile = new File(baseDirectory, MAVEN_WRAPPER_PROPERTIES_PATH);
56 | String url = DEFAULT_DOWNLOAD_URL;
57 | if(mavenWrapperPropertyFile.exists()) {
58 | FileInputStream mavenWrapperPropertyFileInputStream = null;
59 | try {
60 | mavenWrapperPropertyFileInputStream = new FileInputStream(mavenWrapperPropertyFile);
61 | Properties mavenWrapperProperties = new Properties();
62 | mavenWrapperProperties.load(mavenWrapperPropertyFileInputStream);
63 | url = mavenWrapperProperties.getProperty(PROPERTY_NAME_WRAPPER_URL, url);
64 | } catch (IOException e) {
65 | System.out.println("- ERROR loading '" + MAVEN_WRAPPER_PROPERTIES_PATH + "'");
66 | } finally {
67 | try {
68 | if(mavenWrapperPropertyFileInputStream != null) {
69 | mavenWrapperPropertyFileInputStream.close();
70 | }
71 | } catch (IOException e) {
72 | // Ignore ...
73 | }
74 | }
75 | }
76 | System.out.println("- Downloading from: " + url);
77 |
78 | File outputFile = new File(baseDirectory.getAbsolutePath(), MAVEN_WRAPPER_JAR_PATH);
79 | if(!outputFile.getParentFile().exists()) {
80 | if(!outputFile.getParentFile().mkdirs()) {
81 | System.out.println(
82 | "- ERROR creating output directory '" + outputFile.getParentFile().getAbsolutePath() + "'");
83 | }
84 | }
85 | System.out.println("- Downloading to: " + outputFile.getAbsolutePath());
86 | try {
87 | downloadFileFromURL(url, outputFile);
88 | System.out.println("Done");
89 | System.exit(0);
90 | } catch (Throwable e) {
91 | System.out.println("- Error downloading");
92 | e.printStackTrace();
93 | System.exit(1);
94 | }
95 | }
96 |
97 | private static void downloadFileFromURL(String urlString, File destination) throws Exception {
98 | if (System.getenv("MVNW_USERNAME") != null && System.getenv("MVNW_PASSWORD") != null) {
99 | String username = System.getenv("MVNW_USERNAME");
100 | char[] password = System.getenv("MVNW_PASSWORD").toCharArray();
101 | Authenticator.setDefault(new Authenticator() {
102 | @Override
103 | protected PasswordAuthentication getPasswordAuthentication() {
104 | return new PasswordAuthentication(username, password);
105 | }
106 | });
107 | }
108 | URL website = new URL(urlString);
109 | ReadableByteChannel rbc;
110 | rbc = Channels.newChannel(website.openStream());
111 | FileOutputStream fos = new FileOutputStream(destination);
112 | fos.getChannel().transferFrom(rbc, 0, Long.MAX_VALUE);
113 | fos.close();
114 | rbc.close();
115 | }
116 |
117 | }
118 |
--------------------------------------------------------------------------------
/4.0/.mvn/wrapper/maven-wrapper.jar:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/joshlong/reactive-spring-livelessons-2e/f10c568102d0634a050639973ba99f632580392f/4.0/.mvn/wrapper/maven-wrapper.jar
--------------------------------------------------------------------------------
/4.0/.mvn/wrapper/maven-wrapper.properties:
--------------------------------------------------------------------------------
1 | distributionUrl=https://repo.maven.apache.org/maven2/org/apache/maven/apache-maven/3.6.2/apache-maven-3.6.2-bin.zip
2 | wrapperUrl=https://repo.maven.apache.org/maven2/io/takari/maven-wrapper/0.5.5/maven-wrapper-0.5.5.jar
3 |
--------------------------------------------------------------------------------
/4.0/pom.xml:
--------------------------------------------------------------------------------
1 |
2 |
4 | 4.0.0
5 |
6 | org.springframework.boot
7 | spring-boot-starter-parent
8 | 2.2.2.RELEASE
9 |
10 |
11 | com.example
12 | websockets
13 | 0.0.1-SNAPSHOT
14 | websockets
15 | Demo project for Spring Boot
16 |
17 |
18 | 13
19 |
20 |
21 |
22 |
23 | org.springframework.boot
24 | spring-boot-starter-webflux
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 |
--------------------------------------------------------------------------------
/4.0/src/main/java/com/example/websockets/WebsocketsApplication.java:
--------------------------------------------------------------------------------
1 | package com.example.websockets;
2 |
3 | import lombok.AllArgsConstructor;
4 | import lombok.Data;
5 | import lombok.NoArgsConstructor;
6 | import lombok.extern.log4j.Log4j2;
7 | import org.springframework.boot.SpringApplication;
8 | import org.springframework.boot.autoconfigure.SpringBootApplication;
9 | import org.springframework.context.annotation.Bean;
10 | import org.springframework.context.annotation.Configuration;
11 | import org.springframework.stereotype.Service;
12 | import org.springframework.web.reactive.handler.SimpleUrlHandlerMapping;
13 | import org.springframework.web.reactive.socket.WebSocketHandler;
14 | import org.springframework.web.reactive.socket.WebSocketMessage;
15 | import org.springframework.web.reactive.socket.WebSocketSession;
16 | import org.springframework.web.reactive.socket.server.support.WebSocketHandlerAdapter;
17 | import reactor.core.publisher.Flux;
18 | import reactor.core.publisher.Mono;
19 |
20 | import java.time.Duration;
21 | import java.time.Instant;
22 | import java.util.Map;
23 | import java.util.function.Supplier;
24 | import java.util.stream.Stream;
25 |
26 | @SpringBootApplication
27 | public class WebsocketsApplication {
28 |
29 |
30 | public static void main(String[] args) {
31 | SpringApplication.run(WebsocketsApplication.class, args);
32 | }
33 |
34 | }
35 |
36 | @Log4j2
37 | @Configuration
38 | class GreetingWebSocketConfiguration {
39 |
40 | @Bean
41 | SimpleUrlHandlerMapping simpleUrlHandlerMapping(WebSocketHandler wsh) {
42 | return new SimpleUrlHandlerMapping(Map.of("/ws/greetings", wsh), 10);
43 | }
44 |
45 | @Bean
46 | WebSocketHandler webSocketHandler(GreetingService greetingService) {
47 | return session -> {
48 | var receive = session
49 | .receive()
50 | .map(WebSocketMessage::getPayloadAsText)
51 | .map(GreetingRequest::new)
52 | .flatMap(greetingService::greet)
53 | .map(GreetingResponse::getMessage)
54 | .map(session::textMessage)
55 | .doOnEach(signal -> log.info(signal.getType()))
56 | .doFinally(signal -> log.info("finally: " + signal.toString()));
57 | return session.send(receive);
58 | };
59 | }
60 |
61 | @Bean
62 | WebSocketHandlerAdapter webSocketHandlerAdapter() {
63 | return new WebSocketHandlerAdapter();
64 | }
65 |
66 | }
67 |
68 | @Service
69 | class GreetingService {
70 |
71 | Flux greet(GreetingRequest request) {
72 | return Flux
73 | .fromStream(Stream.generate(() -> new GreetingResponse("Hello " + request.getName() + " @ " + Instant.now())))
74 | .delayElements(Duration.ofSeconds(1));
75 | }
76 | }
77 |
78 | @Data
79 | @AllArgsConstructor
80 | @NoArgsConstructor
81 | class GreetingRequest {
82 | private String name;
83 | }
84 |
85 | @Data
86 | @AllArgsConstructor
87 | @NoArgsConstructor
88 | class GreetingResponse {
89 | private String message;
90 | }
91 |
--------------------------------------------------------------------------------
/4.0/src/main/resources/application.properties:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/4.0/src/main/resources/static/ws.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
15 |
16 |
--------------------------------------------------------------------------------
/4.0/src/test/java/com/example/websockets/WebsocketsApplicationTests.java:
--------------------------------------------------------------------------------
1 | package com.example.websockets;
2 |
3 | import org.junit.jupiter.api.Test;
4 | import org.springframework.boot.test.context.SpringBootTest;
5 |
6 | @SpringBootTest
7 | class WebsocketsApplicationTests {
8 |
9 | @Test
10 | void contextLoads() {
11 | }
12 |
13 | }
14 |
--------------------------------------------------------------------------------
/5.0/greeting-client/.mvn/wrapper/MavenWrapperDownloader.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2012-2019 the original author or authors.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * https://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 | import java.net.*;
17 | import java.io.*;
18 | import java.nio.channels.*;
19 | import java.util.Properties;
20 |
21 | public class MavenWrapperDownloader {
22 |
23 | private static final String WRAPPER_VERSION = "0.5.5";
24 | /**
25 | * Default URL to download the maven-wrapper.jar from, if no 'downloadUrl' is provided.
26 | */
27 | private static final String DEFAULT_DOWNLOAD_URL = "https://repo.maven.apache.org/maven2/io/takari/maven-wrapper/"
28 | + WRAPPER_VERSION + "/maven-wrapper-" + WRAPPER_VERSION + ".jar";
29 |
30 | /**
31 | * Path to the maven-wrapper.properties file, which might contain a downloadUrl property to
32 | * use instead of the default one.
33 | */
34 | private static final String MAVEN_WRAPPER_PROPERTIES_PATH =
35 | ".mvn/wrapper/maven-wrapper.properties";
36 |
37 | /**
38 | * Path where the maven-wrapper.jar will be saved to.
39 | */
40 | private static final String MAVEN_WRAPPER_JAR_PATH =
41 | ".mvn/wrapper/maven-wrapper.jar";
42 |
43 | /**
44 | * Name of the property which should be used to override the default download url for the wrapper.
45 | */
46 | private static final String PROPERTY_NAME_WRAPPER_URL = "wrapperUrl";
47 |
48 | public static void main(String args[]) {
49 | System.out.println("- Downloader started");
50 | File baseDirectory = new File(args[0]);
51 | System.out.println("- Using base directory: " + baseDirectory.getAbsolutePath());
52 |
53 | // If the maven-wrapper.properties exists, read it and check if it contains a custom
54 | // wrapperUrl parameter.
55 | File mavenWrapperPropertyFile = new File(baseDirectory, MAVEN_WRAPPER_PROPERTIES_PATH);
56 | String url = DEFAULT_DOWNLOAD_URL;
57 | if(mavenWrapperPropertyFile.exists()) {
58 | FileInputStream mavenWrapperPropertyFileInputStream = null;
59 | try {
60 | mavenWrapperPropertyFileInputStream = new FileInputStream(mavenWrapperPropertyFile);
61 | Properties mavenWrapperProperties = new Properties();
62 | mavenWrapperProperties.load(mavenWrapperPropertyFileInputStream);
63 | url = mavenWrapperProperties.getProperty(PROPERTY_NAME_WRAPPER_URL, url);
64 | } catch (IOException e) {
65 | System.out.println("- ERROR loading '" + MAVEN_WRAPPER_PROPERTIES_PATH + "'");
66 | } finally {
67 | try {
68 | if(mavenWrapperPropertyFileInputStream != null) {
69 | mavenWrapperPropertyFileInputStream.close();
70 | }
71 | } catch (IOException e) {
72 | // Ignore ...
73 | }
74 | }
75 | }
76 | System.out.println("- Downloading from: " + url);
77 |
78 | File outputFile = new File(baseDirectory.getAbsolutePath(), MAVEN_WRAPPER_JAR_PATH);
79 | if(!outputFile.getParentFile().exists()) {
80 | if(!outputFile.getParentFile().mkdirs()) {
81 | System.out.println(
82 | "- ERROR creating output directory '" + outputFile.getParentFile().getAbsolutePath() + "'");
83 | }
84 | }
85 | System.out.println("- Downloading to: " + outputFile.getAbsolutePath());
86 | try {
87 | downloadFileFromURL(url, outputFile);
88 | System.out.println("Done");
89 | System.exit(0);
90 | } catch (Throwable e) {
91 | System.out.println("- Error downloading");
92 | e.printStackTrace();
93 | System.exit(1);
94 | }
95 | }
96 |
97 | private static void downloadFileFromURL(String urlString, File destination) throws Exception {
98 | if (System.getenv("MVNW_USERNAME") != null && System.getenv("MVNW_PASSWORD") != null) {
99 | String username = System.getenv("MVNW_USERNAME");
100 | char[] password = System.getenv("MVNW_PASSWORD").toCharArray();
101 | Authenticator.setDefault(new Authenticator() {
102 | @Override
103 | protected PasswordAuthentication getPasswordAuthentication() {
104 | return new PasswordAuthentication(username, password);
105 | }
106 | });
107 | }
108 | URL website = new URL(urlString);
109 | ReadableByteChannel rbc;
110 | rbc = Channels.newChannel(website.openStream());
111 | FileOutputStream fos = new FileOutputStream(destination);
112 | fos.getChannel().transferFrom(rbc, 0, Long.MAX_VALUE);
113 | fos.close();
114 | rbc.close();
115 | }
116 |
117 | }
118 |
--------------------------------------------------------------------------------
/5.0/greeting-client/.mvn/wrapper/maven-wrapper.jar:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/joshlong/reactive-spring-livelessons-2e/f10c568102d0634a050639973ba99f632580392f/5.0/greeting-client/.mvn/wrapper/maven-wrapper.jar
--------------------------------------------------------------------------------
/5.0/greeting-client/.mvn/wrapper/maven-wrapper.properties:
--------------------------------------------------------------------------------
1 | distributionUrl=https://repo.maven.apache.org/maven2/org/apache/maven/apache-maven/3.6.2/apache-maven-3.6.2-bin.zip
2 | wrapperUrl=https://repo.maven.apache.org/maven2/io/takari/maven-wrapper/0.5.5/maven-wrapper-0.5.5.jar
3 |
--------------------------------------------------------------------------------
/5.0/greeting-client/pom.xml:
--------------------------------------------------------------------------------
1 |
2 |
4 | 4.0.0
5 |
6 | org.springframework.boot
7 | spring-boot-starter-parent
8 | 2.2.2.RELEASE
9 |
10 |
11 | com.example
12 | greeting-client
13 | 0.0.1-SNAPSHOT
14 | greeting-client
15 | Demo project for Spring Boot
16 |
17 |
18 | Hoxton.RELEASE
19 | 13
20 |
21 |
22 |
23 |
24 | org.springframework.cloud
25 | spring-cloud-starter-circuitbreaker-reactor-resilience4j
26 |
27 |
28 | org.springframework.boot
29 | spring-boot-starter-webflux
30 |
31 |
32 |
33 | org.projectlombok
34 | lombok
35 | true
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 | io.projectreactor
50 | reactor-test
51 | test
52 |
53 |
54 |
55 |
56 |
57 |
58 | org.springframework.boot
59 | spring-boot-maven-plugin
60 |
61 |
62 |
63 |
64 |
65 |
66 | org.springframework.cloud
67 | spring-cloud-dependencies
68 | ${spring-cloud.version}
69 | pom
70 | import
71 |
72 |
73 |
74 |
75 |
76 |
77 |
--------------------------------------------------------------------------------
/5.0/greeting-client/src/main/java/com/example/greetingclient/GreetingClientApplication.java:
--------------------------------------------------------------------------------
1 | package com.example.greetingclient;
2 |
3 | import lombok.AllArgsConstructor;
4 | import lombok.Data;
5 | import lombok.NoArgsConstructor;
6 | import lombok.extern.log4j.Log4j2;
7 | import org.springframework.boot.SpringApplication;
8 | import org.springframework.boot.autoconfigure.SpringBootApplication;
9 | import org.springframework.boot.context.event.ApplicationReadyEvent;
10 | import org.springframework.cloud.client.circuitbreaker.ReactiveCircuitBreaker;
11 | import org.springframework.cloud.client.circuitbreaker.ReactiveCircuitBreakerFactory;
12 | import org.springframework.context.annotation.Bean;
13 | import org.springframework.context.event.EventListener;
14 | import org.springframework.stereotype.Component;
15 | import org.springframework.web.reactive.function.client.*;
16 | import reactor.core.publisher.Flux;
17 | import reactor.core.publisher.Mono;
18 |
19 | import java.time.Duration;
20 |
21 | @SpringBootApplication
22 | public class GreetingClientApplication {
23 |
24 | public static void main(String[] args) {
25 | SpringApplication.run(GreetingClientApplication.class, args);
26 | }
27 |
28 | @Bean
29 | WebClient webClient(WebClient.Builder builder) {
30 | return builder
31 | .baseUrl("http://localhost:8080")
32 | // .filter( ExchangeFilterFunctions.basicAuthentication())
33 | .build();
34 | }
35 |
36 | }
37 |
38 | @Component
39 | @Log4j2
40 | //@RequiredArgsConstructor
41 | class Client {
42 |
43 | private final WebClient client;
44 | private final ReactiveCircuitBreaker reactiveCircuitBreaker;
45 |
46 | Client(WebClient client, ReactiveCircuitBreakerFactory cbf) {
47 | this.client = client;
48 | this.reactiveCircuitBreaker = cbf.create("greeting");
49 | }
50 |
51 | @EventListener(ApplicationReadyEvent.class)
52 | public void ready() {
53 |
54 |
55 | // Flux host1 = null;//todo
56 | // Flux host2 = null;//todo
57 | // Flux host3 = null;//todo
58 | //
59 | // Flux first = Flux.first(host1, host2, host3);
60 |
61 | var name = "Spring Fans";
62 |
63 | Mono http = this.client
64 | .get()
65 | .uri("/greeting/{name}", name)
66 | .retrieve()
67 | .bodyToMono(GreetingResponse.class)
68 | .timeout(Duration.ofSeconds(10))
69 | .map(GreetingResponse::getMessage);
70 |
71 | this.reactiveCircuitBreaker
72 | .run(http, throwable -> Mono.just("EEEK!"))
73 | .subscribe(gr -> log.info("Mono: " + gr));
74 |
75 | }
76 | }
77 |
78 |
79 | @Data
80 | @AllArgsConstructor
81 | @NoArgsConstructor
82 | class GreetingRequest {
83 | private String name;
84 | }
85 |
86 | @Data
87 | @AllArgsConstructor
88 | @NoArgsConstructor
89 | class GreetingResponse {
90 | private String message;
91 | }
--------------------------------------------------------------------------------
/5.0/greeting-client/src/main/resources/application.properties:
--------------------------------------------------------------------------------
1 | server.port=0
2 |
--------------------------------------------------------------------------------
/5.0/greeting-client/src/test/java/com/example/greetingclient/GreetingClientApplicationTests.java:
--------------------------------------------------------------------------------
1 | package com.example.greetingclient;
2 |
3 | import org.junit.jupiter.api.Test;
4 | import org.springframework.boot.test.context.SpringBootTest;
5 |
6 | @SpringBootTest
7 | class GreetingClientApplicationTests {
8 |
9 | @Test
10 | void contextLoads() {
11 | }
12 |
13 | }
14 |
--------------------------------------------------------------------------------
/5.0/greeting-service/.mvn/wrapper/maven-wrapper.jar:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/joshlong/reactive-spring-livelessons-2e/f10c568102d0634a050639973ba99f632580392f/5.0/greeting-service/.mvn/wrapper/maven-wrapper.jar
--------------------------------------------------------------------------------
/5.0/greeting-service/.mvn/wrapper/maven-wrapper.properties:
--------------------------------------------------------------------------------
1 | distributionUrl=https://repo.maven.apache.org/maven2/org/apache/maven/apache-maven/3.6.2/apache-maven-3.6.2-bin.zip
2 | wrapperUrl=https://repo.maven.apache.org/maven2/io/takari/maven-wrapper/0.5.5/maven-wrapper-0.5.5.jar
3 |
--------------------------------------------------------------------------------
/5.0/greeting-service/pom.xml:
--------------------------------------------------------------------------------
1 |
2 |
4 | 4.0.0
5 |
6 | org.springframework.boot
7 | spring-boot-starter-parent
8 | 2.2.2.RELEASE
9 |
10 |
11 | com.example
12 | greeting-service
13 | 0.0.1-SNAPSHOT
14 | greeting-service
15 | Demo project for Spring Boot
16 |
17 |
18 | 13
19 |
20 |
21 |
22 |
23 | org.springframework.boot
24 | spring-boot-starter-webflux
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 |
--------------------------------------------------------------------------------
/5.0/greeting-service/src/main/java/com/example/greetingservice/GreetingServiceApplication.java:
--------------------------------------------------------------------------------
1 | package com.example.greetingservice;
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.context.annotation.Bean;
9 | import org.springframework.http.MediaType;
10 | import org.springframework.stereotype.Service;
11 | import org.springframework.web.reactive.function.server.HandlerFunction;
12 | import org.springframework.web.reactive.function.server.RouterFunction;
13 | import org.springframework.web.reactive.function.server.ServerRequest;
14 | import org.springframework.web.reactive.function.server.ServerResponse;
15 | import reactor.core.publisher.Flux;
16 | import reactor.core.publisher.Mono;
17 |
18 | import java.time.Duration;
19 | import java.time.Instant;
20 | import java.util.function.Supplier;
21 | import java.util.stream.Stream;
22 |
23 | import static org.springframework.web.reactive.function.server.RouterFunctions.resourceLookupFunction;
24 | import static org.springframework.web.reactive.function.server.RouterFunctions.route;
25 | import static org.springframework.web.reactive.function.server.ServerResponse.*;
26 |
27 | @SpringBootApplication
28 | public class GreetingServiceApplication {
29 |
30 | public static void main(String[] args) {
31 | SpringApplication.run(GreetingServiceApplication.class, args);
32 | }
33 |
34 | @Bean
35 | RouterFunction routes(GreetingService greetingService) {
36 | return route()
37 | .GET("/greeting/{name}", serverRequest -> ok().body(
38 | greetingService.greetOnce(new GreetingRequest(serverRequest.pathVariable("name"))), GreetingResponse.class))
39 | .GET("/greetings/{name}", serverRequest -> ok().contentType(MediaType.TEXT_EVENT_STREAM).body(
40 | greetingService.greetMany(new GreetingRequest(serverRequest.pathVariable("name"))), GreetingResponse.class))
41 | .build();
42 | }
43 |
44 | }
45 |
46 | @Data
47 | @AllArgsConstructor
48 | @NoArgsConstructor
49 | class GreetingRequest {
50 | private String name;
51 | }
52 |
53 | @Data
54 | @AllArgsConstructor
55 | @NoArgsConstructor
56 | class GreetingResponse {
57 | private String message;
58 | }
59 |
60 | @Service
61 | class GreetingService {
62 |
63 | Mono greetOnce(GreetingRequest request) {
64 | return Mono.just(greet(request.getName()));
65 | }
66 |
67 | Flux greetMany(GreetingRequest request) {
68 | return Flux
69 | .fromStream(Stream.generate(() -> greet(request.getName())))
70 | .delayElements(Duration.ofSeconds(1));
71 | }
72 |
73 | private GreetingResponse greet(String name) {
74 | return new GreetingResponse("Hello " + name + " @ " + Instant.now() + "!");
75 | }
76 | }
77 |
--------------------------------------------------------------------------------
/5.0/greeting-service/src/main/resources/application.properties:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/5.0/greeting-service/src/test/java/com/example/greetingservice/GreetingServiceApplicationTests.java:
--------------------------------------------------------------------------------
1 | package com.example.greetingservice;
2 |
3 | import org.junit.jupiter.api.Test;
4 | import org.springframework.boot.test.context.SpringBootTest;
5 |
6 | @SpringBootTest
7 | class GreetingServiceApplicationTests {
8 |
9 | @Test
10 | void contextLoads() {
11 | }
12 |
13 | }
14 |
--------------------------------------------------------------------------------
/6.0/raw-rsocket-client/.mvn/wrapper/MavenWrapperDownloader.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2012-2019 the original author or authors.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * https://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 |
17 | import java.net.*;
18 | import java.io.*;
19 | import java.nio.channels.*;
20 | import java.util.Properties;
21 |
22 | public class MavenWrapperDownloader {
23 |
24 | private static final String WRAPPER_VERSION = "0.5.5";
25 | /**
26 | * Default URL to download the maven-wrapper.jar from, if no 'downloadUrl' is provided.
27 | */
28 | private static final String DEFAULT_DOWNLOAD_URL = "https://repo.maven.apache.org/maven2/io/takari/maven-wrapper/"
29 | + WRAPPER_VERSION + "/maven-wrapper-" + WRAPPER_VERSION + ".jar";
30 |
31 | /**
32 | * Path to the maven-wrapper.properties file, which might contain a downloadUrl property to
33 | * use instead of the default one.
34 | */
35 | private static final String MAVEN_WRAPPER_PROPERTIES_PATH =
36 | ".mvn/wrapper/maven-wrapper.properties";
37 |
38 | /**
39 | * Path where the maven-wrapper.jar will be saved to.
40 | */
41 | private static final String MAVEN_WRAPPER_JAR_PATH =
42 | ".mvn/wrapper/maven-wrapper.jar";
43 |
44 | /**
45 | * Name of the property which should be used to override the default download url for the wrapper.
46 | */
47 | private static final String PROPERTY_NAME_WRAPPER_URL = "wrapperUrl";
48 |
49 | public static void main(String args[]) {
50 | System.out.println("- Downloader started");
51 | File baseDirectory = new File(args[0]);
52 | System.out.println("- Using base directory: " + baseDirectory.getAbsolutePath());
53 |
54 | // If the maven-wrapper.properties exists, read it and check if it contains a custom
55 | // wrapperUrl parameter.
56 | File mavenWrapperPropertyFile = new File(baseDirectory, MAVEN_WRAPPER_PROPERTIES_PATH);
57 | String url = DEFAULT_DOWNLOAD_URL;
58 | if (mavenWrapperPropertyFile.exists()) {
59 | FileInputStream mavenWrapperPropertyFileInputStream = null;
60 | try {
61 | mavenWrapperPropertyFileInputStream = new FileInputStream(mavenWrapperPropertyFile);
62 | Properties mavenWrapperProperties = new Properties();
63 | mavenWrapperProperties.load(mavenWrapperPropertyFileInputStream);
64 | url = mavenWrapperProperties.getProperty(PROPERTY_NAME_WRAPPER_URL, url);
65 | } catch (IOException e) {
66 | System.out.println("- ERROR loading '" + MAVEN_WRAPPER_PROPERTIES_PATH + "'");
67 | } finally {
68 | try {
69 | if (mavenWrapperPropertyFileInputStream != null) {
70 | mavenWrapperPropertyFileInputStream.close();
71 | }
72 | } catch (IOException e) {
73 | // Ignore ...
74 | }
75 | }
76 | }
77 | System.out.println("- Downloading from: " + url);
78 |
79 | File outputFile = new File(baseDirectory.getAbsolutePath(), MAVEN_WRAPPER_JAR_PATH);
80 | if (!outputFile.getParentFile().exists()) {
81 | if (!outputFile.getParentFile().mkdirs()) {
82 | System.out.println(
83 | "- ERROR creating output directory '" + outputFile.getParentFile().getAbsolutePath() + "'");
84 | }
85 | }
86 | System.out.println("- Downloading to: " + outputFile.getAbsolutePath());
87 | try {
88 | downloadFileFromURL(url, outputFile);
89 | System.out.println("Done");
90 | System.exit(0);
91 | } catch (Throwable e) {
92 | System.out.println("- Error downloading");
93 | e.printStackTrace();
94 | System.exit(1);
95 | }
96 | }
97 |
98 | private static void downloadFileFromURL(String urlString, File destination) throws Exception {
99 | if (System.getenv("MVNW_USERNAME") != null && System.getenv("MVNW_PASSWORD") != null) {
100 | String username = System.getenv("MVNW_USERNAME");
101 | char[] password = System.getenv("MVNW_PASSWORD").toCharArray();
102 | Authenticator.setDefault(new Authenticator() {
103 | @Override
104 | protected PasswordAuthentication getPasswordAuthentication() {
105 | return new PasswordAuthentication(username, password);
106 | }
107 | });
108 | }
109 | URL website = new URL(urlString);
110 | ReadableByteChannel rbc;
111 | rbc = Channels.newChannel(website.openStream());
112 | FileOutputStream fos = new FileOutputStream(destination);
113 | fos.getChannel().transferFrom(rbc, 0, Long.MAX_VALUE);
114 | fos.close();
115 | rbc.close();
116 | }
117 |
118 | }
119 |
--------------------------------------------------------------------------------
/6.0/raw-rsocket-client/.mvn/wrapper/maven-wrapper.jar:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/joshlong/reactive-spring-livelessons-2e/f10c568102d0634a050639973ba99f632580392f/6.0/raw-rsocket-client/.mvn/wrapper/maven-wrapper.jar
--------------------------------------------------------------------------------
/6.0/raw-rsocket-client/.mvn/wrapper/maven-wrapper.properties:
--------------------------------------------------------------------------------
1 | distributionUrl=https://repo.maven.apache.org/maven2/org/apache/maven/apache-maven/3.6.2/apache-maven-3.6.2-bin.zip
2 | wrapperUrl=https://repo.maven.apache.org/maven2/io/takari/maven-wrapper/0.5.5/maven-wrapper-0.5.5.jar
3 |
--------------------------------------------------------------------------------
/6.0/raw-rsocket-client/HELP.md:
--------------------------------------------------------------------------------
1 | # Getting Started
2 |
3 | ### Reference Documentation
4 | For further reference, please consider the following sections:
5 |
6 | * [Official Apache Maven documentation](https://maven.apache.org/guides/index.html)
7 | * [Spring Boot Maven Plugin Reference Guide](https://docs.spring.io/spring-boot/docs/2.2.2.RELEASE/maven-plugin/)
8 |
9 |
--------------------------------------------------------------------------------
/6.0/raw-rsocket-client/pom.xml:
--------------------------------------------------------------------------------
1 |
2 |
4 | 4.0.0
5 |
6 | org.springframework.boot
7 | spring-boot-starter-parent
8 | 2.2.2.RELEASE
9 |
10 |
11 | com.example
12 | raw-rsocket-client
13 | 0.0.1-SNAPSHOT
14 | raw-rsocket-client
15 | Demo project for Spring Boot
16 |
17 |
18 | 13
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 |
--------------------------------------------------------------------------------
/6.0/raw-rsocket-client/src/main/java/com/example/rawrsocketclient/RawRsocketClientApplication.java:
--------------------------------------------------------------------------------
1 | package com.example.rawrsocketclient;
2 |
3 | import com.fasterxml.jackson.databind.ObjectMapper;
4 | import io.rsocket.Payload;
5 | import io.rsocket.RSocketFactory;
6 | import io.rsocket.transport.netty.client.TcpClientTransport;
7 | import io.rsocket.util.DefaultPayload;
8 | import lombok.*;
9 | import lombok.extern.log4j.Log4j2;
10 | import org.springframework.boot.SpringApplication;
11 | import org.springframework.boot.autoconfigure.SpringBootApplication;
12 | import org.springframework.boot.context.event.ApplicationReadyEvent;
13 | import org.springframework.context.ApplicationListener;
14 | import org.springframework.context.event.EventListener;
15 | import org.springframework.core.Ordered;
16 | import org.springframework.stereotype.Component;
17 |
18 | @SpringBootApplication
19 | public class RawRsocketClientApplication {
20 |
21 | @SneakyThrows
22 | public static void main(String[] args) {
23 | SpringApplication.run(RawRsocketClientApplication.class, args);
24 | System.in.read();
25 | }
26 |
27 | }
28 |
29 | @Log4j2
30 | @RequiredArgsConstructor
31 | @Component
32 | class Consumer {
33 |
34 | private final JsonHelper jsonHelper;
35 |
36 | @EventListener(ApplicationReadyEvent.class)
37 | public void start() {
38 |
39 | log.info("consumer starting...");
40 |
41 | var request = jsonHelper.write(new GreetingRequest("Livelessons"));
42 |
43 | RSocketFactory
44 | .connect()
45 | .transport(TcpClientTransport.create(7000))
46 | .start()
47 | .flatMapMany(sender -> sender
48 | .requestStream(DefaultPayload.create(request))
49 | .map(Payload::getDataUtf8)
50 | .map(json -> jsonHelper.read(json, GreetingResponse.class))
51 | )
52 | .subscribe(result -> log.info("processing new result " + result.toString()));
53 | }
54 | }
55 |
56 | @Data
57 | @AllArgsConstructor
58 | @NoArgsConstructor
59 | class GreetingRequest {
60 | private String name;
61 | }
62 |
63 | @Data
64 | @AllArgsConstructor
65 | @NoArgsConstructor
66 | class GreetingResponse {
67 | private String message;
68 | }
69 |
70 | @Component
71 | @RequiredArgsConstructor
72 | class JsonHelper {
73 |
74 | private final ObjectMapper objectMapper;
75 |
76 | @SneakyThrows
77 | T read(String json, Class clzz) {
78 | return this.objectMapper.readValue(json, clzz);
79 | }
80 |
81 | @SneakyThrows
82 | String write(Object o) {
83 | return this.objectMapper.writeValueAsString(o);
84 | }
85 | }
86 |
--------------------------------------------------------------------------------
/6.0/raw-rsocket-client/src/main/resources/application.properties:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/6.0/raw-rsocket-client/src/test/java/com/example/rawrsocketclient/RawRsocketClientApplicationTests.java:
--------------------------------------------------------------------------------
1 | package com.example.rawrsocketclient;
2 |
3 | import org.junit.jupiter.api.Test;
4 | import org.springframework.boot.test.context.SpringBootTest;
5 |
6 | @SpringBootTest
7 | class RawRsocketClientApplicationTests {
8 |
9 | @Test
10 | void contextLoads() {
11 | }
12 |
13 | }
14 |
--------------------------------------------------------------------------------
/6.0/raw-rsocket-service/.mvn/wrapper/maven-wrapper.jar:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/joshlong/reactive-spring-livelessons-2e/f10c568102d0634a050639973ba99f632580392f/6.0/raw-rsocket-service/.mvn/wrapper/maven-wrapper.jar
--------------------------------------------------------------------------------
/6.0/raw-rsocket-service/.mvn/wrapper/maven-wrapper.properties:
--------------------------------------------------------------------------------
1 | distributionUrl=https://repo.maven.apache.org/maven2/org/apache/maven/apache-maven/3.6.2/apache-maven-3.6.2-bin.zip
2 | wrapperUrl=https://repo.maven.apache.org/maven2/io/takari/maven-wrapper/0.5.5/maven-wrapper-0.5.5.jar
3 |
--------------------------------------------------------------------------------
/6.0/raw-rsocket-service/HELP.md:
--------------------------------------------------------------------------------
1 | # Getting Started
2 |
3 | ### Reference Documentation
4 | For further reference, please consider the following sections:
5 |
6 | * [Official Apache Maven documentation](https://maven.apache.org/guides/index.html)
7 | * [Spring Boot Maven Plugin Reference Guide](https://docs.spring.io/spring-boot/docs/2.2.2.RELEASE/maven-plugin/)
8 |
9 |
--------------------------------------------------------------------------------
/6.0/raw-rsocket-service/pom.xml:
--------------------------------------------------------------------------------
1 |
2 |
4 | 4.0.0
5 |
6 | org.springframework.boot
7 | spring-boot-starter-parent
8 | 2.2.2.RELEASE
9 |
10 |
11 | com.example
12 | raw-rsocket-service
13 | 0.0.1-SNAPSHOT
14 | raw-rsocket-service
15 | Demo project for Spring Boot
16 |
17 |
18 | 13
19 |
20 |
21 |
22 |
23 | org.springframework.boot
24 | spring-boot-starter-rsocket
25 |
26 |
27 | org.springframework.boot
28 | spring-boot-starter-webflux
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 | io.projectreactor
49 | reactor-test
50 | test
51 |
52 |
53 |
54 |
55 |
56 |
57 | org.springframework.boot
58 | spring-boot-maven-plugin
59 |
60 |
61 |
62 |
63 |
64 |
--------------------------------------------------------------------------------
/6.0/raw-rsocket-service/src/main/java/com/example/rawrsocketservice/RawRsocketServiceApplication.java:
--------------------------------------------------------------------------------
1 | package com.example.rawrsocketservice;
2 |
3 | import com.fasterxml.jackson.databind.ObjectMapper;
4 | import io.rsocket.AbstractRSocket;
5 | import io.rsocket.Payload;
6 | import io.rsocket.RSocketFactory;
7 | import io.rsocket.SocketAcceptor;
8 | import io.rsocket.transport.netty.server.TcpServerTransport;
9 | import io.rsocket.util.DefaultPayload;
10 | import lombok.*;
11 | import lombok.extern.log4j.Log4j2;
12 | import org.springframework.boot.SpringApplication;
13 | import org.springframework.boot.autoconfigure.SpringBootApplication;
14 | import org.springframework.boot.context.event.ApplicationReadyEvent;
15 | import org.springframework.context.ApplicationListener;
16 | import org.springframework.context.event.EventListener;
17 | import org.springframework.core.Ordered;
18 | import org.springframework.stereotype.Component;
19 | import reactor.core.publisher.Flux;
20 | import reactor.core.publisher.Mono;
21 |
22 | import java.time.Duration;
23 | import java.time.Instant;
24 | import java.util.stream.Stream;
25 |
26 | @SpringBootApplication
27 | public class RawRsocketServiceApplication {
28 | public static void main(String[] args) {
29 | SpringApplication.run(RawRsocketServiceApplication.class, args);
30 | }
31 | }
32 |
33 | @Data
34 | @AllArgsConstructor
35 | @NoArgsConstructor
36 | class GreetingRequest {
37 | private String name;
38 | }
39 |
40 | @Data
41 | @AllArgsConstructor
42 | @NoArgsConstructor
43 | class GreetingResponse {
44 | private String message;
45 | }
46 |
47 | @Component
48 | @RequiredArgsConstructor
49 | class JsonHelper {
50 |
51 | private final ObjectMapper objectMapper;
52 |
53 | @SneakyThrows
54 | T read(String json, Class clzz) {
55 | return this.objectMapper.readValue(json, clzz);
56 | }
57 |
58 | @SneakyThrows
59 | String write(Object o) {
60 | return this.objectMapper.writeValueAsString(o);
61 | }
62 | }
63 |
64 | @Log4j2
65 | @Component
66 | @RequiredArgsConstructor
67 | class Producer {
68 |
69 | private final JsonHelper jsonHelper;
70 |
71 | private Flux greet(GreetingRequest request) {
72 | return Flux
73 | .fromStream(Stream.generate(
74 | () -> new GreetingResponse("Hello " + request.getName() + " @ " + Instant.now().toString())))
75 | .delayElements(Duration.ofSeconds(1));
76 | }
77 |
78 | @EventListener(ApplicationReadyEvent.class)
79 | public void start() {
80 | log.info("producer starting...");
81 | SocketAcceptor socketAcceptor = (connectionSetupPayload, sender) -> {
82 |
83 | AbstractRSocket abstractRSocket = new AbstractRSocket() {
84 |
85 | @Override
86 | public Flux requestStream(Payload payload) {
87 | String json = payload.getDataUtf8();
88 | GreetingRequest greetingRequest = jsonHelper.read(json, GreetingRequest.class);
89 | return greet(greetingRequest)
90 | .map(jsonHelper::write)
91 | .map(DefaultPayload::create);
92 | }
93 | };
94 |
95 | return Mono.just(abstractRSocket);
96 | };
97 |
98 | TcpServerTransport transport = TcpServerTransport.create(7000);
99 |
100 | RSocketFactory
101 | .receive()
102 | .acceptor(socketAcceptor)
103 | .transport(transport)
104 | .start()
105 | .block();
106 | }
107 | }
108 |
--------------------------------------------------------------------------------
/6.0/raw-rsocket-service/src/main/resources/application.properties:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/6.0/raw-rsocket-service/src/test/java/com/example/rawrsocketservice/RawRsocketServiceApplicationTests.java:
--------------------------------------------------------------------------------
1 | package com.example.rawrsocketservice;
2 |
3 | import org.junit.jupiter.api.Test;
4 | import org.springframework.boot.test.context.SpringBootTest;
5 |
6 | @SpringBootTest
7 | class RawRsocketServiceApplicationTests {
8 |
9 | @Test
10 | void contextLoads() {
11 | }
12 |
13 | }
14 |
--------------------------------------------------------------------------------
/6.0/rsocket-client/.mvn/wrapper/MavenWrapperDownloader.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2012-2019 the original author or authors.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * https://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 |
17 | import java.net.*;
18 | import java.io.*;
19 | import java.nio.channels.*;
20 | import java.util.Properties;
21 |
22 | public class MavenWrapperDownloader {
23 |
24 | private static final String WRAPPER_VERSION = "0.5.5";
25 | /**
26 | * Default URL to download the maven-wrapper.jar from, if no 'downloadUrl' is provided.
27 | */
28 | private static final String DEFAULT_DOWNLOAD_URL = "https://repo.maven.apache.org/maven2/io/takari/maven-wrapper/"
29 | + WRAPPER_VERSION + "/maven-wrapper-" + WRAPPER_VERSION + ".jar";
30 |
31 | /**
32 | * Path to the maven-wrapper.properties file, which might contain a downloadUrl property to
33 | * use instead of the default one.
34 | */
35 | private static final String MAVEN_WRAPPER_PROPERTIES_PATH =
36 | ".mvn/wrapper/maven-wrapper.properties";
37 |
38 | /**
39 | * Path where the maven-wrapper.jar will be saved to.
40 | */
41 | private static final String MAVEN_WRAPPER_JAR_PATH =
42 | ".mvn/wrapper/maven-wrapper.jar";
43 |
44 | /**
45 | * Name of the property which should be used to override the default download url for the wrapper.
46 | */
47 | private static final String PROPERTY_NAME_WRAPPER_URL = "wrapperUrl";
48 |
49 | public static void main(String args[]) {
50 | System.out.println("- Downloader started");
51 | File baseDirectory = new File(args[0]);
52 | System.out.println("- Using base directory: " + baseDirectory.getAbsolutePath());
53 |
54 | // If the maven-wrapper.properties exists, read it and check if it contains a custom
55 | // wrapperUrl parameter.
56 | File mavenWrapperPropertyFile = new File(baseDirectory, MAVEN_WRAPPER_PROPERTIES_PATH);
57 | String url = DEFAULT_DOWNLOAD_URL;
58 | if (mavenWrapperPropertyFile.exists()) {
59 | FileInputStream mavenWrapperPropertyFileInputStream = null;
60 | try {
61 | mavenWrapperPropertyFileInputStream = new FileInputStream(mavenWrapperPropertyFile);
62 | Properties mavenWrapperProperties = new Properties();
63 | mavenWrapperProperties.load(mavenWrapperPropertyFileInputStream);
64 | url = mavenWrapperProperties.getProperty(PROPERTY_NAME_WRAPPER_URL, url);
65 | } catch (IOException e) {
66 | System.out.println("- ERROR loading '" + MAVEN_WRAPPER_PROPERTIES_PATH + "'");
67 | } finally {
68 | try {
69 | if (mavenWrapperPropertyFileInputStream != null) {
70 | mavenWrapperPropertyFileInputStream.close();
71 | }
72 | } catch (IOException e) {
73 | // Ignore ...
74 | }
75 | }
76 | }
77 | System.out.println("- Downloading from: " + url);
78 |
79 | File outputFile = new File(baseDirectory.getAbsolutePath(), MAVEN_WRAPPER_JAR_PATH);
80 | if (!outputFile.getParentFile().exists()) {
81 | if (!outputFile.getParentFile().mkdirs()) {
82 | System.out.println(
83 | "- ERROR creating output directory '" + outputFile.getParentFile().getAbsolutePath() + "'");
84 | }
85 | }
86 | System.out.println("- Downloading to: " + outputFile.getAbsolutePath());
87 | try {
88 | downloadFileFromURL(url, outputFile);
89 | System.out.println("Done");
90 | System.exit(0);
91 | } catch (Throwable e) {
92 | System.out.println("- Error downloading");
93 | e.printStackTrace();
94 | System.exit(1);
95 | }
96 | }
97 |
98 | private static void downloadFileFromURL(String urlString, File destination) throws Exception {
99 | if (System.getenv("MVNW_USERNAME") != null && System.getenv("MVNW_PASSWORD") != null) {
100 | String username = System.getenv("MVNW_USERNAME");
101 | char[] password = System.getenv("MVNW_PASSWORD").toCharArray();
102 | Authenticator.setDefault(new Authenticator() {
103 | @Override
104 | protected PasswordAuthentication getPasswordAuthentication() {
105 | return new PasswordAuthentication(username, password);
106 | }
107 | });
108 | }
109 | URL website = new URL(urlString);
110 | ReadableByteChannel rbc;
111 | rbc = Channels.newChannel(website.openStream());
112 | FileOutputStream fos = new FileOutputStream(destination);
113 | fos.getChannel().transferFrom(rbc, 0, Long.MAX_VALUE);
114 | fos.close();
115 | rbc.close();
116 | }
117 |
118 | }
119 |
--------------------------------------------------------------------------------
/6.0/rsocket-client/.mvn/wrapper/maven-wrapper.jar:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/joshlong/reactive-spring-livelessons-2e/f10c568102d0634a050639973ba99f632580392f/6.0/rsocket-client/.mvn/wrapper/maven-wrapper.jar
--------------------------------------------------------------------------------
/6.0/rsocket-client/.mvn/wrapper/maven-wrapper.properties:
--------------------------------------------------------------------------------
1 | distributionUrl=https://repo.maven.apache.org/maven2/org/apache/maven/apache-maven/3.6.2/apache-maven-3.6.2-bin.zip
2 | wrapperUrl=https://repo.maven.apache.org/maven2/io/takari/maven-wrapper/0.5.5/maven-wrapper-0.5.5.jar
3 |
--------------------------------------------------------------------------------
/6.0/rsocket-client/HELP.md:
--------------------------------------------------------------------------------
1 | # Getting Started
2 |
3 | ### Reference Documentation
4 | For further reference, please consider the following sections:
5 |
6 | * [Official Apache Maven documentation](https://maven.apache.org/guides/index.html)
7 | * [Spring Boot Maven Plugin Reference Guide](https://docs.spring.io/spring-boot/docs/2.2.2.RELEASE/maven-plugin/)
8 |
9 |
--------------------------------------------------------------------------------
/6.0/rsocket-client/pom.xml:
--------------------------------------------------------------------------------
1 |
2 |
4 | 4.0.0
5 |
6 | org.springframework.boot
7 | spring-boot-starter-parent
8 | 2.2.2.RELEASE
9 |
10 |
11 | com.example
12 | rsocket-client
13 | 0.0.1-SNAPSHOT
14 | rsocket-client
15 | Demo project for Spring Boot
16 |
17 |
18 | 13
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 |
--------------------------------------------------------------------------------
/6.0/rsocket-client/src/main/java/com/example/rsocketclient/RsocketClientApplication.java:
--------------------------------------------------------------------------------
1 | package com.example.rsocketclient;
2 |
3 | import lombok.*;
4 | import lombok.extern.log4j.Log4j2;
5 | import org.springframework.boot.SpringApplication;
6 | import org.springframework.boot.autoconfigure.SpringBootApplication;
7 | import org.springframework.boot.context.event.ApplicationReadyEvent;
8 | import org.springframework.context.annotation.Bean;
9 | import org.springframework.context.event.EventListener;
10 | import org.springframework.messaging.rsocket.RSocketRequester;
11 | import org.springframework.stereotype.Component;
12 |
13 | @SpringBootApplication
14 | public class RsocketClientApplication {
15 |
16 | @Bean
17 | RSocketRequester rSocketRequester(RSocketRequester.Builder builder) {
18 | return builder.connectTcp("localhost", 7002).block();
19 | }
20 |
21 | @SneakyThrows
22 | public static void main(String[] args) {
23 | SpringApplication.run(RsocketClientApplication.class, args);
24 | System.in.read();
25 | }
26 |
27 | }
28 |
29 | @Component
30 | @Log4j2
31 | @RequiredArgsConstructor
32 | class Client {
33 |
34 | private final RSocketRequester rSocketRequester;
35 |
36 | @EventListener(ApplicationReadyEvent.class)
37 | public void ready() {
38 | this.rSocketRequester
39 | .route("greetings.10")
40 | .data(new GreetingRequest("Livelessons"))
41 | .retrieveFlux(GreetingResponse.class)
42 | .subscribe(log::info);
43 | }
44 | }
45 |
46 | @Data
47 | @AllArgsConstructor
48 | @NoArgsConstructor
49 | class GreetingRequest {
50 | private String name;
51 | }
52 |
53 | @Data
54 | @AllArgsConstructor
55 | @NoArgsConstructor
56 | class GreetingResponse {
57 | private String message;
58 | }
--------------------------------------------------------------------------------
/6.0/rsocket-client/src/main/resources/application.properties:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/6.0/rsocket-client/src/test/java/com/example/rsocketclient/RsocketClientApplicationTests.java:
--------------------------------------------------------------------------------
1 | package com.example.rsocketclient;
2 |
3 | import org.junit.jupiter.api.Test;
4 | import org.springframework.boot.test.context.SpringBootTest;
5 |
6 | @SpringBootTest
7 | class RsocketClientApplicationTests {
8 |
9 | @Test
10 | void contextLoads() {
11 | }
12 |
13 | }
14 |
--------------------------------------------------------------------------------
/6.0/rsocket-service/.mvn/wrapper/MavenWrapperDownloader.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2012-2019 the original author or authors.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * https://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 | import java.net.*;
17 | import java.io.*;
18 | import java.nio.channels.*;
19 | import java.util.Properties;
20 |
21 | public class MavenWrapperDownloader {
22 |
23 | private static final String WRAPPER_VERSION = "0.5.5";
24 | /**
25 | * Default URL to download the maven-wrapper.jar from, if no 'downloadUrl' is provided.
26 | */
27 | private static final String DEFAULT_DOWNLOAD_URL = "https://repo.maven.apache.org/maven2/io/takari/maven-wrapper/"
28 | + WRAPPER_VERSION + "/maven-wrapper-" + WRAPPER_VERSION + ".jar";
29 |
30 | /**
31 | * Path to the maven-wrapper.properties file, which might contain a downloadUrl property to
32 | * use instead of the default one.
33 | */
34 | private static final String MAVEN_WRAPPER_PROPERTIES_PATH =
35 | ".mvn/wrapper/maven-wrapper.properties";
36 |
37 | /**
38 | * Path where the maven-wrapper.jar will be saved to.
39 | */
40 | private static final String MAVEN_WRAPPER_JAR_PATH =
41 | ".mvn/wrapper/maven-wrapper.jar";
42 |
43 | /**
44 | * Name of the property which should be used to override the default download url for the wrapper.
45 | */
46 | private static final String PROPERTY_NAME_WRAPPER_URL = "wrapperUrl";
47 |
48 | public static void main(String args[]) {
49 | System.out.println("- Downloader started");
50 | File baseDirectory = new File(args[0]);
51 | System.out.println("- Using base directory: " + baseDirectory.getAbsolutePath());
52 |
53 | // If the maven-wrapper.properties exists, read it and check if it contains a custom
54 | // wrapperUrl parameter.
55 | File mavenWrapperPropertyFile = new File(baseDirectory, MAVEN_WRAPPER_PROPERTIES_PATH);
56 | String url = DEFAULT_DOWNLOAD_URL;
57 | if(mavenWrapperPropertyFile.exists()) {
58 | FileInputStream mavenWrapperPropertyFileInputStream = null;
59 | try {
60 | mavenWrapperPropertyFileInputStream = new FileInputStream(mavenWrapperPropertyFile);
61 | Properties mavenWrapperProperties = new Properties();
62 | mavenWrapperProperties.load(mavenWrapperPropertyFileInputStream);
63 | url = mavenWrapperProperties.getProperty(PROPERTY_NAME_WRAPPER_URL, url);
64 | } catch (IOException e) {
65 | System.out.println("- ERROR loading '" + MAVEN_WRAPPER_PROPERTIES_PATH + "'");
66 | } finally {
67 | try {
68 | if(mavenWrapperPropertyFileInputStream != null) {
69 | mavenWrapperPropertyFileInputStream.close();
70 | }
71 | } catch (IOException e) {
72 | // Ignore ...
73 | }
74 | }
75 | }
76 | System.out.println("- Downloading from: " + url);
77 |
78 | File outputFile = new File(baseDirectory.getAbsolutePath(), MAVEN_WRAPPER_JAR_PATH);
79 | if(!outputFile.getParentFile().exists()) {
80 | if(!outputFile.getParentFile().mkdirs()) {
81 | System.out.println(
82 | "- ERROR creating output directory '" + outputFile.getParentFile().getAbsolutePath() + "'");
83 | }
84 | }
85 | System.out.println("- Downloading to: " + outputFile.getAbsolutePath());
86 | try {
87 | downloadFileFromURL(url, outputFile);
88 | System.out.println("Done");
89 | System.exit(0);
90 | } catch (Throwable e) {
91 | System.out.println("- Error downloading");
92 | e.printStackTrace();
93 | System.exit(1);
94 | }
95 | }
96 |
97 | private static void downloadFileFromURL(String urlString, File destination) throws Exception {
98 | if (System.getenv("MVNW_USERNAME") != null && System.getenv("MVNW_PASSWORD") != null) {
99 | String username = System.getenv("MVNW_USERNAME");
100 | char[] password = System.getenv("MVNW_PASSWORD").toCharArray();
101 | Authenticator.setDefault(new Authenticator() {
102 | @Override
103 | protected PasswordAuthentication getPasswordAuthentication() {
104 | return new PasswordAuthentication(username, password);
105 | }
106 | });
107 | }
108 | URL website = new URL(urlString);
109 | ReadableByteChannel rbc;
110 | rbc = Channels.newChannel(website.openStream());
111 | FileOutputStream fos = new FileOutputStream(destination);
112 | fos.getChannel().transferFrom(rbc, 0, Long.MAX_VALUE);
113 | fos.close();
114 | rbc.close();
115 | }
116 |
117 | }
118 |
--------------------------------------------------------------------------------
/6.0/rsocket-service/.mvn/wrapper/maven-wrapper.jar:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/joshlong/reactive-spring-livelessons-2e/f10c568102d0634a050639973ba99f632580392f/6.0/rsocket-service/.mvn/wrapper/maven-wrapper.jar
--------------------------------------------------------------------------------
/6.0/rsocket-service/.mvn/wrapper/maven-wrapper.properties:
--------------------------------------------------------------------------------
1 | distributionUrl=https://repo.maven.apache.org/maven2/org/apache/maven/apache-maven/3.6.2/apache-maven-3.6.2-bin.zip
2 | wrapperUrl=https://repo.maven.apache.org/maven2/io/takari/maven-wrapper/0.5.5/maven-wrapper-0.5.5.jar
3 |
--------------------------------------------------------------------------------
/6.0/rsocket-service/HELP.md:
--------------------------------------------------------------------------------
1 | # Getting Started
2 |
3 | ### Reference Documentation
4 | For further reference, please consider the following sections:
5 |
6 | * [Official Apache Maven documentation](https://maven.apache.org/guides/index.html)
7 | * [Spring Boot Maven Plugin Reference Guide](https://docs.spring.io/spring-boot/docs/2.2.2.RELEASE/maven-plugin/)
8 |
9 |
--------------------------------------------------------------------------------
/6.0/rsocket-service/pom.xml:
--------------------------------------------------------------------------------
1 |
2 |
4 | 4.0.0
5 |
6 | org.springframework.boot
7 | spring-boot-starter-parent
8 | 2.2.2.RELEASE
9 |
10 |
11 | com.example
12 | rsocket-service
13 | 0.0.1-SNAPSHOT
14 | rsocket-service
15 | Demo project for Spring Boot
16 |
17 |
18 | 13
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 |
--------------------------------------------------------------------------------
/6.0/rsocket-service/src/main/java/com/example/rsocketservice/RsocketServiceApplication.java:
--------------------------------------------------------------------------------
1 | package com.example.rsocketservice;
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.messaging.handler.annotation.DestinationVariable;
9 | import org.springframework.messaging.handler.annotation.MessageMapping;
10 | import org.springframework.stereotype.Controller;
11 | import reactor.core.publisher.Flux;
12 |
13 | import java.time.Duration;
14 | import java.time.Instant;
15 | import java.util.stream.Stream;
16 |
17 | @SpringBootApplication
18 | public class RsocketServiceApplication {
19 |
20 | public static void main(String[] args) {
21 | SpringApplication.run(RsocketServiceApplication.class, args);
22 | }
23 |
24 | }
25 |
26 | @Controller
27 | class GreetingService {
28 |
29 | @MessageMapping("greetings.{timeInSeconds}")
30 | Flux greet(GreetingRequest request, @DestinationVariable int timeInSeconds) {
31 | if (timeInSeconds == 0 ) {
32 | timeInSeconds = 1 ;
33 | }
34 | return Flux
35 | .fromStream(Stream.generate(() -> new GreetingResponse("Hello " + request.getName() + " @ " + Instant.now() + "!")))
36 | .delayElements(Duration.ofSeconds(timeInSeconds));
37 | }
38 | }
39 |
40 | @Data
41 | @AllArgsConstructor
42 | @NoArgsConstructor
43 | class GreetingRequest {
44 | private String name;
45 | }
46 |
47 | @Data
48 | @AllArgsConstructor
49 | @NoArgsConstructor
50 | class GreetingResponse {
51 | private String message;
52 | }
--------------------------------------------------------------------------------
/6.0/rsocket-service/src/main/resources/application.properties:
--------------------------------------------------------------------------------
1 | spring.rsocket.server.port=7002
2 |
--------------------------------------------------------------------------------
/6.0/rsocket-service/src/test/java/com/example/rsocketservice/RsocketServiceApplicationTests.java:
--------------------------------------------------------------------------------
1 | package com.example.rsocketservice;
2 |
3 | import org.junit.jupiter.api.Test;
4 | import org.springframework.boot.test.context.SpringBootTest;
5 |
6 | @SpringBootTest
7 | class RsocketServiceApplicationTests {
8 |
9 | @Test
10 | void contextLoads() {
11 | }
12 |
13 | }
14 |
--------------------------------------------------------------------------------
/7.0/secure-http-client/.mvn/wrapper/maven-wrapper.jar:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/joshlong/reactive-spring-livelessons-2e/f10c568102d0634a050639973ba99f632580392f/7.0/secure-http-client/.mvn/wrapper/maven-wrapper.jar
--------------------------------------------------------------------------------
/7.0/secure-http-client/.mvn/wrapper/maven-wrapper.properties:
--------------------------------------------------------------------------------
1 | distributionUrl=https://repo.maven.apache.org/maven2/org/apache/maven/apache-maven/3.6.2/apache-maven-3.6.2-bin.zip
2 | wrapperUrl=https://repo.maven.apache.org/maven2/io/takari/maven-wrapper/0.5.5/maven-wrapper-0.5.5.jar
3 |
--------------------------------------------------------------------------------
/7.0/secure-http-client/pom.xml:
--------------------------------------------------------------------------------
1 |
2 |
4 | 4.0.0
5 |
6 | org.springframework.boot
7 | spring-boot-starter-parent
8 | 2.2.2.RELEASE
9 |
10 |
11 | com.example
12 | secure-http-client
13 | 0.0.1-SNAPSHOT
14 | secure-http-client
15 | Demo project for Spring Boot
16 |
17 |
18 | 13
19 |
20 |
21 |
22 |
23 | org.springframework.boot
24 | spring-boot-starter-security
25 |
26 |
27 | org.springframework.boot
28 | spring-boot-starter-webflux
29 |
30 |
31 | org.projectlombok
32 | lombok
33 | true
34 |
35 |
36 | org.springframework.boot
37 | spring-boot-starter-test
38 | test
39 |
40 |
41 | org.junit.vintage
42 | junit-vintage-engine
43 |
44 |
45 |
46 |
47 | io.projectreactor
48 | reactor-test
49 | test
50 |
51 |
52 |
53 |
54 |
55 |
56 | org.springframework.boot
57 | spring-boot-maven-plugin
58 |
59 |
60 |
61 |
62 |
63 |
--------------------------------------------------------------------------------
/7.0/secure-http-client/src/main/java/com/example/http/HttpApplication.java:
--------------------------------------------------------------------------------
1 | package com.example.http;
2 |
3 | import lombok.AllArgsConstructor;
4 | import lombok.Data;
5 | import lombok.NoArgsConstructor;
6 | import lombok.RequiredArgsConstructor;
7 | import lombok.extern.log4j.Log4j2;
8 | import org.springframework.boot.SpringApplication;
9 | import org.springframework.boot.autoconfigure.SpringBootApplication;
10 | import org.springframework.boot.context.event.ApplicationReadyEvent;
11 | import org.springframework.context.annotation.Bean;
12 | import org.springframework.context.event.EventListener;
13 | import org.springframework.stereotype.Component;
14 | import org.springframework.web.reactive.function.client.ExchangeFilterFunctions;
15 | import org.springframework.web.reactive.function.client.WebClient;
16 |
17 | import static org.springframework.web.reactive.function.server.RouterFunctions.route;
18 |
19 | @SpringBootApplication
20 | public class HttpApplication {
21 |
22 | @Bean
23 | WebClient webClient(WebClient.Builder builder) {
24 | return builder
25 | .filter(ExchangeFilterFunctions.basicAuthentication("user", "password"))
26 | .build();
27 | }
28 |
29 | public static void main(String[] args) {
30 | SpringApplication.run(HttpApplication.class, args);
31 | }
32 | }
33 |
34 | @Component
35 | @Log4j2
36 | @RequiredArgsConstructor
37 | class Consumer {
38 |
39 | private final WebClient client;
40 |
41 | @EventListener(ApplicationReadyEvent.class)
42 | public void start() {
43 | this.client
44 | .get()
45 | .uri("http://localhost:8080/greetings")
46 | .retrieve()
47 | .bodyToFlux(GreetingResponse.class)
48 | .subscribe(log::info);
49 | }
50 | }
51 |
52 | @Data
53 | @AllArgsConstructor
54 | @NoArgsConstructor
55 | class GreetingResponse {
56 | private String message;
57 | }
58 |
59 | @Data
60 | @AllArgsConstructor
61 | @NoArgsConstructor
62 | class GreetingRequest {
63 | private String name;
64 | }
65 |
66 |
--------------------------------------------------------------------------------
/7.0/secure-http-client/src/main/resources/application.properties:
--------------------------------------------------------------------------------
1 | server.port=0
2 |
--------------------------------------------------------------------------------
/7.0/secure-http-client/src/test/java/com/example/http/HttpApplicationTests.java:
--------------------------------------------------------------------------------
1 | package com.example.http;
2 |
3 | import org.junit.jupiter.api.Test;
4 | import org.springframework.boot.test.context.SpringBootTest;
5 |
6 | @SpringBootTest
7 | class HttpApplicationTests {
8 |
9 | @Test
10 | void contextLoads() {
11 | }
12 |
13 | }
14 |
--------------------------------------------------------------------------------
/7.0/secure-http-service/.mvn/wrapper/maven-wrapper.jar:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/joshlong/reactive-spring-livelessons-2e/f10c568102d0634a050639973ba99f632580392f/7.0/secure-http-service/.mvn/wrapper/maven-wrapper.jar
--------------------------------------------------------------------------------
/7.0/secure-http-service/.mvn/wrapper/maven-wrapper.properties:
--------------------------------------------------------------------------------
1 | distributionUrl=https://repo.maven.apache.org/maven2/org/apache/maven/apache-maven/3.6.2/apache-maven-3.6.2-bin.zip
2 | wrapperUrl=https://repo.maven.apache.org/maven2/io/takari/maven-wrapper/0.5.5/maven-wrapper-0.5.5.jar
3 |
--------------------------------------------------------------------------------
/7.0/secure-http-service/pom.xml:
--------------------------------------------------------------------------------
1 |
2 |
4 | 4.0.0
5 |
6 | org.springframework.boot
7 | spring-boot-starter-parent
8 | 2.2.2.RELEASE
9 |
10 |
11 | com.example
12 | secure-http-service
13 | 0.0.1-SNAPSHOT
14 | secure-http-service
15 | Demo project for Spring Boot
16 |
17 |
18 | 13
19 |
20 |
21 |
22 |
23 | org.springframework.boot
24 | spring-boot-starter-security
25 |
26 |
27 | org.springframework.boot
28 | spring-boot-starter-webflux
29 |
30 |
31 | org.projectlombok
32 | lombok
33 | true
34 |
35 |
36 | org.springframework.boot
37 | spring-boot-starter-test
38 | test
39 |
40 |
41 | org.junit.vintage
42 | junit-vintage-engine
43 |
44 |
45 |
46 |
47 | io.projectreactor
48 | reactor-test
49 | test
50 |
51 |
52 |
53 |
54 |
55 |
56 | org.springframework.boot
57 | spring-boot-maven-plugin
58 |
59 |
60 |
61 |
62 |
63 |
--------------------------------------------------------------------------------
/7.0/secure-http-service/src/main/java/com/example/http/HttpApplication.java:
--------------------------------------------------------------------------------
1 | package com.example.http;
2 |
3 | import lombok.AllArgsConstructor;
4 | import lombok.Data;
5 | import lombok.NoArgsConstructor;
6 | import lombok.extern.log4j.Log4j2;
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.security.config.Customizer;
12 | import org.springframework.security.config.web.server.ServerHttpSecurity;
13 | import org.springframework.security.core.userdetails.MapReactiveUserDetailsService;
14 | import org.springframework.security.core.userdetails.User;
15 | import org.springframework.security.core.userdetails.UserDetails;
16 | import org.springframework.security.web.server.SecurityWebFilterChain;
17 | import org.springframework.stereotype.Service;
18 | import org.springframework.web.reactive.function.server.*;
19 | import reactor.core.publisher.Flux;
20 | import reactor.core.publisher.Mono;
21 | import reactor.core.scheduler.Scheduler;
22 | import reactor.core.scheduler.Schedulers;
23 |
24 | import java.security.Principal;
25 | import java.time.Duration;
26 | import java.time.Instant;
27 | import java.util.function.Supplier;
28 | import java.util.stream.Stream;
29 |
30 | import static org.springframework.web.reactive.function.server.RouterFunctions.route;
31 | import static org.springframework.web.reactive.function.server.ServerResponse.*;
32 |
33 | @Log4j2
34 | @SpringBootApplication
35 | public class HttpApplication {
36 |
37 | @Bean
38 | MapReactiveUserDetailsService userDetails() {
39 | UserDetails user = User.withDefaultPasswordEncoder().username("user").password("password").roles("USER").build();
40 | return new MapReactiveUserDetailsService(user);
41 | }
42 |
43 | @Bean
44 | SecurityWebFilterChain authorization(ServerHttpSecurity http) {
45 | return http
46 | .csrf(ServerHttpSecurity.CsrfSpec::disable)
47 | .authorizeExchange(x -> x.pathMatchers("/greeting*").authenticated())
48 | .httpBasic(Customizer.withDefaults())
49 | .build();
50 | }
51 |
52 |
53 | @Bean
54 | RouterFunction routes(GreetingService gs) {
55 | return route()
56 | .GET("/greeting", request -> {
57 |
58 | Mono greetingResponseFlux = request
59 | .principal()
60 | .map(Principal::getName)
61 | .map(GreetingRequest::new)
62 | .flatMap(gs::greetOnce);
63 | return ServerResponse.ok().body(greetingResponseFlux, GreetingResponse.class);
64 | })
65 | .GET("/greetings", request -> {
66 | Flux greetingResponseFlux = request
67 | .principal()
68 | .map(Principal::getName)
69 | .map(GreetingRequest::new)
70 | .flatMapMany(gs::greetMany);
71 | return ServerResponse
72 | .ok()
73 | .contentType(MediaType.TEXT_EVENT_STREAM)
74 | .body(greetingResponseFlux, GreetingResponse.class);
75 | })
76 | .build();
77 | }
78 |
79 | public static void main(String[] args) {
80 | SpringApplication.run(HttpApplication.class, args);
81 | }
82 | }
83 |
84 |
85 | @Service
86 | class GreetingService {
87 |
88 | Flux greetMany(GreetingRequest request) {
89 | return Flux
90 | .fromStream(Stream.generate(() -> greet(request.getName())))
91 | .delayElements(Duration.ofSeconds(1))
92 | .subscribeOn(Schedulers.elastic());
93 | }
94 |
95 | Mono greetOnce(GreetingRequest request) {
96 | return Mono.just(greet(request.getName()));
97 | }
98 |
99 | private GreetingResponse greet(String name) {
100 | return new GreetingResponse("Hello " + name + " @ " + Instant.now());
101 | }
102 | }
103 |
104 | @Data
105 | @AllArgsConstructor
106 | @NoArgsConstructor
107 | class GreetingResponse {
108 | private String message;
109 | }
110 |
111 | @Data
112 | @AllArgsConstructor
113 | @NoArgsConstructor
114 | class GreetingRequest {
115 | private String name;
116 | }
117 |
118 |
--------------------------------------------------------------------------------
/7.0/secure-http-service/src/main/resources/application.properties:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/7.0/secure-http-service/src/test/java/com/example/http/HttpApplicationTests.java:
--------------------------------------------------------------------------------
1 | package com.example.http;
2 |
3 | import org.junit.jupiter.api.Test;
4 | import org.springframework.boot.test.context.SpringBootTest;
5 |
6 | @SpringBootTest
7 | class HttpApplicationTests {
8 |
9 | @Test
10 | void contextLoads() {
11 | }
12 |
13 | }
14 |
--------------------------------------------------------------------------------
/7.0/secure-rsocket-client/.mvn/wrapper/MavenWrapperDownloader.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2012-2019 the original author or authors.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * https://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 |
17 | import java.net.*;
18 | import java.io.*;
19 | import java.nio.channels.*;
20 | import java.util.Properties;
21 |
22 | public class MavenWrapperDownloader {
23 |
24 | private static final String WRAPPER_VERSION = "0.5.5";
25 | /**
26 | * Default URL to download the maven-wrapper.jar from, if no 'downloadUrl' is provided.
27 | */
28 | private static final String DEFAULT_DOWNLOAD_URL = "https://repo.maven.apache.org/maven2/io/takari/maven-wrapper/"
29 | + WRAPPER_VERSION + "/maven-wrapper-" + WRAPPER_VERSION + ".jar";
30 |
31 | /**
32 | * Path to the maven-wrapper.properties file, which might contain a downloadUrl property to
33 | * use instead of the default one.
34 | */
35 | private static final String MAVEN_WRAPPER_PROPERTIES_PATH =
36 | ".mvn/wrapper/maven-wrapper.properties";
37 |
38 | /**
39 | * Path where the maven-wrapper.jar will be saved to.
40 | */
41 | private static final String MAVEN_WRAPPER_JAR_PATH =
42 | ".mvn/wrapper/maven-wrapper.jar";
43 |
44 | /**
45 | * Name of the property which should be used to override the default download url for the wrapper.
46 | */
47 | private static final String PROPERTY_NAME_WRAPPER_URL = "wrapperUrl";
48 |
49 | public static void main(String args[]) {
50 | System.out.println("- Downloader started");
51 | File baseDirectory = new File(args[0]);
52 | System.out.println("- Using base directory: " + baseDirectory.getAbsolutePath());
53 |
54 | // If the maven-wrapper.properties exists, read it and check if it contains a custom
55 | // wrapperUrl parameter.
56 | File mavenWrapperPropertyFile = new File(baseDirectory, MAVEN_WRAPPER_PROPERTIES_PATH);
57 | String url = DEFAULT_DOWNLOAD_URL;
58 | if (mavenWrapperPropertyFile.exists()) {
59 | FileInputStream mavenWrapperPropertyFileInputStream = null;
60 | try {
61 | mavenWrapperPropertyFileInputStream = new FileInputStream(mavenWrapperPropertyFile);
62 | Properties mavenWrapperProperties = new Properties();
63 | mavenWrapperProperties.load(mavenWrapperPropertyFileInputStream);
64 | url = mavenWrapperProperties.getProperty(PROPERTY_NAME_WRAPPER_URL, url);
65 | } catch (IOException e) {
66 | System.out.println("- ERROR loading '" + MAVEN_WRAPPER_PROPERTIES_PATH + "'");
67 | } finally {
68 | try {
69 | if (mavenWrapperPropertyFileInputStream != null) {
70 | mavenWrapperPropertyFileInputStream.close();
71 | }
72 | } catch (IOException e) {
73 | // Ignore ...
74 | }
75 | }
76 | }
77 | System.out.println("- Downloading from: " + url);
78 |
79 | File outputFile = new File(baseDirectory.getAbsolutePath(), MAVEN_WRAPPER_JAR_PATH);
80 | if (!outputFile.getParentFile().exists()) {
81 | if (!outputFile.getParentFile().mkdirs()) {
82 | System.out.println(
83 | "- ERROR creating output directory '" + outputFile.getParentFile().getAbsolutePath() + "'");
84 | }
85 | }
86 | System.out.println("- Downloading to: " + outputFile.getAbsolutePath());
87 | try {
88 | downloadFileFromURL(url, outputFile);
89 | System.out.println("Done");
90 | System.exit(0);
91 | } catch (Throwable e) {
92 | System.out.println("- Error downloading");
93 | e.printStackTrace();
94 | System.exit(1);
95 | }
96 | }
97 |
98 | private static void downloadFileFromURL(String urlString, File destination) throws Exception {
99 | if (System.getenv("MVNW_USERNAME") != null && System.getenv("MVNW_PASSWORD") != null) {
100 | String username = System.getenv("MVNW_USERNAME");
101 | char[] password = System.getenv("MVNW_PASSWORD").toCharArray();
102 | Authenticator.setDefault(new Authenticator() {
103 | @Override
104 | protected PasswordAuthentication getPasswordAuthentication() {
105 | return new PasswordAuthentication(username, password);
106 | }
107 | });
108 | }
109 | URL website = new URL(urlString);
110 | ReadableByteChannel rbc;
111 | rbc = Channels.newChannel(website.openStream());
112 | FileOutputStream fos = new FileOutputStream(destination);
113 | fos.getChannel().transferFrom(rbc, 0, Long.MAX_VALUE);
114 | fos.close();
115 | rbc.close();
116 | }
117 |
118 | }
119 |
--------------------------------------------------------------------------------
/7.0/secure-rsocket-client/.mvn/wrapper/maven-wrapper.jar:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/joshlong/reactive-spring-livelessons-2e/f10c568102d0634a050639973ba99f632580392f/7.0/secure-rsocket-client/.mvn/wrapper/maven-wrapper.jar
--------------------------------------------------------------------------------
/7.0/secure-rsocket-client/.mvn/wrapper/maven-wrapper.properties:
--------------------------------------------------------------------------------
1 | distributionUrl=https://repo.maven.apache.org/maven2/org/apache/maven/apache-maven/3.6.2/apache-maven-3.6.2-bin.zip
2 | wrapperUrl=https://repo.maven.apache.org/maven2/io/takari/maven-wrapper/0.5.5/maven-wrapper-0.5.5.jar
3 |
--------------------------------------------------------------------------------
/7.0/secure-rsocket-client/HELP.md:
--------------------------------------------------------------------------------
1 | # Getting Started
2 |
3 | ### Reference Documentation
4 | For further reference, please consider the following sections:
5 |
6 | * [Official Apache Maven documentation](https://maven.apache.org/guides/index.html)
7 | * [Spring Boot Maven Plugin Reference Guide](https://docs.spring.io/spring-boot/docs/2.2.2.RELEASE/maven-plugin/)
8 |
9 |
--------------------------------------------------------------------------------
/7.0/secure-rsocket-client/pom.xml:
--------------------------------------------------------------------------------
1 |
2 |
4 | 4.0.0
5 |
6 | org.springframework.boot
7 | spring-boot-starter-parent
8 | 2.2.2.RELEASE
9 |
10 |
11 | com.example
12 | secure-rsocket-client
13 | 0.0.1-SNAPSHOT
14 | rsocket-client
15 | Demo project for Spring Boot
16 |
17 |
18 | Hoxton.RELEASE
19 |
20 | 13
21 |
22 |
23 |
24 |
25 |
26 |
27 | org.springframework.security
28 | spring-security-messaging
29 |
30 |
31 | org.springframework.boot
32 | spring-boot-starter-security
33 |
34 |
35 | org.springframework.security
36 | spring-security-rsocket
37 |
38 |
39 |
40 | org.springframework.boot
41 | spring-boot-starter-rsocket
42 |
43 |
44 |
45 | org.projectlombok
46 | lombok
47 | true
48 |
49 |
50 | org.springframework.boot
51 | spring-boot-starter-test
52 | test
53 |
54 |
55 | org.junit.vintage
56 | junit-vintage-engine
57 |
58 |
59 |
60 |
61 | io.projectreactor
62 | reactor-test
63 | test
64 |
65 |
66 |
67 |
68 |
69 |
70 | org.springframework.boot
71 | spring-boot-maven-plugin
72 |
73 |
74 |
75 |
76 |
77 |
--------------------------------------------------------------------------------
/7.0/secure-rsocket-client/src/main/java/com/example/rsocketclient/RsocketClientApplication.java:
--------------------------------------------------------------------------------
1 | package com.example.rsocketclient;
2 |
3 | import lombok.*;
4 | import lombok.extern.log4j.Log4j2;
5 | import org.springframework.boot.SpringApplication;
6 | import org.springframework.boot.autoconfigure.SpringBootApplication;
7 | import org.springframework.boot.context.event.ApplicationReadyEvent;
8 | import org.springframework.boot.rsocket.messaging.RSocketStrategiesCustomizer;
9 | import org.springframework.context.annotation.Bean;
10 | import org.springframework.context.event.EventListener;
11 | import org.springframework.messaging.rsocket.RSocketRequester;
12 | import org.springframework.security.rsocket.metadata.BasicAuthenticationEncoder;
13 | import org.springframework.security.rsocket.metadata.UsernamePasswordMetadata;
14 | import org.springframework.stereotype.Component;
15 |
16 | import static org.springframework.security.rsocket.metadata.UsernamePasswordMetadata.BASIC_AUTHENTICATION_MIME_TYPE;
17 |
18 | @SpringBootApplication
19 | public class RsocketClientApplication {
20 |
21 | @Bean
22 | RSocketStrategiesCustomizer rSocketStrategiesCustomizer() {
23 | return strategies -> strategies.encoder(new BasicAuthenticationEncoder());
24 | }
25 |
26 | @Bean
27 | RSocketRequester rSocketRequester(RSocketRequester.Builder builder) {
28 | return builder.connectTcp("localhost", 7002).block();
29 | }
30 |
31 | @SneakyThrows
32 | public static void main(String[] args) {
33 | SpringApplication.run(RsocketClientApplication.class, args);
34 | System.in.read();
35 | }
36 |
37 | }
38 |
39 | @Component
40 | @Log4j2
41 | @RequiredArgsConstructor
42 | class Client {
43 |
44 | private final RSocketRequester rSocketRequester;
45 |
46 | @EventListener(ApplicationReadyEvent.class)
47 | public void ready() {
48 | var credentials = new UsernamePasswordMetadata("user", "password");
49 | this.rSocketRequester
50 | .route("greetings.1")
51 | .metadata(credentials, BASIC_AUTHENTICATION_MIME_TYPE)
52 | .retrieveFlux(GreetingResponse.class)
53 | .subscribe(log::info);
54 | }
55 | }
56 |
57 | @Data
58 | @AllArgsConstructor
59 | @NoArgsConstructor
60 | class GreetingRequest {
61 | private String name;
62 | }
63 |
64 | @Data
65 | @AllArgsConstructor
66 | @NoArgsConstructor
67 | class GreetingResponse {
68 | private String message;
69 | }
--------------------------------------------------------------------------------
/7.0/secure-rsocket-client/src/main/resources/application.properties:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/7.0/secure-rsocket-client/src/test/java/com/example/rsocketclient/RsocketClientApplicationTests.java:
--------------------------------------------------------------------------------
1 | package com.example.rsocketclient;
2 |
3 | import org.junit.jupiter.api.Test;
4 | import org.springframework.boot.test.context.SpringBootTest;
5 |
6 | @SpringBootTest
7 | class RsocketClientApplicationTests {
8 |
9 | @Test
10 | void contextLoads() {
11 | }
12 |
13 | }
14 |
--------------------------------------------------------------------------------
/7.0/secure-rsocket-service/.mvn/wrapper/maven-wrapper.jar:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/joshlong/reactive-spring-livelessons-2e/f10c568102d0634a050639973ba99f632580392f/7.0/secure-rsocket-service/.mvn/wrapper/maven-wrapper.jar
--------------------------------------------------------------------------------
/7.0/secure-rsocket-service/.mvn/wrapper/maven-wrapper.properties:
--------------------------------------------------------------------------------
1 | distributionUrl=https://repo.maven.apache.org/maven2/org/apache/maven/apache-maven/3.6.2/apache-maven-3.6.2-bin.zip
2 | wrapperUrl=https://repo.maven.apache.org/maven2/io/takari/maven-wrapper/0.5.5/maven-wrapper-0.5.5.jar
3 |
--------------------------------------------------------------------------------
/7.0/secure-rsocket-service/HELP.md:
--------------------------------------------------------------------------------
1 | # Getting Started
2 |
3 | ### Reference Documentation
4 | For further reference, please consider the following sections:
5 |
6 | * [Official Apache Maven documentation](https://maven.apache.org/guides/index.html)
7 | * [Spring Boot Maven Plugin Reference Guide](https://docs.spring.io/spring-boot/docs/2.2.2.RELEASE/maven-plugin/)
8 |
9 |
--------------------------------------------------------------------------------
/7.0/secure-rsocket-service/pom.xml:
--------------------------------------------------------------------------------
1 |
2 |
4 | 4.0.0
5 |
6 | org.springframework.boot
7 | spring-boot-starter-parent
8 | 2.2.2.RELEASE
9 |
10 |
11 | com.example
12 | secure-rsocket-service
13 | 0.0.1-SNAPSHOT
14 | rsocket-service
15 | Demo project for Spring Boot
16 |
17 |
18 | 13
19 |
20 |
21 |
22 |
23 | org.springframework.security
24 | spring-security-messaging
25 |
26 |
27 | org.springframework.boot
28 | spring-boot-starter-security
29 |
30 |
31 | org.springframework.security
32 | spring-security-rsocket
33 |
34 |
35 |
36 | org.springframework.boot
37 | spring-boot-starter-rsocket
38 |
39 |
40 |
41 | org.projectlombok
42 | lombok
43 | true
44 |
45 |
46 | org.springframework.boot
47 | spring-boot-starter-test
48 | test
49 |
50 |
51 | org.junit.vintage
52 | junit-vintage-engine
53 |
54 |
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 |
--------------------------------------------------------------------------------
/7.0/secure-rsocket-service/src/main/java/com/example/rsocketservice/RsocketServiceApplication.java:
--------------------------------------------------------------------------------
1 | package com.example.rsocketservice;
2 |
3 | import lombok.AllArgsConstructor;
4 | import lombok.Data;
5 | import lombok.NoArgsConstructor;
6 | import lombok.extern.log4j.Log4j2;
7 | import org.springframework.boot.SpringApplication;
8 | import org.springframework.boot.autoconfigure.SpringBootApplication;
9 | import org.springframework.context.annotation.Bean;
10 | import org.springframework.context.annotation.Configuration;
11 | import org.springframework.messaging.handler.annotation.DestinationVariable;
12 | import org.springframework.messaging.handler.annotation.MessageExceptionHandler;
13 | import org.springframework.messaging.handler.annotation.MessageMapping;
14 | import org.springframework.security.config.Customizer;
15 | import org.springframework.security.config.annotation.rsocket.EnableRSocketSecurity;
16 | import org.springframework.security.config.annotation.rsocket.RSocketSecurity;
17 | import org.springframework.security.core.annotation.AuthenticationPrincipal;
18 | import org.springframework.security.core.annotation.CurrentSecurityContext;
19 | import org.springframework.security.core.context.ReactiveSecurityContextHolder;
20 | import org.springframework.security.core.context.SecurityContext;
21 | import org.springframework.security.core.userdetails.MapReactiveUserDetailsService;
22 | import org.springframework.security.core.userdetails.User;
23 | import org.springframework.security.core.userdetails.UserDetails;
24 | import org.springframework.security.rsocket.core.PayloadSocketAcceptorInterceptor;
25 | import org.springframework.stereotype.Controller;
26 | import reactor.core.publisher.Flux;
27 | import reactor.core.publisher.Mono;
28 |
29 | import java.security.Principal;
30 | import java.time.Duration;
31 | import java.time.Instant;
32 | import java.util.stream.Stream;
33 |
34 | @SpringBootApplication
35 | public class RsocketServiceApplication {
36 |
37 | public static void main(String[] args) {
38 | SpringApplication.run(RsocketServiceApplication.class, args);
39 | }
40 |
41 | }
42 |
43 | @Log4j2
44 | @Controller
45 | class GreetingService {
46 |
47 | @MessageExceptionHandler(IllegalArgumentException.class)
48 | Mono onIllegalArgumentException(IllegalArgumentException iae) {
49 | log.error(iae);
50 | return Mono.just("OoOps!");
51 | }
52 |
53 | @MessageMapping("greetings.{timeInSeconds}")
54 | Flux greet(@DestinationVariable int timeInSeconds) {
55 |
56 | return ReactiveSecurityContextHolder
57 | .getContext()
58 | .map(SecurityContext::getAuthentication)
59 | .map(au -> (User) au.getPrincipal())
60 | .map(User::getUsername)
61 | .flatMapMany(str -> Flux
62 | .fromStream(Stream.generate(() -> new GreetingResponse("Hello " + str + " @ " + Instant.now() + "!")))
63 | .delayElements(Duration.ofSeconds(timeInSeconds)));
64 | }
65 | }
66 |
67 | @Configuration
68 | @EnableRSocketSecurity
69 | class RSocketSecurityConfiguration {
70 |
71 | @Bean
72 | PayloadSocketAcceptorInterceptor rsocketInterceptor(RSocketSecurity rsocket) {
73 | return rsocket
74 | .authorizePayload(authorize ->
75 | authorize
76 | .route("greeting*").authenticated()
77 | .anyExchange().permitAll()
78 | )
79 | .basicAuthentication(Customizer.withDefaults())
80 | .build();
81 | }
82 |
83 | @Bean
84 | MapReactiveUserDetailsService userDetailsService() {
85 | UserDetails user = User.withDefaultPasswordEncoder()
86 | .username("user")
87 | .password("password")
88 | .roles("USER")
89 | .build();
90 | return new MapReactiveUserDetailsService(user);
91 | }
92 |
93 | }
94 |
95 | @Data
96 | @AllArgsConstructor
97 | @NoArgsConstructor
98 | class GreetingRequest {
99 | private String name;
100 | }
101 |
102 | @Data
103 | @AllArgsConstructor
104 | @NoArgsConstructor
105 | class GreetingResponse {
106 | private String message;
107 | }
--------------------------------------------------------------------------------
/7.0/secure-rsocket-service/src/main/resources/application.properties:
--------------------------------------------------------------------------------
1 | spring.rsocket.server.port=7002
2 |
--------------------------------------------------------------------------------
/7.0/secure-rsocket-service/src/test/java/com/example/rsocketservice/RsocketServiceApplicationTests.java:
--------------------------------------------------------------------------------
1 | package com.example.rsocketservice;
2 |
3 | import org.junit.jupiter.api.Test;
4 | import org.springframework.boot.test.context.SpringBootTest;
5 |
6 | @SpringBootTest
7 | class RsocketServiceApplicationTests {
8 |
9 | @Test
10 | void contextLoads() {
11 | }
12 |
13 | }
14 |
--------------------------------------------------------------------------------
/8.0/http/http-gateway/.mvn/wrapper/maven-wrapper.jar:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/joshlong/reactive-spring-livelessons-2e/f10c568102d0634a050639973ba99f632580392f/8.0/http/http-gateway/.mvn/wrapper/maven-wrapper.jar
--------------------------------------------------------------------------------
/8.0/http/http-gateway/.mvn/wrapper/maven-wrapper.properties:
--------------------------------------------------------------------------------
1 | distributionUrl=https://repo.maven.apache.org/maven2/org/apache/maven/apache-maven/3.6.2/apache-maven-3.6.2-bin.zip
2 | wrapperUrl=https://repo.maven.apache.org/maven2/io/takari/maven-wrapper/0.5.5/maven-wrapper-0.5.5.jar
3 |
--------------------------------------------------------------------------------
/8.0/http/http-gateway/HELP.md:
--------------------------------------------------------------------------------
1 | # Getting Started
2 |
3 | ### Reference Documentation
4 | For further reference, please consider the following sections:
5 |
6 | * [Official Apache Maven documentation](https://maven.apache.org/guides/index.html)
7 | * [Spring Boot Maven Plugin Reference Guide](https://docs.spring.io/spring-boot/docs/2.2.2.RELEASE/maven-plugin/)
8 | * [Spring Data Reactive Redis](https://docs.spring.io/spring-boot/docs/2.2.2.RELEASE/reference/htmlsingle/#boot-features-redis)
9 | * [Spring Security](https://docs.spring.io/spring-boot/docs/2.2.2.RELEASE/reference/htmlsingle/#boot-features-security)
10 |
11 | ### Guides
12 | The following guides illustrate how to use some features concretely:
13 |
14 | * [Using Spring Cloud Gateway](https://github.com/spring-cloud-samples/spring-cloud-gateway-sample)
15 | * [Messaging with Redis](https://spring.io/guides/gs/messaging-redis/)
16 | * [Securing a Web Application](https://spring.io/guides/gs/securing-web/)
17 | * [Spring Boot and OAuth2](https://spring.io/guides/tutorials/spring-boot-oauth2/)
18 | * [Authenticating a User with LDAP](https://spring.io/guides/gs/authenticating-ldap/)
19 |
20 |
--------------------------------------------------------------------------------
/8.0/http/http-gateway/pom.xml:
--------------------------------------------------------------------------------
1 |
2 |
4 | 4.0.0
5 |
6 | org.springframework.boot
7 | spring-boot-starter-parent
8 | 2.2.2.RELEASE
9 |
10 |
11 | com.example
12 | http-gateway
13 | 0.0.1-SNAPSHOT
14 | http-gateway
15 | Demo project for Spring Boot
16 |
17 |
18 | 13
19 | Hoxton.RELEASE
20 |
21 |
22 |
23 |
24 | org.springframework.boot
25 | spring-boot-starter-data-redis-reactive
26 |
27 |
28 | org.springframework.boot
29 | spring-boot-starter-security
30 |
31 |
32 | org.springframework.boot
33 | spring-boot-starter-webflux
34 |
35 |
36 | org.springframework.cloud
37 | spring-cloud-starter-gateway
38 |
39 |
40 |
41 | org.projectlombok
42 | lombok
43 | true
44 |
45 |
46 | org.springframework.boot
47 | spring-boot-starter-test
48 | test
49 |
50 |
51 | org.junit.vintage
52 | junit-vintage-engine
53 |
54 |
55 |
56 |
57 | io.projectreactor
58 | reactor-test
59 | test
60 |
61 |
62 | org.springframework.security
63 | spring-security-test
64 | test
65 |
66 |
67 |
68 |
69 |
70 |
71 | org.springframework.cloud
72 | spring-cloud-dependencies
73 | ${spring-cloud.version}
74 | pom
75 | import
76 |
77 |
78 |
79 |
80 |
81 |
82 |
83 | org.springframework.boot
84 | spring-boot-maven-plugin
85 |
86 |
87 |
88 |
89 |
90 |
--------------------------------------------------------------------------------
/8.0/http/http-gateway/src/main/java/com/example/httpgateway/HttpGatewayApplication.java:
--------------------------------------------------------------------------------
1 | package com.example.httpgateway;
2 |
3 | import org.springframework.boot.SpringApplication;
4 | import org.springframework.boot.autoconfigure.SpringBootApplication;
5 | import org.springframework.cloud.gateway.filter.ratelimit.KeyResolver;
6 | import org.springframework.cloud.gateway.filter.ratelimit.PrincipalNameKeyResolver;
7 | import org.springframework.cloud.gateway.filter.ratelimit.RedisRateLimiter;
8 | import org.springframework.cloud.gateway.route.RouteLocator;
9 | import org.springframework.cloud.gateway.route.builder.RouteLocatorBuilder;
10 | import org.springframework.context.annotation.Bean;
11 | import org.springframework.http.HttpHeaders;
12 | import org.springframework.security.config.Customizer;
13 | import org.springframework.security.config.web.server.ServerHttpSecurity;
14 | import org.springframework.security.core.userdetails.MapReactiveUserDetailsService;
15 | import org.springframework.security.core.userdetails.User;
16 | import org.springframework.security.web.server.SecurityWebFilterChain;
17 | import org.springframework.web.server.ServerWebExchange;
18 | import reactor.core.publisher.Mono;
19 |
20 | import java.security.Principal;
21 | import java.util.function.Predicate;
22 |
23 | @SpringBootApplication
24 | public class HttpGatewayApplication {
25 |
26 | @Bean
27 | RedisRateLimiter redisRateLimiter() {
28 | return new RedisRateLimiter(5, 7);
29 | }
30 |
31 | @Bean
32 | SecurityWebFilterChain authorization(ServerHttpSecurity http) {
33 | return http
34 | .csrf(ServerHttpSecurity.CsrfSpec::disable)
35 | .httpBasic(Customizer.withDefaults())
36 | .authorizeExchange(x -> x.pathMatchers("/proxy").authenticated())
37 | .build();
38 | }
39 |
40 | @Bean
41 | MapReactiveUserDetailsService authentication() {
42 | return new MapReactiveUserDetailsService(
43 | User.withDefaultPasswordEncoder().username("user").password("password").roles("USER").build());
44 | }
45 |
46 | @Bean
47 | RouteLocator gateway(RouteLocatorBuilder rlb) {
48 | return rlb
49 | .routes()
50 | .route(routeSpec -> routeSpec
51 | .host("*.spring.io").and().path("/proxy")
52 | .filters(filterSpec -> filterSpec
53 | .setPath("/reservations")
54 | .addResponseHeader(HttpHeaders.ACCESS_CONTROL_ALLOW_ORIGIN, "*")
55 | .requestRateLimiter(rl -> rl
56 | .setRateLimiter(redisRateLimiter())
57 | )
58 | )
59 | .uri("http://localhost:8080/")
60 | )
61 | .build();
62 | }
63 |
64 | public static void main(String[] args) {
65 | SpringApplication.run(HttpGatewayApplication.class, args);
66 | }
67 |
68 | }
69 |
--------------------------------------------------------------------------------
/8.0/http/http-gateway/src/main/resources/application.properties:
--------------------------------------------------------------------------------
1 | server.port=9999
2 |
--------------------------------------------------------------------------------
/8.0/http/http-gateway/src/test/java/com/example/httpgateway/HttpGatewayApplicationTests.java:
--------------------------------------------------------------------------------
1 | package com.example.httpgateway;
2 |
3 | import org.junit.jupiter.api.Test;
4 | import org.springframework.boot.test.context.SpringBootTest;
5 |
6 | @SpringBootTest
7 | class HttpGatewayApplicationTests {
8 |
9 | @Test
10 | void contextLoads() {
11 | }
12 |
13 | }
14 |
--------------------------------------------------------------------------------
/8.0/http/reservation-service/.mvn/wrapper/maven-wrapper.jar:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/joshlong/reactive-spring-livelessons-2e/f10c568102d0634a050639973ba99f632580392f/8.0/http/reservation-service/.mvn/wrapper/maven-wrapper.jar
--------------------------------------------------------------------------------
/8.0/http/reservation-service/.mvn/wrapper/maven-wrapper.properties:
--------------------------------------------------------------------------------
1 | distributionUrl=https://repo.maven.apache.org/maven2/org/apache/maven/apache-maven/3.6.2/apache-maven-3.6.2-bin.zip
2 | wrapperUrl=https://repo.maven.apache.org/maven2/io/takari/maven-wrapper/0.5.5/maven-wrapper-0.5.5.jar
3 |
--------------------------------------------------------------------------------
/8.0/http/reservation-service/HELP.md:
--------------------------------------------------------------------------------
1 | # Getting Started
2 |
3 | ### Reference Documentation
4 | For further reference, please consider the following sections:
5 |
6 | * [Official Apache Maven documentation](https://maven.apache.org/guides/index.html)
7 | * [Spring Boot Maven Plugin Reference Guide](https://docs.spring.io/spring-boot/docs/2.2.2.RELEASE/maven-plugin/)
8 | * [Spring Data R2DBC [Experimental]](https://docs.spring.io/spring-data/r2dbc/docs/1.0.x/reference/html/#reference)
9 |
10 | ### Guides
11 | The following guides illustrate how to use some features concretely:
12 |
13 | * [R2DBC example](https://github.com/spring-projects-experimental/spring-boot-r2dbc/tree/master/spring-boot-example-h2)
14 |
15 | ### Additional Links
16 | These additional references should also help you:
17 |
18 | * [R2DBC Homepage](https://r2dbc.io)
19 |
20 |
--------------------------------------------------------------------------------
/8.0/http/reservation-service/pom.xml:
--------------------------------------------------------------------------------
1 |
2 |
4 | 4.0.0
5 |
6 | org.springframework.boot
7 | spring-boot-starter-parent
8 | 2.2.2.RELEASE
9 |
10 |
11 | com.example
12 | reservation-service
13 | 0.0.1-SNAPSHOT
14 | reservation-service
15 | Demo project for Spring Boot
16 |
17 |
18 | 1.8
19 |
20 |
21 |
22 |
23 | org.springframework.boot.experimental
24 | spring-boot-starter-data-r2dbc
25 |
26 |
27 | org.springframework.boot
28 | spring-boot-starter-webflux
29 |
30 |
31 |
32 | io.r2dbc
33 | r2dbc-postgresql
34 | runtime
35 |
36 |
37 | org.postgresql
38 | postgresql
39 | runtime
40 |
41 |
42 | org.projectlombok
43 | lombok
44 | true
45 |
46 |
47 | org.springframework.boot
48 | spring-boot-starter-test
49 | test
50 |
51 |
52 | org.junit.vintage
53 | junit-vintage-engine
54 |
55 |
56 |
57 |
58 | org.springframework.boot.experimental
59 | spring-boot-test-autoconfigure-r2dbc
60 | test
61 |
62 |
63 | io.projectreactor
64 | reactor-test
65 | test
66 |
67 |
68 |
69 |
70 |
71 |
72 | org.springframework.boot.experimental
73 | spring-boot-bom-r2dbc
74 | 0.1.0.M3
75 | pom
76 | import
77 |
78 |
79 |
80 |
81 |
82 |
83 |
84 | org.springframework.boot
85 | spring-boot-maven-plugin
86 |
87 |
88 |
89 |
90 |
91 |
92 | spring-milestones
93 | Spring Milestones
94 | https://repo.spring.io/milestone
95 |
96 |
97 |
98 |
99 |
--------------------------------------------------------------------------------
/8.0/http/reservation-service/src/main/java/com/example/reservationservice/ReservationServiceApplication.java:
--------------------------------------------------------------------------------
1 | package com.example.reservationservice;
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.context.annotation.Bean;
9 | import org.springframework.context.event.EventListener;
10 | import org.springframework.data.annotation.Id;
11 | import org.springframework.data.repository.reactive.ReactiveCrudRepository;
12 | import org.springframework.web.reactive.function.server.HandlerFunction;
13 | import org.springframework.web.reactive.function.server.RouterFunction;
14 | import org.springframework.web.reactive.function.server.ServerRequest;
15 | import org.springframework.web.reactive.function.server.ServerResponse;
16 | import reactor.core.publisher.Mono;
17 |
18 | import static org.springframework.web.reactive.function.server.RouterFunctions.route;
19 | import static org.springframework.web.reactive.function.server.ServerResponse.ok;
20 |
21 | @SpringBootApplication
22 | public class ReservationServiceApplication {
23 |
24 | public static void main(String[] args) {
25 | SpringApplication.run(ReservationServiceApplication.class, args);
26 | }
27 |
28 | @Bean
29 | RouterFunction routes(ReservationRepository rr) {
30 | return route()
31 | .GET("/reservations", r -> ok().body(rr.findAll(), Reservation.class))
32 | .build();
33 | }
34 | }
35 |
36 | interface ReservationRepository extends ReactiveCrudRepository {
37 | }
38 |
39 | @Data
40 | @AllArgsConstructor
41 | @NoArgsConstructor
42 | class Reservation {
43 | @Id
44 | private Integer id;
45 | private String name;
46 | }
47 |
48 |
--------------------------------------------------------------------------------
/8.0/http/reservation-service/src/main/resources/application.properties:
--------------------------------------------------------------------------------
1 | spring.r2dbc.url=r2dbc:postgres://localhost/orders
2 | spring.r2dbc.username=orders
3 | spring.r2dbc.password=orders
4 |
--------------------------------------------------------------------------------
/8.0/http/reservation-service/src/test/java/com/example/reservationservice/ReservationServiceApplicationTests.java:
--------------------------------------------------------------------------------
1 | package com.example.reservationservice;
2 |
3 | import org.junit.jupiter.api.Test;
4 | import org.springframework.boot.test.context.SpringBootTest;
5 |
6 | @SpringBootTest
7 | class ReservationServiceApplicationTests {
8 |
9 | @Test
10 | void contextLoads() {
11 | }
12 |
13 | }
14 |
--------------------------------------------------------------------------------
/8.0/rsocket-gateway-deps.md:
--------------------------------------------------------------------------------
1 |
2 | spring.rsocket.server.port=7002
3 |
4 |
5 | org.springframework.cloud
6 | spring-cloud-rsocket-dependencies
7 | 0.2.0.BUILD-SNAPSHOT
8 | pom
9 | import
10 |
11 |
12 |
13 |
14 | org.springframework.cloud
15 | spring-cloud-rsocket-broker
16 |
17 |
18 |
19 |
20 | org.springframework.cloud
21 | spring-cloud-rsocket-client
22 |
23 |
24 | spring.rsocket.server.port=8888
25 | server.port=8081
26 | spring.application.name=greetings-service
27 | spring.cloud.gateway.rsocket.client.service-name=greetings-service
28 | spring.cloud.gateway.rsocket.client.route-id=3
29 | spring.cloud.gateway.rsocket.client.broker.host=localhost
30 | spring.cloud.gateway.rsocket.client.broker.port=7002
31 |
32 |
33 | @Bean
34 | ApplicationListener> gatewayClient(BrokerClient client) {
35 | return event ->
36 | event
37 | .getPayload()
38 | .route("greetings")
39 | .metadata(client.forwarding("greetings-service"))
40 | .data(new GreetingRequest("World"))
41 | .retrieveFlux(GreetingResponse.class)
42 | .subscribe(gr -> log.info("gateway rsocket client: " + gr.getMessage()));
43 | }
--------------------------------------------------------------------------------
/8.0/rsocket/greetings-client/.mvn/wrapper/maven-wrapper.jar:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/joshlong/reactive-spring-livelessons-2e/f10c568102d0634a050639973ba99f632580392f/8.0/rsocket/greetings-client/.mvn/wrapper/maven-wrapper.jar
--------------------------------------------------------------------------------
/8.0/rsocket/greetings-client/.mvn/wrapper/maven-wrapper.properties:
--------------------------------------------------------------------------------
1 | distributionUrl=https://repo.maven.apache.org/maven2/org/apache/maven/apache-maven/3.6.2/apache-maven-3.6.2-bin.zip
2 | wrapperUrl=https://repo.maven.apache.org/maven2/io/takari/maven-wrapper/0.5.5/maven-wrapper-0.5.5.jar
3 |
--------------------------------------------------------------------------------
/8.0/rsocket/greetings-client/HELP.md:
--------------------------------------------------------------------------------
1 | # Getting Started
2 |
3 | ### Reference Documentation
4 | For further reference, please consider the following sections:
5 |
6 | * [Official Apache Maven documentation](https://maven.apache.org/guides/index.html)
7 | * [Spring Boot Maven Plugin Reference Guide](https://docs.spring.io/spring-boot/docs/2.2.3.BUILD-SNAPSHOT/maven-plugin/)
8 |
9 |
--------------------------------------------------------------------------------
/8.0/rsocket/greetings-client/pom.xml:
--------------------------------------------------------------------------------
1 |
2 |
4 | 4.0.0
5 |
6 | org.springframework.boot
7 | spring-boot-starter-parent
8 | 2.2.3.BUILD-SNAPSHOT
9 |
10 |
11 | com.example
12 | greetings-client
13 | 0.0.1-SNAPSHOT
14 | greetings-client
15 | Demo project for Spring Boot
16 |
17 |
18 | Hoxton.BUILD-SNAPSHOT
19 | 13
20 |
21 |
22 |
23 |
24 | import
25 | pom
26 | 0.2.0.BUILD-SNAPSHOT
27 | org.springframework.cloud
28 | spring-cloud-rsocket-dependencies
29 |
30 |
31 | org.springframework.cloud
32 | spring-cloud-dependencies
33 | ${spring-cloud.version}
34 | pom
35 | import
36 |
37 |
38 |
39 |
40 |
41 |
42 | org.springframework.boot
43 | spring-boot-starter-actuator
44 |
45 |
46 | org.springframework.boot
47 | spring-boot-starter-rsocket
48 |
49 |
50 | org.springframework.cloud
51 | spring-cloud-rsocket-client
52 |
53 |
54 | org.projectlombok
55 | lombok
56 | true
57 |
58 |
59 | org.springframework.boot
60 | spring-boot-starter-test
61 | test
62 |
63 |
64 | org.junit.vintage
65 | junit-vintage-engine
66 |
67 |
68 |
69 |
70 | io.projectreactor
71 | reactor-test
72 | test
73 |
74 |
75 |
76 |
77 |
78 |
79 | org.springframework.boot
80 | spring-boot-maven-plugin
81 |
82 |
83 |
84 |
85 |
86 |
87 | spring-milestones
88 | Spring Milestones
89 | https://repo.spring.io/milestone
90 |
91 |
92 | spring-snapshots
93 | Spring Snapshots
94 | https://repo.spring.io/snapshot
95 |
96 | true
97 |
98 |
99 |
100 |
101 |
102 | spring-milestones
103 | Spring Milestones
104 | https://repo.spring.io/milestone
105 |
106 |
107 | spring-snapshots
108 | Spring Snapshots
109 | https://repo.spring.io/snapshot
110 |
111 | true
112 |
113 |
114 |
115 |
116 |
117 |
--------------------------------------------------------------------------------
/8.0/rsocket/greetings-client/src/main/java/com/example/greetingsclient/GreetingsClientApplication.java:
--------------------------------------------------------------------------------
1 | package com.example.greetingsclient;
2 |
3 | import lombok.AllArgsConstructor;
4 | import lombok.Data;
5 | import lombok.NoArgsConstructor;
6 | import lombok.RequiredArgsConstructor;
7 | import lombok.extern.log4j.Log4j2;
8 | import org.springframework.boot.SpringApplication;
9 | import org.springframework.boot.autoconfigure.SpringBootApplication;
10 | import org.springframework.cloud.gateway.rsocket.client.BrokerClient;
11 | import org.springframework.context.PayloadApplicationEvent;
12 | import org.springframework.context.event.EventListener;
13 | import org.springframework.messaging.rsocket.RSocketRequester;
14 | import org.springframework.stereotype.Component;
15 |
16 | @SpringBootApplication
17 | public class GreetingsClientApplication {
18 |
19 | public static void main(String[] args) {
20 | SpringApplication.run(GreetingsClientApplication.class, args);
21 | }
22 | }
23 |
24 | @Data
25 | @AllArgsConstructor
26 | @NoArgsConstructor
27 | class GreetingResponse {
28 | private String message;
29 | }
30 |
31 | @Data
32 | @AllArgsConstructor
33 | @NoArgsConstructor
34 | class GreetingRequest {
35 | private String name;
36 | }
37 |
38 | @Log4j2
39 | @Component
40 | @RequiredArgsConstructor
41 | class RSocketGatewayClient {
42 |
43 | private final BrokerClient client;
44 |
45 | @EventListener
46 | public void gatewayRsocketClient(PayloadApplicationEvent event) {
47 | event
48 | .getPayload()
49 | .route("greetings.{time}", 2)
50 | .metadata(client.forwarding("greetings-service"))
51 | .data(new GreetingRequest("Livelessons"))
52 | .retrieveFlux(GreetingResponse.class)
53 | .subscribe(gr -> log.info(gr.toString()));
54 | }
55 |
56 |
57 | }
58 |
59 |
60 |
--------------------------------------------------------------------------------
/8.0/rsocket/greetings-client/src/main/resources/application.properties:
--------------------------------------------------------------------------------
1 | spring.rsocket.server.port=6000
2 | spring.application.name=greetings-client
3 | #
4 | spring.cloud.gateway.rsocket.client.service-name=${spring.application.name}
5 | spring.cloud.gateway.rsocket.client.route-id=5
6 | spring.cloud.gateway.rsocket.client.broker.port=9999
7 | spring.cloud.gateway.rsocket.client.broker.host=localhost
8 |
--------------------------------------------------------------------------------
/8.0/rsocket/greetings-client/src/test/java/com/example/greetingsservice/GreetingsServiceApplicationTests.java:
--------------------------------------------------------------------------------
1 | package com.example.greetingsservice;
2 |
3 | import org.junit.jupiter.api.Test;
4 | import org.springframework.boot.test.context.SpringBootTest;
5 |
6 | @SpringBootTest
7 | class GreetingsServiceApplicationTests {
8 |
9 | @Test
10 | void contextLoads() {
11 | }
12 |
13 | }
14 |
--------------------------------------------------------------------------------
/8.0/rsocket/greetings-service/.mvn/wrapper/maven-wrapper.jar:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/joshlong/reactive-spring-livelessons-2e/f10c568102d0634a050639973ba99f632580392f/8.0/rsocket/greetings-service/.mvn/wrapper/maven-wrapper.jar
--------------------------------------------------------------------------------
/8.0/rsocket/greetings-service/.mvn/wrapper/maven-wrapper.properties:
--------------------------------------------------------------------------------
1 | distributionUrl=https://repo.maven.apache.org/maven2/org/apache/maven/apache-maven/3.6.2/apache-maven-3.6.2-bin.zip
2 | wrapperUrl=https://repo.maven.apache.org/maven2/io/takari/maven-wrapper/0.5.5/maven-wrapper-0.5.5.jar
3 |
--------------------------------------------------------------------------------
/8.0/rsocket/greetings-service/HELP.md:
--------------------------------------------------------------------------------
1 | # Getting Started
2 |
3 | ### Reference Documentation
4 | For further reference, please consider the following sections:
5 |
6 | * [Official Apache Maven documentation](https://maven.apache.org/guides/index.html)
7 | * [Spring Boot Maven Plugin Reference Guide](https://docs.spring.io/spring-boot/docs/2.2.3.BUILD-SNAPSHOT/maven-plugin/)
8 |
9 |
--------------------------------------------------------------------------------
/8.0/rsocket/greetings-service/pom.xml:
--------------------------------------------------------------------------------
1 |
2 |
4 | 4.0.0
5 |
6 | org.springframework.boot
7 | spring-boot-starter-parent
8 | 2.2.3.BUILD-SNAPSHOT
9 |
10 |
11 | com.example
12 | greetings-service
13 | 0.0.1-SNAPSHOT
14 | greetings-service
15 | Demo project for Spring Boot
16 |
17 |
18 | Hoxton.BUILD-SNAPSHOT
19 | 13
20 |
21 |
22 |
23 |
24 | import
25 | pom
26 | 0.2.0.BUILD-SNAPSHOT
27 | org.springframework.cloud
28 | spring-cloud-rsocket-dependencies
29 |
30 |
31 | org.springframework.cloud
32 | spring-cloud-dependencies
33 | ${spring-cloud.version}
34 | pom
35 | import
36 |
37 |
38 |
39 |
40 |
41 |
42 | org.springframework.boot
43 | spring-boot-starter-actuator
44 |
45 |
46 | org.springframework.boot
47 | spring-boot-starter-rsocket
48 |
49 |
50 | org.springframework.cloud
51 | spring-cloud-rsocket-client
52 |
53 |
54 | org.projectlombok
55 | lombok
56 | true
57 |
58 |
59 | org.springframework.boot
60 | spring-boot-starter-test
61 | test
62 |
63 |
64 | org.junit.vintage
65 | junit-vintage-engine
66 |
67 |
68 |
69 |
70 | io.projectreactor
71 | reactor-test
72 | test
73 |
74 |
75 |
76 |
77 |
78 |
79 | org.springframework.boot
80 | spring-boot-maven-plugin
81 |
82 |
83 |
84 |
85 |
86 |
87 | spring-milestones
88 | Spring Milestones
89 | https://repo.spring.io/milestone
90 |
91 |
92 | spring-snapshots
93 | Spring Snapshots
94 | https://repo.spring.io/snapshot
95 |
96 | true
97 |
98 |
99 |
100 |
101 |
102 | spring-milestones
103 | Spring Milestones
104 | https://repo.spring.io/milestone
105 |
106 |
107 | spring-snapshots
108 | Spring Snapshots
109 | https://repo.spring.io/snapshot
110 |
111 | true
112 |
113 |
114 |
115 |
116 |
117 |
--------------------------------------------------------------------------------
/8.0/rsocket/greetings-service/src/main/java/com/example/greetingsservice/GreetingsServiceApplication.java:
--------------------------------------------------------------------------------
1 | package com.example.greetingsservice;
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.messaging.handler.annotation.DestinationVariable;
9 | import org.springframework.messaging.handler.annotation.MessageMapping;
10 | import org.springframework.stereotype.Controller;
11 | import reactor.core.publisher.Flux;
12 |
13 | import java.time.Duration;
14 | import java.time.Instant;
15 | import java.util.function.Supplier;
16 | import java.util.stream.Stream;
17 |
18 | @SpringBootApplication
19 | public class GreetingsServiceApplication {
20 |
21 | public static void main(String[] args) {
22 | SpringApplication.run(GreetingsServiceApplication.class, args);
23 | }
24 | }
25 |
26 | @Controller
27 | class GreetingsRSocketController {
28 |
29 | @MessageMapping("greetings.{timeInSeconds}")
30 | Flux greet(@DestinationVariable int timeInSeconds, GreetingRequest greetingRequest) {
31 | return Flux
32 | .fromStream(Stream.generate(() -> new GreetingResponse("Hello " + greetingRequest.getName() + " @ " + Instant.now() + "!")))
33 | .delayElements(Duration.ofSeconds(timeInSeconds));
34 | }
35 | }
36 |
37 | @Data
38 | @AllArgsConstructor
39 | @NoArgsConstructor
40 | class GreetingResponse {
41 | private String message;
42 | }
43 |
44 | @Data
45 | @AllArgsConstructor
46 | @NoArgsConstructor
47 | class GreetingRequest {
48 | private String name;
49 | }
--------------------------------------------------------------------------------
/8.0/rsocket/greetings-service/src/main/resources/application.properties:
--------------------------------------------------------------------------------
1 | spring.rsocket.server.port=8000
2 | spring.application.name=greetings-service
3 | #
4 | spring.cloud.gateway.rsocket.client.service-name=${spring.application.name}
5 | spring.cloud.gateway.rsocket.client.route-id=2
6 | spring.cloud.gateway.rsocket.client.broker.port=9999
7 | spring.cloud.gateway.rsocket.client.broker.host=localhost
8 |
--------------------------------------------------------------------------------
/8.0/rsocket/greetings-service/src/test/java/com/example/greetingsservice/GreetingsServiceApplicationTests.java:
--------------------------------------------------------------------------------
1 | package com.example.greetingsservice;
2 |
3 | import org.junit.jupiter.api.Test;
4 | import org.springframework.boot.test.context.SpringBootTest;
5 |
6 | @SpringBootTest
7 | class GreetingsServiceApplicationTests {
8 |
9 | @Test
10 | void contextLoads() {
11 | }
12 |
13 | }
14 |
--------------------------------------------------------------------------------
/8.0/rsocket/rsocket-gateway/.mvn/wrapper/maven-wrapper.jar:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/joshlong/reactive-spring-livelessons-2e/f10c568102d0634a050639973ba99f632580392f/8.0/rsocket/rsocket-gateway/.mvn/wrapper/maven-wrapper.jar
--------------------------------------------------------------------------------
/8.0/rsocket/rsocket-gateway/.mvn/wrapper/maven-wrapper.properties:
--------------------------------------------------------------------------------
1 | distributionUrl=https://repo.maven.apache.org/maven2/org/apache/maven/apache-maven/3.6.2/apache-maven-3.6.2-bin.zip
2 | wrapperUrl=https://repo.maven.apache.org/maven2/io/takari/maven-wrapper/0.5.5/maven-wrapper-0.5.5.jar
3 |
--------------------------------------------------------------------------------
/8.0/rsocket/rsocket-gateway/HELP.md:
--------------------------------------------------------------------------------
1 | # Getting Started
2 |
3 | ### Reference Documentation
4 | For further reference, please consider the following sections:
5 |
6 | * [Official Apache Maven documentation](https://maven.apache.org/guides/index.html)
7 | * [Spring Boot Maven Plugin Reference Guide](https://docs.spring.io/spring-boot/docs/2.2.2.RELEASE/maven-plugin/)
8 | * [Cloud Bootstrap](https://spring.io/projects/spring-cloud-commons)
9 | * [Spring Boot Actuator](https://docs.spring.io/spring-boot/docs/2.2.2.RELEASE/reference/htmlsingle/#production-ready)
10 |
11 | ### Guides
12 | The following guides illustrate how to use some features concretely:
13 |
14 | * [Building a RESTful Web Service with Spring Boot Actuator](https://spring.io/guides/gs/actuator-service/)
15 |
16 |
--------------------------------------------------------------------------------
/8.0/rsocket/rsocket-gateway/pom.xml:
--------------------------------------------------------------------------------
1 |
2 |
4 | 4.0.0
5 |
6 | org.springframework.boot
7 | spring-boot-starter-parent
8 | 2.2.2.RELEASE
9 |
10 |
11 | com.example
12 | rsocket-gateway
13 | 0.0.1-SNAPSHOT
14 | rsocket-gateway
15 | Demo project for Spring Boot
16 |
17 |
18 | 13
19 | Hoxton.RELEASE
20 |
21 |
22 |
23 |
24 | org.springframework.boot
25 | spring-boot-starter-actuator
26 |
27 |
28 | org.springframework.boot
29 | spring-boot-starter-rsocket
30 |
31 |
32 | org.springframework.cloud
33 | spring-cloud-starter
34 |
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 | io.projectreactor
49 | reactor-test
50 | test
51 |
52 |
53 | org.springframework.cloud
54 | spring-cloud-rsocket-broker
55 |
56 |
57 |
58 |
59 |
60 |
61 | import
62 | pom
63 | 0.2.0.BUILD-SNAPSHOT
64 | org.springframework.cloud
65 | spring-cloud-rsocket-dependencies
66 |
67 |
68 | org.springframework.cloud
69 | spring-cloud-dependencies
70 | ${spring-cloud.version}
71 | pom
72 | import
73 |
74 |
75 |
76 |
77 |
78 |
79 |
80 | org.springframework.boot
81 | spring-boot-maven-plugin
82 |
83 |
84 |
85 |
86 |
87 |
--------------------------------------------------------------------------------
/8.0/rsocket/rsocket-gateway/src/main/java/com/example/rsocketgateway/RsocketGatewayApplication.java:
--------------------------------------------------------------------------------
1 | package com.example.rsocketgateway;
2 |
3 | import org.springframework.boot.SpringApplication;
4 | import org.springframework.boot.autoconfigure.SpringBootApplication;
5 |
6 | @SpringBootApplication
7 | public class RsocketGatewayApplication {
8 |
9 | public static void main(String[] args) {
10 | SpringApplication.run(RsocketGatewayApplication.class, args);
11 | }
12 |
13 | }
14 |
--------------------------------------------------------------------------------
/8.0/rsocket/rsocket-gateway/src/main/resources/application.properties:
--------------------------------------------------------------------------------
1 | spring.rsocket.server.port=9999
2 |
--------------------------------------------------------------------------------
/8.0/rsocket/rsocket-gateway/src/test/java/com/example/rsocketgateway/RsocketGatewayApplicationTests.java:
--------------------------------------------------------------------------------
1 | package com.example.rsocketgateway;
2 |
3 | import org.junit.jupiter.api.Test;
4 | import org.springframework.boot.test.context.SpringBootTest;
5 |
6 | @SpringBootTest
7 | class RsocketGatewayApplicationTests {
8 |
9 | @Test
10 | void contextLoads() {
11 | }
12 |
13 | }
14 |
--------------------------------------------------------------------------------
/9.0/consumer/.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 |
--------------------------------------------------------------------------------
/9.0/consumer/.mvn/wrapper/MavenWrapperDownloader.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2012-2019 the original author or authors.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * https://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 | import java.net.*;
17 | import java.io.*;
18 | import java.nio.channels.*;
19 | import java.util.Properties;
20 |
21 | public class MavenWrapperDownloader {
22 |
23 | private static final String WRAPPER_VERSION = "0.5.5";
24 | /**
25 | * Default URL to download the maven-wrapper.jar from, if no 'downloadUrl' is provided.
26 | */
27 | private static final String DEFAULT_DOWNLOAD_URL = "https://repo.maven.apache.org/maven2/io/takari/maven-wrapper/"
28 | + WRAPPER_VERSION + "/maven-wrapper-" + WRAPPER_VERSION + ".jar";
29 |
30 | /**
31 | * Path to the maven-wrapper.properties file, which might contain a downloadUrl property to
32 | * use instead of the default one.
33 | */
34 | private static final String MAVEN_WRAPPER_PROPERTIES_PATH =
35 | ".mvn/wrapper/maven-wrapper.properties";
36 |
37 | /**
38 | * Path where the maven-wrapper.jar will be saved to.
39 | */
40 | private static final String MAVEN_WRAPPER_JAR_PATH =
41 | ".mvn/wrapper/maven-wrapper.jar";
42 |
43 | /**
44 | * Name of the property which should be used to override the default download url for the wrapper.
45 | */
46 | private static final String PROPERTY_NAME_WRAPPER_URL = "wrapperUrl";
47 |
48 | public static void main(String args[]) {
49 | System.out.println("- Downloader started");
50 | File baseDirectory = new File(args[0]);
51 | System.out.println("- Using base directory: " + baseDirectory.getAbsolutePath());
52 |
53 | // If the maven-wrapper.properties exists, read it and check if it contains a custom
54 | // wrapperUrl parameter.
55 | File mavenWrapperPropertyFile = new File(baseDirectory, MAVEN_WRAPPER_PROPERTIES_PATH);
56 | String url = DEFAULT_DOWNLOAD_URL;
57 | if(mavenWrapperPropertyFile.exists()) {
58 | FileInputStream mavenWrapperPropertyFileInputStream = null;
59 | try {
60 | mavenWrapperPropertyFileInputStream = new FileInputStream(mavenWrapperPropertyFile);
61 | Properties mavenWrapperProperties = new Properties();
62 | mavenWrapperProperties.load(mavenWrapperPropertyFileInputStream);
63 | url = mavenWrapperProperties.getProperty(PROPERTY_NAME_WRAPPER_URL, url);
64 | } catch (IOException e) {
65 | System.out.println("- ERROR loading '" + MAVEN_WRAPPER_PROPERTIES_PATH + "'");
66 | } finally {
67 | try {
68 | if(mavenWrapperPropertyFileInputStream != null) {
69 | mavenWrapperPropertyFileInputStream.close();
70 | }
71 | } catch (IOException e) {
72 | // Ignore ...
73 | }
74 | }
75 | }
76 | System.out.println("- Downloading from: " + url);
77 |
78 | File outputFile = new File(baseDirectory.getAbsolutePath(), MAVEN_WRAPPER_JAR_PATH);
79 | if(!outputFile.getParentFile().exists()) {
80 | if(!outputFile.getParentFile().mkdirs()) {
81 | System.out.println(
82 | "- ERROR creating output directory '" + outputFile.getParentFile().getAbsolutePath() + "'");
83 | }
84 | }
85 | System.out.println("- Downloading to: " + outputFile.getAbsolutePath());
86 | try {
87 | downloadFileFromURL(url, outputFile);
88 | System.out.println("Done");
89 | System.exit(0);
90 | } catch (Throwable e) {
91 | System.out.println("- Error downloading");
92 | e.printStackTrace();
93 | System.exit(1);
94 | }
95 | }
96 |
97 | private static void downloadFileFromURL(String urlString, File destination) throws Exception {
98 | if (System.getenv("MVNW_USERNAME") != null && System.getenv("MVNW_PASSWORD") != null) {
99 | String username = System.getenv("MVNW_USERNAME");
100 | char[] password = System.getenv("MVNW_PASSWORD").toCharArray();
101 | Authenticator.setDefault(new Authenticator() {
102 | @Override
103 | protected PasswordAuthentication getPasswordAuthentication() {
104 | return new PasswordAuthentication(username, password);
105 | }
106 | });
107 | }
108 | URL website = new URL(urlString);
109 | ReadableByteChannel rbc;
110 | rbc = Channels.newChannel(website.openStream());
111 | FileOutputStream fos = new FileOutputStream(destination);
112 | fos.getChannel().transferFrom(rbc, 0, Long.MAX_VALUE);
113 | fos.close();
114 | rbc.close();
115 | }
116 |
117 | }
118 |
--------------------------------------------------------------------------------
/9.0/consumer/.mvn/wrapper/maven-wrapper.jar:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/joshlong/reactive-spring-livelessons-2e/f10c568102d0634a050639973ba99f632580392f/9.0/consumer/.mvn/wrapper/maven-wrapper.jar
--------------------------------------------------------------------------------
/9.0/consumer/.mvn/wrapper/maven-wrapper.properties:
--------------------------------------------------------------------------------
1 | distributionUrl=https://repo.maven.apache.org/maven2/org/apache/maven/apache-maven/3.6.2/apache-maven-3.6.2-bin.zip
2 | wrapperUrl=https://repo.maven.apache.org/maven2/io/takari/maven-wrapper/0.5.5/maven-wrapper-0.5.5.jar
3 |
--------------------------------------------------------------------------------
/9.0/consumer/pom.xml:
--------------------------------------------------------------------------------
1 |
2 |
4 | 4.0.0
5 |
6 | org.springframework.boot
7 | spring-boot-starter-parent
8 | 2.2.2.RELEASE
9 |
10 |
11 | com.example
12 | consumer
13 | 0.0.1-SNAPSHOT
14 | consumer
15 | Demo project for Spring Boot
16 |
17 |
18 | 13
19 | Hoxton.RELEASE
20 |
21 |
22 |
23 |
24 | org.springframework.boot
25 | spring-boot-starter-webflux
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 | io.projectreactor
40 | reactor-test
41 | test
42 |
43 |
44 | org.springframework.cloud
45 | spring-cloud-starter-contract-stub-runner
46 | test
47 |
48 |
49 |
50 |
51 |
52 |
53 | org.springframework.cloud
54 | spring-cloud-dependencies
55 | ${spring-cloud.version}
56 | pom
57 | import
58 |
59 |
60 |
61 |
62 |
63 |
64 |
65 | org.springframework.boot
66 | spring-boot-maven-plugin
67 |
68 |
69 |
70 |
71 |
72 |
--------------------------------------------------------------------------------
/9.0/consumer/src/main/java/com/example/consumer/ConsumerApplication.java:
--------------------------------------------------------------------------------
1 | package com.example.consumer;
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.web.reactive.function.client.WebClient;
7 |
8 | @SpringBootApplication
9 | public class ConsumerApplication {
10 |
11 | @Bean
12 | WebClient webClient(WebClient.Builder builder) {
13 | return builder.build();
14 | }
15 |
16 | public static void main(String[] args) {
17 | SpringApplication.run(ConsumerApplication.class, args);
18 | }
19 |
20 | }
21 |
--------------------------------------------------------------------------------
/9.0/consumer/src/main/java/com/example/consumer/Reservation.java:
--------------------------------------------------------------------------------
1 | package com.example.consumer;
2 |
3 | import lombok.AllArgsConstructor;
4 | import lombok.Data;
5 | import lombok.NoArgsConstructor;
6 |
7 | @Data
8 | @AllArgsConstructor
9 | @NoArgsConstructor
10 | public class Reservation {
11 | private String id, name;
12 | }
13 |
--------------------------------------------------------------------------------
/9.0/consumer/src/main/java/com/example/consumer/ReservationClient.java:
--------------------------------------------------------------------------------
1 | package com.example.consumer;
2 |
3 | import lombok.RequiredArgsConstructor;
4 | import org.springframework.stereotype.Component;
5 | import org.springframework.web.reactive.function.client.WebClient;
6 | import reactor.core.publisher.Flux;
7 |
8 | @Component
9 | @RequiredArgsConstructor
10 | public class ReservationClient {
11 |
12 | private final WebClient webClient;
13 |
14 | public Flux getAllReservations() {
15 | return this.webClient
16 | .get()
17 | .uri("http://localhost:8080/reservations")
18 | .retrieve()
19 | .bodyToFlux(Reservation.class);
20 | }
21 | }
22 |
--------------------------------------------------------------------------------
/9.0/consumer/src/main/resources/application.properties:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/9.0/consumer/src/test/java/com/example/consumer/ConsumerApplicationTests.java:
--------------------------------------------------------------------------------
1 | package com.example.consumer;
2 |
3 | import org.junit.Test;
4 | import org.junit.runner.RunWith;
5 | import org.springframework.beans.factory.annotation.Autowired;
6 | import org.springframework.boot.test.context.SpringBootTest;
7 | import org.springframework.cloud.contract.stubrunner.spring.AutoConfigureStubRunner;
8 | import org.springframework.cloud.contract.stubrunner.spring.StubRunnerProperties;
9 | import org.springframework.test.context.junit4.SpringRunner;
10 | import reactor.core.publisher.Flux;
11 | import reactor.test.StepVerifier;
12 |
13 | @SpringBootTest
14 | @RunWith(SpringRunner.class)
15 | @AutoConfigureStubRunner(
16 | ids = "com.example:producer:+:8080",
17 | stubsMode = StubRunnerProperties.StubsMode.LOCAL
18 | )
19 | public class ConsumerApplicationTests {
20 |
21 | @Autowired
22 | private ReservationClient client;
23 |
24 | @Test
25 | public void contextLoads() {
26 | Flux reservations = this.client.getAllReservations();
27 | StepVerifier
28 | .create(reservations)
29 | .expectNextMatches(reservation ->
30 | reservation.getId() != null && reservation.getName().equalsIgnoreCase("Jane"))
31 | .verifyComplete();
32 | }
33 |
34 | }
35 |
--------------------------------------------------------------------------------
/9.0/producer/.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 |
--------------------------------------------------------------------------------
/9.0/producer/.mvn/wrapper/MavenWrapperDownloader.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2012-2019 the original author or authors.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * https://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 | import java.net.*;
17 | import java.io.*;
18 | import java.nio.channels.*;
19 | import java.util.Properties;
20 |
21 | public class MavenWrapperDownloader {
22 |
23 | private static final String WRAPPER_VERSION = "0.5.5";
24 | /**
25 | * Default URL to download the maven-wrapper.jar from, if no 'downloadUrl' is provided.
26 | */
27 | private static final String DEFAULT_DOWNLOAD_URL = "https://repo.maven.apache.org/maven2/io/takari/maven-wrapper/"
28 | + WRAPPER_VERSION + "/maven-wrapper-" + WRAPPER_VERSION + ".jar";
29 |
30 | /**
31 | * Path to the maven-wrapper.properties file, which might contain a downloadUrl property to
32 | * use instead of the default one.
33 | */
34 | private static final String MAVEN_WRAPPER_PROPERTIES_PATH =
35 | ".mvn/wrapper/maven-wrapper.properties";
36 |
37 | /**
38 | * Path where the maven-wrapper.jar will be saved to.
39 | */
40 | private static final String MAVEN_WRAPPER_JAR_PATH =
41 | ".mvn/wrapper/maven-wrapper.jar";
42 |
43 | /**
44 | * Name of the property which should be used to override the default download url for the wrapper.
45 | */
46 | private static final String PROPERTY_NAME_WRAPPER_URL = "wrapperUrl";
47 |
48 | public static void main(String args[]) {
49 | System.out.println("- Downloader started");
50 | File baseDirectory = new File(args[0]);
51 | System.out.println("- Using base directory: " + baseDirectory.getAbsolutePath());
52 |
53 | // If the maven-wrapper.properties exists, read it and check if it contains a custom
54 | // wrapperUrl parameter.
55 | File mavenWrapperPropertyFile = new File(baseDirectory, MAVEN_WRAPPER_PROPERTIES_PATH);
56 | String url = DEFAULT_DOWNLOAD_URL;
57 | if(mavenWrapperPropertyFile.exists()) {
58 | FileInputStream mavenWrapperPropertyFileInputStream = null;
59 | try {
60 | mavenWrapperPropertyFileInputStream = new FileInputStream(mavenWrapperPropertyFile);
61 | Properties mavenWrapperProperties = new Properties();
62 | mavenWrapperProperties.load(mavenWrapperPropertyFileInputStream);
63 | url = mavenWrapperProperties.getProperty(PROPERTY_NAME_WRAPPER_URL, url);
64 | } catch (IOException e) {
65 | System.out.println("- ERROR loading '" + MAVEN_WRAPPER_PROPERTIES_PATH + "'");
66 | } finally {
67 | try {
68 | if(mavenWrapperPropertyFileInputStream != null) {
69 | mavenWrapperPropertyFileInputStream.close();
70 | }
71 | } catch (IOException e) {
72 | // Ignore ...
73 | }
74 | }
75 | }
76 | System.out.println("- Downloading from: " + url);
77 |
78 | File outputFile = new File(baseDirectory.getAbsolutePath(), MAVEN_WRAPPER_JAR_PATH);
79 | if(!outputFile.getParentFile().exists()) {
80 | if(!outputFile.getParentFile().mkdirs()) {
81 | System.out.println(
82 | "- ERROR creating output directory '" + outputFile.getParentFile().getAbsolutePath() + "'");
83 | }
84 | }
85 | System.out.println("- Downloading to: " + outputFile.getAbsolutePath());
86 | try {
87 | downloadFileFromURL(url, outputFile);
88 | System.out.println("Done");
89 | System.exit(0);
90 | } catch (Throwable e) {
91 | System.out.println("- Error downloading");
92 | e.printStackTrace();
93 | System.exit(1);
94 | }
95 | }
96 |
97 | private static void downloadFileFromURL(String urlString, File destination) throws Exception {
98 | if (System.getenv("MVNW_USERNAME") != null && System.getenv("MVNW_PASSWORD") != null) {
99 | String username = System.getenv("MVNW_USERNAME");
100 | char[] password = System.getenv("MVNW_PASSWORD").toCharArray();
101 | Authenticator.setDefault(new Authenticator() {
102 | @Override
103 | protected PasswordAuthentication getPasswordAuthentication() {
104 | return new PasswordAuthentication(username, password);
105 | }
106 | });
107 | }
108 | URL website = new URL(urlString);
109 | ReadableByteChannel rbc;
110 | rbc = Channels.newChannel(website.openStream());
111 | FileOutputStream fos = new FileOutputStream(destination);
112 | fos.getChannel().transferFrom(rbc, 0, Long.MAX_VALUE);
113 | fos.close();
114 | rbc.close();
115 | }
116 |
117 | }
118 |
--------------------------------------------------------------------------------
/9.0/producer/.mvn/wrapper/maven-wrapper.jar:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/joshlong/reactive-spring-livelessons-2e/f10c568102d0634a050639973ba99f632580392f/9.0/producer/.mvn/wrapper/maven-wrapper.jar
--------------------------------------------------------------------------------
/9.0/producer/.mvn/wrapper/maven-wrapper.properties:
--------------------------------------------------------------------------------
1 | distributionUrl=https://repo.maven.apache.org/maven2/org/apache/maven/apache-maven/3.6.2/apache-maven-3.6.2-bin.zip
2 | wrapperUrl=https://repo.maven.apache.org/maven2/io/takari/maven-wrapper/0.5.5/maven-wrapper-0.5.5.jar
3 |
--------------------------------------------------------------------------------
/9.0/producer/pom.xml:
--------------------------------------------------------------------------------
1 |
2 |
4 | 4.0.0
5 |
6 | org.springframework.boot
7 | spring-boot-starter-parent
8 | 2.2.2.RELEASE
9 |
10 |
11 | com.example
12 | producer
13 | 0.0.1-SNAPSHOT
14 | producer
15 | Demo project for Spring Boot
16 |
17 |
18 | 13
19 | Hoxton.RELEASE
20 |
21 |
22 |
23 |
24 | org.springframework.boot
25 | spring-boot-starter-data-mongodb-reactive
26 |
27 |
28 | org.springframework.boot
29 | spring-boot-starter-webflux
30 |
31 |
32 |
33 | org.projectlombok
34 | lombok
35 | true
36 |
37 |
44 |
45 | org.springframework.boot
46 | spring-boot-starter-test
47 | test
48 |
54 |
55 |
56 | io.projectreactor
57 | reactor-test
58 | test
59 |
60 |
61 | org.springframework.cloud
62 | spring-cloud-starter-contract-verifier
63 | test
64 |
65 |
66 |
67 |
68 |
69 |
70 | org.springframework.cloud
71 | spring-cloud-dependencies
72 | ${spring-cloud.version}
73 | pom
74 | import
75 |
76 |
77 |
78 |
79 |
80 |
81 |
82 | org.springframework.cloud
83 | spring-cloud-contract-maven-plugin
84 | 2.2.0.RELEASE
85 | true
86 |
87 |
88 | com.example.producer.BaseClass
89 |
90 |
91 | EXPLICIT
92 |
93 |
94 |
95 | org.springframework.boot
96 | spring-boot-maven-plugin
97 |
98 |
99 |
100 |
101 |
102 |
--------------------------------------------------------------------------------
/9.0/producer/src/main/java/com/example/producer/ProducerApplication.java:
--------------------------------------------------------------------------------
1 | package com.example.producer;
2 |
3 | import org.springframework.boot.SpringApplication;
4 | import org.springframework.boot.autoconfigure.SpringBootApplication;
5 |
6 | @SpringBootApplication
7 | public class ProducerApplication {
8 |
9 | public static void main(String[] args) {
10 | SpringApplication.run(ProducerApplication.class, args);
11 | }
12 |
13 | }
14 |
--------------------------------------------------------------------------------
/9.0/producer/src/main/java/com/example/producer/Reservation.java:
--------------------------------------------------------------------------------
1 | package com.example.producer;
2 |
3 | import lombok.AllArgsConstructor;
4 | import lombok.Data;
5 | import lombok.NoArgsConstructor;
6 | import org.springframework.data.annotation.Id;
7 |
8 | @Data
9 | @AllArgsConstructor
10 | @NoArgsConstructor
11 | public class Reservation {
12 | private String id;
13 | private String name;
14 | }
15 |
--------------------------------------------------------------------------------
/9.0/producer/src/main/java/com/example/producer/ReservationHttpConfiguration.java:
--------------------------------------------------------------------------------
1 | package com.example.producer;
2 |
3 | import org.springframework.beans.factory.annotation.Autowired;
4 | import org.springframework.context.annotation.Bean;
5 | import org.springframework.context.annotation.Configuration;
6 | import org.springframework.web.reactive.function.server.HandlerFunction;
7 | import org.springframework.web.reactive.function.server.RouterFunction;
8 | import org.springframework.web.reactive.function.server.ServerRequest;
9 | import org.springframework.web.reactive.function.server.ServerResponse;
10 | import reactor.core.publisher.Mono;
11 |
12 | import static org.springframework.web.reactive.function.server.RouterFunctions.route;
13 | import static org.springframework.web.reactive.function.server.ServerResponse.*;
14 |
15 | @Configuration
16 | class ReservationHttpConfiguration {
17 |
18 | @Bean
19 | RouterFunction routes(ReservationRepository rr) {
20 | return route()
21 | .GET("/reservations", r -> ok().body(rr.findAll(), Reservation.class))
22 | .build();
23 | }
24 | }
25 |
--------------------------------------------------------------------------------
/9.0/producer/src/main/java/com/example/producer/ReservationRepository.java:
--------------------------------------------------------------------------------
1 | package com.example.producer;
2 |
3 | import org.springframework.data.repository.reactive.ReactiveCrudRepository;
4 | import reactor.core.publisher.Flux;
5 |
6 | public interface ReservationRepository extends ReactiveCrudRepository {
7 |
8 | Flux findByName(String name);
9 | }
10 |
--------------------------------------------------------------------------------
/9.0/producer/src/main/resources/application.properties:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/9.0/producer/src/test/java/com/example/producer/BaseClass.java:
--------------------------------------------------------------------------------
1 | package com.example.producer;
2 |
3 | import io.restassured.RestAssured;
4 | import org.junit.Before;
5 | import org.junit.runner.RunWith;
6 | import org.mockito.Mockito;
7 | import org.springframework.beans.factory.annotation.Autowired;
8 | import org.springframework.boot.test.context.SpringBootTest;
9 | import org.springframework.boot.test.mock.mockito.MockBean;
10 | import org.springframework.boot.web.server.LocalServerPort;
11 | import org.springframework.test.context.junit4.SpringRunner;
12 | import org.springframework.test.web.reactive.server.WebTestClient;
13 | import reactor.core.publisher.Flux;
14 |
15 | @SpringBootTest(
16 | webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT,
17 | properties = "server.port=0")
18 | @RunWith(SpringRunner.class)
19 | public class BaseClass {
20 |
21 | @MockBean
22 | private ReservationRepository reservationRepository;
23 |
24 | @LocalServerPort
25 | private int port;
26 |
27 | @Before
28 | public void before() {
29 | RestAssured.baseURI = "http://localhost:" + this.port;
30 | Mockito
31 | .when(this.reservationRepository.findAll())
32 | .thenReturn(Flux.just(new Reservation("1", "Jane")));
33 | }
34 |
35 | }
36 |
--------------------------------------------------------------------------------
/9.0/producer/src/test/java/com/example/producer/ReservationEntityTest.java:
--------------------------------------------------------------------------------
1 | package com.example.producer;
2 |
3 | import org.junit.Test;
4 | import org.junit.runner.RunWith;
5 | import org.springframework.beans.factory.annotation.Autowired;
6 | import org.springframework.boot.test.autoconfigure.data.mongo.DataMongoTest;
7 | import org.springframework.data.mongodb.core.ReactiveMongoTemplate;
8 | import org.springframework.test.context.junit4.SpringRunner;
9 | import reactor.core.publisher.Mono;
10 | import reactor.test.StepVerifier;
11 |
12 | @RunWith(SpringRunner.class)
13 | @DataMongoTest
14 | public class ReservationEntityTest {
15 |
16 | @Autowired
17 | private ReactiveMongoTemplate reactiveMongoTemplate;
18 |
19 | @Test
20 | public void persist() {
21 | Reservation reservation = new Reservation(null, "Jane");
22 | Mono savedRecord = this.reactiveMongoTemplate.save(reservation);
23 | StepVerifier
24 | .create(savedRecord)
25 | .expectNextMatches(res -> res.getId() != null && res.getName().equalsIgnoreCase("Jane"))
26 | .verifyComplete();
27 |
28 | }
29 | }
30 |
--------------------------------------------------------------------------------
/9.0/producer/src/test/java/com/example/producer/ReservationHttpTest.java:
--------------------------------------------------------------------------------
1 | package com.example.producer;
2 |
3 | import org.junit.Before;
4 | import org.junit.Test;
5 | import org.junit.runner.RunWith;
6 | import org.mockito.Mockito;
7 | import org.springframework.beans.factory.annotation.Autowired;
8 | import org.springframework.boot.test.autoconfigure.web.reactive.WebFluxTest;
9 | import org.springframework.boot.test.mock.mockito.MockBean;
10 | import org.springframework.context.annotation.Bean;
11 | import org.springframework.context.annotation.Configuration;
12 | import org.springframework.context.annotation.Import;
13 | import org.springframework.http.MediaType;
14 | import org.springframework.test.context.junit4.SpringRunner;
15 | import org.springframework.test.web.reactive.server.WebTestClient;
16 | import reactor.core.publisher.Flux;
17 |
18 | @WebFluxTest
19 | @Import({ReservationHttpConfiguration.class})
20 | @RunWith(SpringRunner.class)
21 | public class ReservationHttpTest {
22 |
23 | @MockBean
24 | private ReservationRepository reservationRepository;
25 |
26 | @Autowired
27 | private WebTestClient testClient;
28 |
29 | @Before
30 | public void before() {
31 | Mockito
32 | .when(this.reservationRepository.findAll())
33 | .thenReturn(Flux.just(new Reservation("1", "Jane")));
34 | }
35 |
36 | @Test
37 | public void getAllReservations() throws Exception {
38 |
39 | this.testClient
40 | .get()
41 | .uri("/reservations")
42 | .exchange()
43 | .expectStatus().isOk()
44 | .expectHeader().contentType(MediaType.APPLICATION_JSON)
45 | .expectBody().jsonPath("@.[0].name").isEqualTo("Jane");
46 | }
47 | }
48 |
49 |
--------------------------------------------------------------------------------
/9.0/producer/src/test/java/com/example/producer/ReservationPojoTest.java:
--------------------------------------------------------------------------------
1 | package com.example.producer;
2 |
3 | import org.hamcrest.BaseMatcher;
4 | import org.hamcrest.Description;
5 | import org.hamcrest.Matcher;
6 | import org.hamcrest.Matchers;
7 | import org.junit.After;
8 | import org.junit.Assert;
9 | import org.junit.Before;
10 | import org.junit.Test;
11 |
12 | public class ReservationPojoTest {
13 |
14 |
15 |
16 | @Test
17 | public void create() {
18 | Reservation reservation = new Reservation("1", "Jane");
19 | Assert.assertEquals(reservation.getId(), "1");
20 | Assert.assertEquals(reservation.getName(), "Jane");
21 | Assert.assertNotNull(reservation.getId());
22 | Assert.assertThat(reservation.getName(), Matchers.equalToIgnoringCase("Jane"));
23 | Assert.assertThat(reservation.getName(), new ValidNameMatcher());
24 | }
25 |
26 |
27 | }
28 |
29 | class ValidNameMatcher extends BaseMatcher {
30 |
31 | @Override
32 | public boolean matches(Object o) {
33 | return o instanceof String && isValidName((String) o);
34 | }
35 |
36 | @Override
37 | public void describeTo(Description description) {
38 | description.appendText("the name must be non-empty and start with an uppercase letter");
39 | }
40 |
41 | private boolean isValidName(String name) {
42 | return name != null && name.length() > 0 && Character.isUpperCase(name.charAt(0));
43 | }
44 | }
45 |
--------------------------------------------------------------------------------
/9.0/producer/src/test/java/com/example/producer/ReservationRepositoryTest.java:
--------------------------------------------------------------------------------
1 | package com.example.producer;
2 |
3 | import org.junit.Test;
4 | import org.junit.runner.RunWith;
5 | import org.springframework.beans.factory.annotation.Autowired;
6 | import org.springframework.boot.test.autoconfigure.data.mongo.DataMongoTest;
7 | import org.springframework.test.context.junit4.SpringRunner;
8 | import reactor.core.publisher.Flux;
9 | import reactor.core.publisher.Mono;
10 | import reactor.test.StepVerifier;
11 |
12 | @RunWith(SpringRunner.class)
13 | @DataMongoTest
14 | public class ReservationRepositoryTest {
15 |
16 | @Autowired
17 | private ReservationRepository repository;
18 |
19 | @Test
20 | public void persist() throws Exception {
21 |
22 | Flux reservationFlux = this.repository.saveAll(
23 | Flux.just(new Reservation(null, "A"),
24 | new Reservation(null, "B"),
25 | new Reservation(null, "C"),
26 | new Reservation(null, "A")));
27 |
28 | StepVerifier
29 | .create(this.repository.deleteAll())
30 | .verifyComplete();
31 |
32 | StepVerifier
33 | .create(reservationFlux)
34 | .expectNextCount(4)
35 | .verifyComplete();
36 |
37 | StepVerifier
38 | .create(this.repository.findByName("A"))
39 | .expectNextCount(2)
40 | .verifyComplete();
41 |
42 | }
43 |
44 | }
45 |
--------------------------------------------------------------------------------
/9.0/producer/src/test/resources/contracts/shouldReturnAllReservations.groovy:
--------------------------------------------------------------------------------
1 | import org.springframework.cloud.contract.spec.Contract
2 | import org.springframework.http.HttpStatus
3 | import org.springframework.http.MediaType
4 |
5 | Contract.make {
6 | description("should return all Reservations")
7 | request {
8 | method("GET")
9 | url("/reservations")
10 | }
11 | response {
12 | status(HttpStatus.OK.value())
13 | headers {
14 | contentType(MediaType.APPLICATION_JSON_VALUE)
15 | }
16 | body([[id: "1", name: "Jane"]])
17 | }
18 | }
--------------------------------------------------------------------------------
/reactive-spring.md:
--------------------------------------------------------------------------------
1 | ## Basics
2 | * Motivations for Reactive Programming
3 | * Reactive Streams and Java 9 `Flow`
4 | * Project Reactor
5 | * The Spring Initializr
6 |
7 | ## Data
8 | * NoSQL with MongoDB
9 | * SQL with R2DBC
10 | * Transactions
11 |
12 | ## HTTP Services
13 | * Spring MVC-style HTTP Controllers
14 | * Functional Reactive-style Controllers
15 | * Server-Sent Events
16 |
17 | ## WebSockets
18 | * a simple never ending websocket example
19 | * JavaScript to talk to it
20 |
21 | ## HTTP Clients
22 | * The Reactive HTTP Client
23 | * Reactor Error Handling
24 | * Spring Cloud Circuit Breaker
25 | * Service Hedging
26 |
27 | ## RSocket
28 | * Motivations
29 | * Raw RSocket
30 | * RSocket in Spring
31 |
32 | ## Security
33 | * Motivations
34 | * HTTP
35 | * RSocket
36 |
37 | ## Gateway
38 | * Motivations
39 | * HTTP
40 | * RSocket
41 |
42 | ## Kotlin
43 | * Basics
44 | * Koroutines (see Spring Tips)
45 |
46 | ## Reactive Streams Redux
47 | * Akka Streams
48 |
49 | ## Testing
50 | * Motivations for Test-Driven Development
51 | * Basic Testing
52 | * Testing Data Tier
53 | * Testing the Web Tier
54 | * Testing a Client
55 | * Microservice Testing
56 |
57 |
--------------------------------------------------------------------------------