Spring Reactive Web Client

I have a reactive rest api (webflux), also using the spring WebClient class to request data from other leisure services.

Simplified design:

 @PostMapping(value = "/document") public Mono<Document> save(@RequestBody Mono<Document> document){ //1st Problem: I do not know how to get the documentoOwner ID //that is inside the Document class from the request body without using .block() Mono<DocumentOwner> documentOwner = documentOwnerWebClient() .get().uri("/document-owner/{id}", document.getDocumentOwner().getId()) .accept(MediaType.APPLICATION_STREAM_JSON) .exchange() .flatMap(do -> do.bodyToMono(DocumentOwner.class)); //2nd Problem: I need to check (validate) if the documentOwner object is "active", for instance //documentOwner and document instances below should be the object per se, not the Mono returned from the external API if (!documentOwner.isActive) throw SomeBusinessException(); document.setDocumentOwner(documentOwner); //Now I can save the document in some reactive repository, //and return the one saved with the given ID. return documentRepository.save(document) } 

In other words: I understand (almost) all reactive examples individually, but I cannot put it all together and build a simple usage example (get → validate → save → return) without blocking objects.


The closer I could get, the lower:

 @PostMapping(value = "/document") public Mono<Document> salvar(@RequestBody Mono<Document> documentRequest){ return documentRequest .transform(this::getDocumentOwner) .transform(this::validateDocumentOwner) .and(documentRequest, this::setDocumentOwner) .transform(this::saveDocument); } 

Helper Methods:

 private Mono<DocumentOwner> getDocumentOwner(Mono<Document> document) { return document.flatMap(p -> documentOwnerConsumer.getDocumentOwner(p.getDocumentOwnerId())); } private Mono<DocumentOwner> validateDocumentOwner(Mono<DocumentOwner> documentOwner) { return documentOwner.flatMap(do -> { if (do.getActive()) { return Mono.error(new BusinessException("Document Owner is Inactive")); } return Mono.just(do); }); } private DocumentOwnersetDocumentOwner(DocumentOwner documentOwner, Document document) { document.setDocumentOwner(documentOwner); return document; } private Mono<Document> saveDocument(Mono<Document> documentMono) { return documentMono.flatMap(documentRepository::save); } 

I use Netty, SpringBoot, spring WebFlux and Reactive Mongo Repository. But there are some problems:

1) I get an error: java.lang.IllegalStateException: only one connection recipient is allowed. Maybe because I use the same documentRequest for conversion and setDocumentOwner. I really do not know.

2) the setDocumentOwner method is not called. Thus, the document object to be saved is not updated. I believe that there may be a better way to implement this setDocumentOwner ().

thanks

+5
source share
1 answer

I do not quite understand the essence of the aspect of this issue. But it looks like you are trying to put reactive types together. This is what the reactor handles beautifully with operators.

Of course, there is a better way to handle this case, but a quick search in the Mono API makes you think about it :

 Mono<Document> document = ... Mono<DocumentOwner> docOwner = ... another = Mono.when(document, docOwner) .map(tuple -> { Document doc = tuple.getT1(); DocumentOwner owner = tuple.getT2(); if(owner.getActive()) { return Mono.error(new BusinessException("Document Owner is Inactive")); } doc.setDocumentOwner(owner); return doc; }) .flatMap(documentRepository::save); 
+2
source

Source: https://habr.com/ru/post/1269119/


All Articles