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);
}
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());
}
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());
}
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);
}
}
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;
}
}
Aggregations