001/*
002 * Copyright 2002-2016 the original author or authors.
003 *
004 * Licensed under the Apache License, Version 2.0 (the "License");
005 * you may not use this file except in compliance with the License.
006 * You may obtain a copy of the License at
007 *
008 *      https://www.apache.org/licenses/LICENSE-2.0
009 *
010 * Unless required by applicable law or agreed to in writing, software
011 * distributed under the License is distributed on an "AS IS" BASIS,
012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
013 * See the License for the specific language governing permissions and
014 * limitations under the License.
015 */
016
017package org.springframework.web.servlet.mvc.method.annotation;
018
019import java.util.concurrent.CompletionStage;
020import java.util.function.Consumer;
021import java.util.function.Function;
022
023import org.springframework.core.MethodParameter;
024import org.springframework.lang.UsesJava8;
025import org.springframework.web.context.request.NativeWebRequest;
026import org.springframework.web.context.request.async.DeferredResult;
027import org.springframework.web.context.request.async.WebAsyncUtils;
028import org.springframework.web.method.support.AsyncHandlerMethodReturnValueHandler;
029import org.springframework.web.method.support.ModelAndViewContainer;
030
031/**
032 * Handles return values of type {@link CompletionStage} (implemented by
033 * {@link java.util.concurrent.CompletableFuture} for example).
034 *
035 * @author Sebastien Deleuze
036 * @since 4.2
037 * @deprecated as of 4.3 {@link DeferredResultMethodReturnValueHandler} supports
038 * CompletionStage return values via an adapter mechanism.
039 */
040@Deprecated
041@UsesJava8
042public class CompletionStageReturnValueHandler implements AsyncHandlerMethodReturnValueHandler {
043
044        @Override
045        public boolean supportsReturnType(MethodParameter returnType) {
046                return CompletionStage.class.isAssignableFrom(returnType.getParameterType());
047        }
048
049        @Override
050        public boolean isAsyncReturnValue(Object returnValue, MethodParameter returnType) {
051                return (returnValue != null && returnValue instanceof CompletionStage);
052        }
053
054        @Override
055        public void handleReturnValue(Object returnValue, MethodParameter returnType,
056                        ModelAndViewContainer mavContainer, NativeWebRequest webRequest) throws Exception {
057
058                if (returnValue == null) {
059                        mavContainer.setRequestHandled(true);
060                        return;
061                }
062
063                final DeferredResult<Object> deferredResult = new DeferredResult<Object>();
064                WebAsyncUtils.getAsyncManager(webRequest).startDeferredResultProcessing(deferredResult, mavContainer);
065
066                @SuppressWarnings("unchecked")
067                CompletionStage<Object> future = (CompletionStage<Object>) returnValue;
068                future.thenAccept(new Consumer<Object>() {
069                        @Override
070                        public void accept(Object result) {
071                                deferredResult.setResult(result);
072                        }
073                });
074                future.exceptionally(new Function<Throwable, Object>() {
075                        @Override
076                        public Object apply(Throwable ex) {
077                                deferredResult.setErrorResult(ex);
078                                return null;
079                        }
080                });
081        }
082
083}