Home > Enterprise >  Transfer file and store file id (elasticsearch) via webflux (spring-boot)
Transfer file and store file id (elasticsearch) via webflux (spring-boot)

Time:06-17

I'm trying to transfer files to a third party service via webflux and store the file ids in a elasticsearch. Files are transferred and saved, but the id is not attached to the entity.

controller:

@PostMapping(value = "upload", consumes = MediaType.MULTIPART_FORM_DATA_VALUE, produces = MediaType.APPLICATION_JSON_VALUE)
    public Flux<String> store(@RequestParam(required = false) String orderId, @RequestPart("file") Flux<FilePart> files){
        return imageService.store(orderId, files);
    }

service:

    public Flux<String> store(String orderId, Flux<FilePart> files) {
        return marketService.findById(orderId)
                .filter(Objects::nonNull)
                .flatMapMany(order -> {
                    return files.ofType(FilePart.class).flatMap(file -> save(orderId, file));
                });
    }

    private Mono<String> save(String orderId, FilePart file) {
        return file.content()
                .flatMap(dataBuffer -> {
                    byte[] bytes = new byte[dataBuffer.readableByteCount()];
                    dataBuffer.read(bytes);
                    String image = storeApi.upload(bytes, file.filename());
                    DataBufferUtils.release(dataBuffer);
                    return Mono.just(image);
                })
                .doOnNext(image -> marketService.addImages(orderId, image))
                .last();
    }

marketService.addImages:

    public Mono<Order> addImages(String id, String image){
        log.info("addImages: id={}, image={}", id, image);
        return orderRepository
                .findById(id)
                .doOnNext(order -> {
                    if(order.getProduct().getImages() == null){
                        order.getProduct().setImages(new ArrayList<>());
                    }
                    order.getProduct().getImages().add(image);
                })
                .flatMap(this::create);
    }

The code in the doOnNext and flatMap block in method (addImages) does not work. In doing so, calling the method (addImages) from the controller works fine. Tell me please what i'm missing.

CodePudding user response:

I think I have found a solution. I changed the operation from doOnNext to flatMap as per this solution: Spring Webflux Proper Way To Find and Save

public Mono<OrderPostgres> store(String orderId, Flux<FilePart> files) {
        return marketService.findById(orderId)
                .filter(Objects::nonNull)
                .flatMapMany(order -> {
                    return files.ofType(FilePart.class)
                            .flatMap(file -> save(orderId, file))
                            .collectList();
                })
                .flatMap(image -> marketService.addImages(orderId, image))
                .then(Mono.empty());
    }

    private Flux<String> save(String orderId, FilePart file) {
        return file.content()
                .log()
                .flatMap(dataBuffer -> {
                    byte[] bytes = new byte[dataBuffer.readableByteCount()];
                    dataBuffer.read(bytes);
                    String image = storeApi.upload(bytes, file.filename());
                    DataBufferUtils.release(dataBuffer);
                    return Flux.just(image);
                }).switchIfEmpty(Flux.empty());
    }

public Mono<OrderPostgres> addImages(String id, List<String> images){
        log.info("### addImage: id={}, images={}", id, images);

        Mono<OrderPostgres> byId = orderRepository.findById(id);
        return byId
                .flatMap(order -> {
                    if (order.getImages() == null) {
                        order.setImages(new ArrayList<>());
                    }
                    order.getImages().addAll(images);
                    return orderRepository.save(order);
                }).then(Mono.empty());
    }
  • Related