Full Stack Reactive with React and Spring WebFlux
Matt Raible | @mraible
March 12, 2020
Photo by Lukas Schlagenhauf flickr.com/photos/lschlagenhauf/33223388493
Blogger on raibledesigns.com and

developer.okta.com/blog
Web Developer and Java Champion
Father, Skier, Mountain Biker,
Whitewater Rafter
Open Source Connoisseur
Who is Matt Raible?
Bus Lover
Okta Developer Advocate
developer.okta.com
What About You?
Full Stack Reactive
http://bit.ly/webflux-and-react
OAuth 2.0 Overview
Today’s Agenda
What is reactive programming?

Introduction to Spring WebFlux

Developing an API with WebFlux

Handling Streaming Data with React

Securing WebFlux and React
What is reactive programming?
Asynchronous I/O
package com.example.io;
import lombok.extern.log4j.Log4j2;
import org.springframework.util.FileCopyUtils;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.util.function.Consumer;
@Log4j2
class Synchronous implements Reader {
@Override
public void read(File file, Consumer<BytesPayload> consumer) throws IOException {
try (FileInputStream in = new FileInputStream(file)) {
byte[] data = new byte[FileCopyUtils.BUFFER_SIZE];
int res;
while ((res = in.read(data, 0, data.length)) != -1) {
consumer.accept(BytesPayload.from(data, res));
}
}
}
}
class Asynchronous implements Reader, CompletionHandler<Integer, ByteBuffer> {
private int bytesRead;
private long position;
private AsynchronousFileChannel fileChannel;
private Consumer<BytesPayload> consumer;
private final ExecutorService executorService = Executors.newFixedThreadPool(10);
public void read(File file, Consumer<BytesPayload> c) throws IOException {
this.consumer = c;
Path path = file.toPath();
this.fileChannel = AsynchronousFileChannel.open(path,
Collections.singleton(StandardOpenOption.READ), this.executorService);
ByteBuffer buffer = ByteBuffer.allocate(FileCopyUtils.BUFFER_SIZE);
this.fileChannel.read(buffer, position, buffer, this);
while (this.bytesRead > 0) {
this.position = this.position + this.bytesRead;
this.fileChannel.read(buffer, this.position, buffer, this);
}
}
@Override
public void completed(Integer result, ByteBuffer buffer) {
...
}
}
@Override
public void completed(Integer result, ByteBuffer buffer) {
this.bytesRead = result;
if (this.bytesRead < 0)
return;
buffer.flip();
byte[] data = new byte[buffer.limit()];
buffer.get(data);
consumer.accept(BytesPayload.from(data, data.length));
buffer.clear();
this.position = this.position + this.bytesRead;
this.fileChannel.read(buffer, this.position, buffer, this);
}
@Override
public void failed(Throwable exc, ByteBuffer attachment) {
log.error(exc);
}
Reactive Streams
Reactive Streams reactive-streams.org
Reactive Streams reactive-streams.org
Reactive Streams reactive-streams.org
Reactive Streams reactive-streams.org
Spring WebFlux
@SpringBootApplication
public class DemoApplication {
public static void main(String[] args) {
SpringApplication.run(DemoApplication.class, args);
}
}
@Entity
class Blog {
@Id
@GeneratedValue
private Long id;
private String name;
// getters, setters, toString(), etc
}
@RepositoryRestResource
interface BlogRepository extends JpaRepository<Blog, Long> {
}
Demo: Build a Spring WebFlux API
ES6, ES7 and TypeScript
ES5: es5.github.io 

ES6: git.io/es6features 

ES7: bit.ly/es7features

TS: www.typescriptlang.org
TSES7ES6ES5
@spring_io
#springio17
TypeScript
“Node.js is a JavaScript runtime built on Chrome's V8
JavaScript engine. Node.js uses an event-driven, non-
blocking I/O model that makes it lightweight and
efficient. Node.js' package ecosystem, npm, is the
largest ecosystem of open source libraries in the world.”
https://nodejs.org
https://github.com/creationix/nvm
Hello World with React
http://codepen.io/gaearon/pen/ZpvBNJ?editors=0100
<div id="root"></div>
<script>
ReactDOM.render(
<h1>Hello, world!</h1>,
document.getElementById('root')
);
</script>
Imperative Code
if (count > 99) {
if (!hasFire()) {
addFire();
}
} else {
if (hasFire()) {
removeFire();
}
}
if (count === 0) {
if (hasBadge()) {
removeBadge();
}
return;
}
if (!hasBadge()) {
addBadge();
}
var countText = count > 99 ? "99+" : count.toString();
getBadge().setText(countText);
Declarative Code
if (count === 0) {
return <div className="bell"/>;
} else if (count <= 99) {
return (
<div className="bell">
<span className="badge">{count}</span>
</div>
);
} else {
return (
<div className="bell onFire">
<span className="badge">99+</span>
</div>
);
}
https://facebook.github.io/create-react-app/
Learning React
https://vimeo.com/213710634
Handling Streaming Data in React
Polling with Interval

Polling with RxJS

WebSocket

Server-Sent Events and EventSource

RSocket
Demo: Build a React Client
class ProfileList extends React.Component<ProfileListProps, ProfileListState> {
constructor(props: ProfileListProps) {
super(props);
this.state = {
profiles: [],
isLoading: false
};
}
async componentDidMount() {
this.setState({isLoading: true});
const response = await fetch('http://localhost:8080/profiles', {
headers: {
Authorization: 'Bearer ' + this.props.authState.accessToken
}
});
const data = await response.json();
this.setState({profiles: data, isLoading: false});
}
render() {
const {profiles, isLoading} = this.state;
...
}
}
@spring_io
#springio17
JHipster jhipster.tech
JHipster is a development platform to generate, develop and deploy 
Spring Boot + Angular/React Web applications and Spring microservices. 
The JHipster Mini-Book
v5.0 Available Now!
jhipster-book.com
21-points.com
@jhipster_book
Write your own InfoQ mini-book! github.com/mraible/infoq-mini-book
Action!
Try Spring WebFlux
Try React
Try OIDC
Explore PWAs
Enjoy the experience!
DIY: Full Stack Reactive
http://bit.ly/webflux-and-react
CRUD with React and Spring Boot
http://bit.ly/react-boot-crud
#LearnAllTheThings
developer.okta.com/blog
@oktadev
Use the Source, Luke!
git clone https://github.com/oktadeveloper/okta-spring-webflux-react-
example.git
https://github.com/oktadeveloper/okta-spring-webflux-react-example
Questions?
Keep in touch!

@starbuxman

@mraible

Presentation

speakerdeck.com/mraible

Code

github.com/oktadeveloper
@oktadev

Full Stack Reactive with React and Spring WebFlux - Switzerland JUG 2020

  • 1.
    Full Stack Reactivewith React and Spring WebFlux Matt Raible | @mraible March 12, 2020 Photo by Lukas Schlagenhauf flickr.com/photos/lschlagenhauf/33223388493
  • 4.
    Blogger on raibledesigns.comand developer.okta.com/blog Web Developer and Java Champion Father, Skier, Mountain Biker, Whitewater Rafter Open Source Connoisseur Who is Matt Raible? Bus Lover Okta Developer Advocate
  • 8.
  • 9.
  • 10.
  • 11.
    OAuth 2.0 Overview Today’sAgenda What is reactive programming? Introduction to Spring WebFlux Developing an API with WebFlux Handling Streaming Data with React Securing WebFlux and React
  • 12.
    What is reactiveprogramming? Asynchronous I/O
  • 13.
    package com.example.io; import lombok.extern.log4j.Log4j2; importorg.springframework.util.FileCopyUtils; import java.io.File; import java.io.FileInputStream; import java.io.IOException; import java.util.function.Consumer; @Log4j2 class Synchronous implements Reader { @Override public void read(File file, Consumer<BytesPayload> consumer) throws IOException { try (FileInputStream in = new FileInputStream(file)) { byte[] data = new byte[FileCopyUtils.BUFFER_SIZE]; int res; while ((res = in.read(data, 0, data.length)) != -1) { consumer.accept(BytesPayload.from(data, res)); } } } }
  • 14.
    class Asynchronous implementsReader, CompletionHandler<Integer, ByteBuffer> { private int bytesRead; private long position; private AsynchronousFileChannel fileChannel; private Consumer<BytesPayload> consumer; private final ExecutorService executorService = Executors.newFixedThreadPool(10); public void read(File file, Consumer<BytesPayload> c) throws IOException { this.consumer = c; Path path = file.toPath(); this.fileChannel = AsynchronousFileChannel.open(path, Collections.singleton(StandardOpenOption.READ), this.executorService); ByteBuffer buffer = ByteBuffer.allocate(FileCopyUtils.BUFFER_SIZE); this.fileChannel.read(buffer, position, buffer, this); while (this.bytesRead > 0) { this.position = this.position + this.bytesRead; this.fileChannel.read(buffer, this.position, buffer, this); } } @Override public void completed(Integer result, ByteBuffer buffer) { ... } }
  • 15.
    @Override public void completed(Integerresult, ByteBuffer buffer) { this.bytesRead = result; if (this.bytesRead < 0) return; buffer.flip(); byte[] data = new byte[buffer.limit()]; buffer.get(data); consumer.accept(BytesPayload.from(data, data.length)); buffer.clear(); this.position = this.position + this.bytesRead; this.fileChannel.read(buffer, this.position, buffer, this); } @Override public void failed(Throwable exc, ByteBuffer attachment) { log.error(exc); }
  • 16.
  • 17.
  • 18.
  • 19.
  • 20.
  • 21.
  • 22.
    @SpringBootApplication public class DemoApplication{ public static void main(String[] args) { SpringApplication.run(DemoApplication.class, args); } } @Entity class Blog { @Id @GeneratedValue private Long id; private String name; // getters, setters, toString(), etc } @RepositoryRestResource interface BlogRepository extends JpaRepository<Blog, Long> { }
  • 23.
    Demo: Build aSpring WebFlux API
  • 24.
    ES6, ES7 andTypeScript ES5: es5.github.io ES6: git.io/es6features ES7: bit.ly/es7features TS: www.typescriptlang.org TSES7ES6ES5
  • 25.
  • 26.
    “Node.js is aJavaScript runtime built on Chrome's V8 JavaScript engine. Node.js uses an event-driven, non- blocking I/O model that makes it lightweight and efficient. Node.js' package ecosystem, npm, is the largest ecosystem of open source libraries in the world.” https://nodejs.org https://github.com/creationix/nvm
  • 27.
    Hello World withReact http://codepen.io/gaearon/pen/ZpvBNJ?editors=0100 <div id="root"></div> <script> ReactDOM.render( <h1>Hello, world!</h1>, document.getElementById('root') ); </script>
  • 28.
    Imperative Code if (count> 99) { if (!hasFire()) { addFire(); } } else { if (hasFire()) { removeFire(); } } if (count === 0) { if (hasBadge()) { removeBadge(); } return; } if (!hasBadge()) { addBadge(); } var countText = count > 99 ? "99+" : count.toString(); getBadge().setText(countText);
  • 29.
    Declarative Code if (count=== 0) { return <div className="bell"/>; } else if (count <= 99) { return ( <div className="bell"> <span className="badge">{count}</span> </div> ); } else { return ( <div className="bell onFire"> <span className="badge">99+</span> </div> ); }
  • 30.
  • 31.
  • 32.
    Handling Streaming Datain React Polling with Interval Polling with RxJS WebSocket Server-Sent Events and EventSource RSocket
  • 33.
    Demo: Build aReact Client class ProfileList extends React.Component<ProfileListProps, ProfileListState> { constructor(props: ProfileListProps) { super(props); this.state = { profiles: [], isLoading: false }; } async componentDidMount() { this.setState({isLoading: true}); const response = await fetch('http://localhost:8080/profiles', { headers: { Authorization: 'Bearer ' + this.props.authState.accessToken } }); const data = await response.json(); this.setState({profiles: data, isLoading: false}); } render() { const {profiles, isLoading} = this.state; ... } }
  • 34.
    @spring_io #springio17 JHipster jhipster.tech JHipster isa development platform to generate, develop and deploy  Spring Boot + Angular/React Web applications and Spring microservices. 
  • 35.
    The JHipster Mini-Book v5.0Available Now! jhipster-book.com 21-points.com @jhipster_book Write your own InfoQ mini-book! github.com/mraible/infoq-mini-book
  • 36.
    Action! Try Spring WebFlux TryReact Try OIDC Explore PWAs Enjoy the experience!
  • 37.
    DIY: Full StackReactive http://bit.ly/webflux-and-react
  • 38.
    CRUD with Reactand Spring Boot http://bit.ly/react-boot-crud
  • 39.
  • 40.
  • 41.
    Use the Source,Luke! git clone https://github.com/oktadeveloper/okta-spring-webflux-react- example.git https://github.com/oktadeveloper/okta-spring-webflux-react-example
  • 42.
  • 43.