loiane.com
@loiane
Full-Stack	Reativa	com	
Spring	WebFlux	+	
Angular
Agenda
•Pq	rea(vo?	
•Rea(vo	x	MVC	
•Back-end	rea(vo	com	Spring	WebFlux	
•Front-end	rea(vo	com	with	Angular	
•Gerenciamento	de	estado	com	NgRx	e	RxJS	
•Demo
@loiane
Loiane Groner
@loiane
github.com/loiane
loiane.com
loiane.training
Analista Negócios | Engenheira @ Citibank US
Tech Stack
@loiane
Arquitetura Full-Stack
Data source
Event
Source Observable<T[]>
Component ->
async pipe
ngRx
Redux
Repository
Flux<T>
Controller |
Routes
Flux<T>
MongoDB Spring WebFlux Angular Reativo
@loiane
@loiane
@loiane
@loiane
Programação Reativa
Streams Streams Streams Streams Streams Streams Streams Streams Streams
Streams Streams Streams Streams Streams Streams Streams Streams Streams
Streams Streams Streams Streams Streams Streams Streams Streams Streams
Streams Streams Streams Streams Streams Streams Streams Streams Streams
Streams Streams Streams Streams Streams Streams Streams Streams Streams
Streams Streams Streams Streams Streams Streams Streams Streams Streams
Streams Streams Streams Streams Streams Streams Streams Streams Streams
Streams Streams Streams Streams Streams Streams Streams Streams Streams
Streams Streams Streams Streams Streams Streams Streams Streams Streams
Streams Streams Streams Streams Streams Streams Streams Streams Streams
Streams Streams Streams Streams Streams Streams Streams Streams Streams
Streams Streams Streams Streams Streams Streams Streams Streams Streams
Streams Streams Streams Streams Streams Streams Streams Streams Streams @loiane
@loiane
Aplicações Reativas
Publisher SubscriberStream
@loiane
Spring 5
https://docs.spring.io/spring-framework/docs/5.0.0.M1/spring-framework-reference/html/web-reactive.html @loiane
Spring Data
public interface ReactiveMongoRepository<T, ID> {
<S extends T> Mono<S> insert(S var1);
<S extends T> Flux<S> insert(Iterable<S> var1);
<S extends T> Flux<S> insert(Publisher<S> var1);
<S extends T> Flux<S> findAll(Example<S> var1);
<S extends T> Flux<S> findAll(Example<S> var1, Sort var2);
}
@loiane
Um Objeto
@loiane
Vários Objetos
@loiane
@loiane
Oracle Cloud
@loiane
Model
@NoArgsConstructor
@AllArgsConstructor
@Data
@Document(collection = "products")
public class Product {
@Id
private String id;
private String name;
private String description;
private Double price;
private String image;
private String status;
private String discounted;
private Double discount;
}
@loiane
Repository
public interface ProductRepository
extends ReactiveMongoRepository<Product, String> {
}
@loiane
Controller
@RestController
@RequestMapping("/api/products")
public class ProductController {
private ProductRepository repository;
public ProductController(ProductRepository repository) {
this.repository = repository;
}
}
@loiane
Controller
@GetMapping
public Flux<Product> getAll() {
return repository.findAll();
}
@GetMapping("{id}")
public Mono<ResponseEntity<Product!>> getById(@PathVariable String id) {
return repository.findById(id)
.map(product !-> ResponseEntity.ok(product))
.defaultIfEmpty(ResponseEntity.notFound().build());
}
@loiane
Controller: WebFlux x MVC
@GetMapping
public Flux<Product> getAll() {
return repository.findAll();
}
@GetMapping
public List findAll(){
return repository.findAll();
}
WebFlux
MVC
@loiane
Controller: WebFlux x MVC
@GetMapping(“{id}")
public Mono<ResponseEntity<Product!>> getById(@PathVariable String id) {
return repository.findById(id)
.map(product !-> ResponseEntity.ok(product))
.defaultIfEmpty(ResponseEntity.notFound().build());
}
@GetMapping(path = {"{id}"})
public ResponseEntity<Contact> findById(@PathVariable("id") long id){
return repository.findById(id)
.map(record !-> ResponseEntity.ok().body(record))
.orElse(ResponseEntity.notFound().build());
}
WebFlux
MVC
@loiane
Mundo Real
List<Order> getOrders(int customerId)
List<Product> getProducts(Order order)
ShippingStatus getShippingStatus(Order o, Product p)
getOrdersAsync(1) !// Flux<Order>
    .flatMap(o !-> getProductsAsync(o) !// Flux<Product>
            .flatMap(p !-> getShippingStatusAsync(o, p))
    );
@loiane
Backpressure
@loiane
Streams
Source: https://jakearchibald.com/2016/streams-ftw/ @loiane
Streams
NJSON
Newline delimited JSON @loiane
Backpressure
@GetMapping(value = "/stream", produces = MediaType.TEXT_EVENT_STREAM_VALUE)
public Flux<Order> streamOrderStatus() {
return repository.findAll().delayElements(Duration.ofSeconds(7));
}
@loiane
Angular Reativo
•HKp	
•Router	
•Guards	
•Forms
@loiane
Observable
Observable ObserverOperadores
Data Source
Fonte
Transforma os dados
Consumer
Consumidor
Observable emite valores assíncronos e notifica observers
@loiane
Angular Http + Spring
load() {
return this.http.get<Contact[]>(this.API)
.pipe(
take(1),
tap(data !=> this.contactsCache = data)
);
}
create(record: Contact) {
return this.http.post<Contact>(this.API, record).pipe(take(1));
}
update(record: Contact) {
return this.http.put<Contact>(`${this.API}/${record.id}`, record).pipe(take(1));
}
remove(id: number) {
return this.http.delete<Contact>(`${this.API}/${id}`).pipe(take(1));
}
@loiane
Backpressure with RxJS
observeMessages(url: string): Observable<any> {
return new Observable<any>(obs !=> {
const es = new EventSource(url);
es.addEventListener('message', (evt: any) !=> {
console.log(evt.data);
obs.next(evt.data !!= null ? JSON.parse(evt.data) : evt.data);
});
return () !=> es.close();
});
}
@loiane
https://github.com/ngrx
@loiane
Fluxo de Dados Assíncrono
Reducer
dispatch
Store
subscribe
Requisita
Ação
Action
Executa o Reducer
Estado
Atualiza a View
Retorna um novo Estado
Component
@loiane
Componente inicia a mudança
@loiane
estado
Com Redux
@loiane
Store
Redux Store
Action
dispatch
subscribe
@loiane
@loiane
Apenas MongoDB?
@loiane
Desafios
@loiane
hKps://github.com/loiane/
reac(ve-spring-angular
@loiane
Referências
• hKps://docs.spring.io/spring/docs/current/spring-framework-reference/pdf/web-
reac(ve.pdf	
• hKps://docs.spring.io/spring/docs/current/spring-framework-reference/web-
reac(ve.html	
• hKp://www.reac(ve-streams.org/	
• hKps://github.com/ngrx/plaPorm	
• hKps://blog.nrwl.io/ngrx-paKerns-and-techniques-f46126e2b1e5
@loiane
Obrigada!
@loiane	
github.com/loiane	
loiane.com	
youtube.com/loianegroner

Full-Stack Reativo com Spring WebFlux + Angular - Devs Java Girl