Hernán Tenjo
Hernán Tenjo

Reputation: 198

CompletableFuture in SpringBoot controller not working when method return type is void

I found the following issue trying to return a photo in a SpringBoot controller (Both methods have the same behavior but the second one return the CompletableFuture).

Method 1: Does not send anything to the outputStream and the response is an http 200.

@RequestMapping(value = FIND_PHOTO, method = RequestMethod.GET, produces = MediaType.IMAGE_JPEG_VALUE)
    public void getPhoto(HttpServletResponse response, @PathVariable String id) {
        ExceptionalConsumer<String, IOException> photoConsumer = photo -> {
            ByteArrayInputStream bais = new ByteArrayInputStream(Base64.getDecoder().decode(photo));
            response.setContentType(MediaType.IMAGE_JPEG_VALUE);
            StreamUtils.copy(bais, response.getOutputStream());
        };

        photoService.findPhoto(id) //This returns a CompletableFuture<String>
            .thenAccept(photoConsumer);
    }

Method 2: Return the data through the outputStream.

  @RequestMapping(value = FIND_PHOTO, method = RequestMethod.GET, produces = MediaType.IMAGE_JPEG_VALUE)
    public CompletableFuture<Void> getPhoto(HttpServletResponse response, @PathVariable String id) {
        ExceptionalConsumer<String, IOException> photoConsumer = photo -> {
            ByteArrayInputStream bais = new ByteArrayInputStream(Base64.getDecoder().decode(photo));
            response.setContentType(MediaType.IMAGE_JPEG_VALUE);
            StreamUtils.copy(bais, response.getOutputStream());
        };

        return photoService.findPhoto(id)
            .thenAccept(photoConsumer);
    }

I think spring has a kind of queue for CompletableFutures waiting to finish but if the return of the method is void, then spring is not aware of the async behaviour and then I'll need to call get() or join() by myself.

Could someone confirm if that is the real behaviour or if there is an error from my side?

Upvotes: 0

Views: 1922

Answers (1)

mrossini
mrossini

Reputation: 408

You should not really call get() on a CompletableFuture if you are not handling exceptions for that....

Spring does not have that queue. That is how it is supposed to work if you return nothing than you have to call join() and the returned object from the method will be T as of CompleatableFuture or you can just return the completable future, so your observations are correct.

Upvotes: 1

Related Questions