Search in sources :

Example 1 with DeferredResult

use of org.springframework.web.context.request.async.DeferredResult in project spring-framework by spring-projects.

the class ResponseBodyEmitterReturnValueHandler method handleReturnValue.

@Override
public void handleReturnValue(Object returnValue, MethodParameter returnType, ModelAndViewContainer mavContainer, NativeWebRequest webRequest) throws Exception {
    if (returnValue == null) {
        mavContainer.setRequestHandled(true);
        return;
    }
    HttpServletResponse response = webRequest.getNativeResponse(HttpServletResponse.class);
    ServerHttpResponse outputMessage = new ServletServerHttpResponse(response);
    if (returnValue instanceof ResponseEntity) {
        ResponseEntity<?> responseEntity = (ResponseEntity<?>) returnValue;
        response.setStatus(responseEntity.getStatusCodeValue());
        outputMessage.getHeaders().putAll(responseEntity.getHeaders());
        returnValue = responseEntity.getBody();
        if (returnValue == null) {
            mavContainer.setRequestHandled(true);
            outputMessage.flush();
            return;
        }
    }
    ServletRequest request = webRequest.getNativeRequest(ServletRequest.class);
    ShallowEtagHeaderFilter.disableContentCaching(request);
    ResponseBodyEmitterAdapter adapter = getAdapterFor(returnValue.getClass());
    if (adapter == null) {
        throw new IllegalStateException("Could not find ResponseBodyEmitterAdapter for return value type: " + returnValue.getClass());
    }
    ResponseBodyEmitter emitter = adapter.adaptToEmitter(returnValue, outputMessage);
    emitter.extendResponse(outputMessage);
    // Commit the response and wrap to ignore further header changes
    outputMessage.getBody();
    outputMessage.flush();
    outputMessage = new StreamingServletServerHttpResponse(outputMessage);
    DeferredResult<?> deferredResult = new DeferredResult<>(emitter.getTimeout());
    WebAsyncUtils.getAsyncManager(webRequest).startDeferredResultProcessing(deferredResult, mavContainer);
    HttpMessageConvertingHandler handler = new HttpMessageConvertingHandler(outputMessage, deferredResult);
    emitter.initialize(handler);
}
Also used : ServletRequest(javax.servlet.ServletRequest) HttpServletResponse(javax.servlet.http.HttpServletResponse) ServletServerHttpResponse(org.springframework.http.server.ServletServerHttpResponse) ServerHttpResponse(org.springframework.http.server.ServerHttpResponse) ServletServerHttpResponse(org.springframework.http.server.ServletServerHttpResponse) ResponseEntity(org.springframework.http.ResponseEntity) DeferredResult(org.springframework.web.context.request.async.DeferredResult)

Example 2 with DeferredResult

use of org.springframework.web.context.request.async.DeferredResult in project spring-framework by spring-projects.

the class DeferredResultReturnValueHandlerTests method deferredResultWitError.

@Test
public void deferredResultWitError() throws Exception {
    MethodParameter returnType = returnType("handleDeferredResult");
    DeferredResult<String> deferredResult = new DeferredResult<>();
    handleReturnValue(deferredResult, returnType);
    assertTrue(this.request.isAsyncStarted());
    assertFalse(WebAsyncUtils.getAsyncManager(this.webRequest).hasConcurrentResult());
    IllegalStateException ex = new IllegalStateException();
    deferredResult.setErrorResult(ex);
    assertTrue(WebAsyncUtils.getAsyncManager(this.webRequest).hasConcurrentResult());
    assertSame(ex, WebAsyncUtils.getAsyncManager(this.webRequest).getConcurrentResult());
}
Also used : MethodParameter(org.springframework.core.MethodParameter) DeferredResult(org.springframework.web.context.request.async.DeferredResult) Test(org.junit.Test)

Example 3 with DeferredResult

use of org.springframework.web.context.request.async.DeferredResult in project spring-framework by spring-projects.

the class DeferredResultReturnValueHandlerTests method deferredResult.

@Test
public void deferredResult() throws Exception {
    MethodParameter returnType = returnType("handleDeferredResult");
    DeferredResult<String> deferredResult = new DeferredResult<>();
    handleReturnValue(deferredResult, returnType);
    assertTrue(this.request.isAsyncStarted());
    assertFalse(WebAsyncUtils.getAsyncManager(this.webRequest).hasConcurrentResult());
    deferredResult.setResult("foo");
    assertTrue(WebAsyncUtils.getAsyncManager(this.webRequest).hasConcurrentResult());
    assertEquals("foo", WebAsyncUtils.getAsyncManager(this.webRequest).getConcurrentResult());
}
Also used : MethodParameter(org.springframework.core.MethodParameter) DeferredResult(org.springframework.web.context.request.async.DeferredResult) Test(org.junit.Test)

Example 4 with DeferredResult

use of org.springframework.web.context.request.async.DeferredResult in project chassis by Kixeye.

the class ActionInvokingWebSocket method onWebSocketBinary.

public void onWebSocketBinary(byte[] payload, int offset, int length) {
    try {
        // don't accept empty frames
        if (payload == null || length < 1) {
            throw new WebSocketServiceException(new ServiceError("EMPTY_ENVELOPE", "Empty envelope!"), "UNKNOWN", null);
        }
        // check if we need to do psk encryption
        byte[] processedPayload = pskFrameProcessor.processIncoming(payload, offset, length);
        if (processedPayload != payload) {
            payload = processedPayload;
            offset = 0;
            length = payload.length;
        }
        // get the envelope
        final WebSocketEnvelope envelope = new WebSocketEnvelope(serDe.deserialize(payload, offset, length, Envelope.class));
        // gets all the actions
        Collection<WebSocketAction> actions = mappingRegistry.getActionMethods(envelope.getAction());
        final AtomicInteger invokedActions = new AtomicInteger(0);
        // invokes them
        for (final WebSocketAction action : actions) {
            // get and validate type ID
            Class<?> messageClass = null;
            if (StringUtils.isNotBlank(envelope.getTypeId())) {
                messageClass = messageRegistry.getClassByTypeId(envelope.getTypeId());
            }
            // validate if action has a payload class that it needs
            if (action.getPayloadClass() != null && messageClass == null) {
                throw new WebSocketServiceException(new ServiceError("INVALID_TYPE_ID", "Unknown type ID!"), envelope.getAction(), envelope.getTransactionId());
            }
            // invoke this action if allowed
            if (action.canInvoke(webSocketSession, messageClass)) {
                invokedActions.incrementAndGet();
                final Object handler = handlerCache.get(action.getHandlerClass().getName());
                final Class<?> finalMessageClass = messageClass;
                ListenableFuture<DeferredResult<?>> invocation = serviceExecutor.submit(new Callable<DeferredResult<?>>() {

                    @Override
                    public DeferredResult<?> call() throws Exception {
                        // then invoke
                        return action.invoke(handler, new RawWebSocketMessage<>(envelope.getPayload(), finalMessageClass, messageValidator, serDe), envelope, webSocketSession);
                    }
                });
                Futures.addCallback(invocation, new FutureCallback<DeferredResult<?>>() {

                    public void onSuccess(DeferredResult<?> result) {
                        if (result != null) {
                            result.setResultHandler(new DeferredResultHandler() {

                                @Override
                                public void handleResult(Object result) {
                                    if (result instanceof Exception) {
                                        onFailure((Exception) result);
                                        return;
                                    }
                                    sendResponse(result);
                                }
                            });
                        }
                    }

                    public void onFailure(Throwable t) {
                        if (t instanceof InvocationTargetException) {
                            t = ((InvocationTargetException) t).getTargetException();
                        }
                        ServiceError error = ExceptionServiceErrorMapper.mapException(t);
                        if (error != null && !ExceptionServiceErrorMapper.VALIDATION_ERROR_CODE.equals(error.code)) {
                            logger.error("Unexpected exception throw while executing action [{}]", envelope.getAction(), t);
                        }
                        sendResponse(error);
                    }

                    public Future<Void> sendResponse(Object response) {
                        try {
                            return sendMessage(envelope.getAction(), envelope.getTransactionId(), response);
                        } catch (IOException | GeneralSecurityException e) {
                            logger.error("Unable to send message to channel", e);
                            return Futures.immediateFuture(null);
                        }
                    }
                }, responseExecutor);
            }
        }
        // make sure we actually invoked something
        if (invokedActions.get() < 1) {
            throw new WebSocketServiceException(new ServiceError("INVALID_ACTION_MAPPING", "No actions invoked."), envelope.getAction(), envelope.getTransactionId());
        }
    } catch (Exception e) {
        throw new RuntimeException(e);
    }
}
Also used : ServiceError(com.kixeye.chassis.transport.dto.ServiceError) Envelope(com.kixeye.chassis.transport.dto.Envelope) GeneralSecurityException(java.security.GeneralSecurityException) IOException(java.io.IOException) InvocationTargetException(java.lang.reflect.InvocationTargetException) InvocationTargetException(java.lang.reflect.InvocationTargetException) DeferredResultHandler(org.springframework.web.context.request.async.DeferredResult.DeferredResultHandler) AtomicInteger(java.util.concurrent.atomic.AtomicInteger) ListenableFuture(com.google.common.util.concurrent.ListenableFuture) Future(java.util.concurrent.Future) DeferredResult(org.springframework.web.context.request.async.DeferredResult)

Example 5 with DeferredResult

use of org.springframework.web.context.request.async.DeferredResult in project chassis by Kixeye.

the class WebSocketAction method invoke.

/**
     * Invokes this action.
     *
     * @param handler
     * @param message
     * @param envelope
     * @param session
     * @return
     * @throws MethodArgumentNotValidException
     *
     * @throws InvocationTargetException
     * @throws IllegalArgumentException
     * @throws IllegalAccessException
     */
public DeferredResult<?> invoke(Object handler, RawWebSocketMessage<?> message, WebSocketEnvelope envelope, WebSocketSession session) throws Exception {
    Object response = null;
    // invoke the method
    Object[] parameters = new Object[method.getParameterTypes().length];
    Integer payloadParamIndex = parameterTypes.get(ParameterType.ACTION_PAYLOAD);
    if (payloadParamIndex != null) {
        parameters[payloadParamIndex] = message.deserialize(this);
    }
    Integer sessionParamIndex = parameterTypes.get(ParameterType.WEB_SOCKET_SESSION);
    if (sessionParamIndex != null) {
        parameters[sessionParamIndex] = session;
    }
    Integer transactionParamIndex = parameterTypes.get(ParameterType.TRANSACTION_ID);
    if (transactionParamIndex != null) {
        parameters[transactionParamIndex] = envelope.getTransactionId();
    }
    Integer envelopeParamIndex = parameterTypes.get(ParameterType.ENVELOPE);
    if (envelopeParamIndex != null) {
        parameters[envelopeParamIndex] = envelope;
    }
    resolveCustomArguments(parameters, method, session, envelope);
    // now do actual invoke
    response = method.invoke(handler, parameters);
    // otherwise there was no error
    if (response != null) {
        // find a converter
        for (WebSocketResponseConverter converter : responseConverters.get()) {
            if (converter.canConvertResponse(response)) {
                return converter.convertToDeferredResult(response);
            }
        }
        // default to using the object as is
        final DeferredResult<Object> deferredResult = new DeferredResult<>();
        deferredResult.setResult(response);
        return deferredResult;
    } else {
        return null;
    }
}
Also used : WebSocketResponseConverter(com.kixeye.chassis.transport.websocket.responseconverter.WebSocketResponseConverter) DeferredResult(org.springframework.web.context.request.async.DeferredResult)

Aggregations

DeferredResult (org.springframework.web.context.request.async.DeferredResult)6 Test (org.junit.Test)2 MethodParameter (org.springframework.core.MethodParameter)2 ListenableFuture (com.google.common.util.concurrent.ListenableFuture)1 Envelope (com.kixeye.chassis.transport.dto.Envelope)1 ServiceError (com.kixeye.chassis.transport.dto.ServiceError)1 WebSocketResponseConverter (com.kixeye.chassis.transport.websocket.responseconverter.WebSocketResponseConverter)1 IOException (java.io.IOException)1 InvocationTargetException (java.lang.reflect.InvocationTargetException)1 GeneralSecurityException (java.security.GeneralSecurityException)1 Future (java.util.concurrent.Future)1 AtomicInteger (java.util.concurrent.atomic.AtomicInteger)1 ServletRequest (javax.servlet.ServletRequest)1 HttpServletResponse (javax.servlet.http.HttpServletResponse)1 ResponseEntity (org.springframework.http.ResponseEntity)1 ServerHttpResponse (org.springframework.http.server.ServerHttpResponse)1 ServletServerHttpResponse (org.springframework.http.server.ServletServerHttpResponse)1 DeferredResultHandler (org.springframework.web.context.request.async.DeferredResult.DeferredResultHandler)1 StandardServletAsyncWebRequest (org.springframework.web.context.request.async.StandardServletAsyncWebRequest)1 WebAsyncManager (org.springframework.web.context.request.async.WebAsyncManager)1