use of io.micronaut.core.bind.ExecutableBinder in project micronaut-core by micronaut-projects.
the class AbstractNettyWebSocketHandler method handleWebSocketFrame.
/**
* Handles WebSocket frame request.
*
* @param ctx The context
* @param msg The frame
*/
protected void handleWebSocketFrame(ChannelHandlerContext ctx, WebSocketFrame msg) {
if (msg instanceof TextWebSocketFrame || msg instanceof BinaryWebSocketFrame || msg instanceof ContinuationWebSocketFrame) {
if (messageHandler == null) {
if (LOG.isDebugEnabled()) {
LOG.debug("WebSocket bean [" + webSocketBean.getTarget() + "] received message, but defined no @OnMessage handler. Dropping frame...");
}
writeCloseFrameAndTerminate(ctx, CloseReason.UNSUPPORTED_DATA);
} else {
ByteBuf msgContent = msg.content().retain();
if (!msg.isFinalFragment()) {
frameBuffer.updateAndGet((buffer) -> {
if (buffer == null) {
buffer = ctx.alloc().compositeBuffer();
}
buffer.addComponent(true, msgContent);
return buffer;
});
return;
}
ByteBuf content;
CompositeByteBuf buffer = frameBuffer.getAndSet(null);
if (buffer == null) {
content = msgContent;
} else {
buffer.addComponent(true, msgContent);
content = buffer;
}
Argument<?> bodyArgument = this.getBodyArgument();
Optional<?> converted = ConversionService.SHARED.convert(content, bodyArgument);
content.release();
if (!converted.isPresent()) {
MediaType mediaType;
try {
mediaType = messageHandler.stringValue(Consumes.class).map(MediaType::of).orElse(MediaType.APPLICATION_JSON_TYPE);
} catch (IllegalArgumentException e) {
exceptionCaught(ctx, e);
return;
}
try {
converted = mediaTypeCodecRegistry.findCodec(mediaType).map(codec -> codec.decode(bodyArgument, new NettyByteBufferFactory(ctx.alloc()).wrap(msg.content())));
} catch (CodecException e) {
messageProcessingException(ctx, e);
return;
}
}
if (converted.isPresent()) {
Object v = converted.get();
NettyWebSocketSession currentSession = getSession();
ExecutableBinder<WebSocketState> executableBinder = new DefaultExecutableBinder<>(Collections.singletonMap(bodyArgument, v));
try {
BoundExecutable boundExecutable = executableBinder.bind(messageHandler.getExecutableMethod(), webSocketBinder, new WebSocketState(currentSession, originatingRequest));
Object result = invokeExecutable(boundExecutable, messageHandler);
if (Publishers.isConvertibleToPublisher(result)) {
Flux<?> flowable = Flux.from(instrumentPublisher(ctx, result));
flowable.subscribe(o -> {
}, error -> messageProcessingException(ctx, error), () -> messageHandled(ctx, session, v));
} else {
messageHandled(ctx, session, v);
}
} catch (Throwable e) {
messageProcessingException(ctx, e);
}
} else {
writeCloseFrameAndTerminate(ctx, CloseReason.UNSUPPORTED_DATA.getCode(), CloseReason.UNSUPPORTED_DATA.getReason() + ": " + "Received data cannot be converted to target type: " + bodyArgument);
}
}
} else if (msg instanceof PingWebSocketFrame) {
// respond with pong
PingWebSocketFrame frame = (PingWebSocketFrame) msg.retain();
ctx.writeAndFlush(new PongWebSocketFrame(frame.content()));
} else if (msg instanceof PongWebSocketFrame) {
if (pongHandler != null) {
ByteBuf content = msg.content();
WebSocketPongMessage message = new WebSocketPongMessage(NettyByteBufferFactory.DEFAULT.wrap(content));
NettyWebSocketSession currentSession = getSession();
ExecutableBinder<WebSocketState> executableBinder = new DefaultExecutableBinder<>(Collections.singletonMap(getPongArgument(), message));
try {
BoundExecutable boundExecutable = executableBinder.bind(pongHandler.getExecutableMethod(), webSocketBinder, new WebSocketState(currentSession, originatingRequest));
Object result = invokeExecutable(boundExecutable, pongHandler);
if (Publishers.isConvertibleToPublisher(result)) {
// delay the buffer release until the publisher has completed
content.retain();
Flux<?> flowable = Flux.from(instrumentPublisher(ctx, result));
flowable.subscribe(o -> {
}, error -> {
if (LOG.isErrorEnabled()) {
LOG.error("Error Processing WebSocket Pong Message [" + webSocketBean + "]: " + error.getMessage(), error);
}
exceptionCaught(ctx, error);
}, content::release);
}
} catch (Throwable e) {
if (LOG.isErrorEnabled()) {
LOG.error("Error Processing WebSocket Message [" + webSocketBean + "]: " + e.getMessage(), e);
}
exceptionCaught(ctx, e);
}
}
} else if (msg instanceof CloseWebSocketFrame) {
CloseWebSocketFrame cwsf = (CloseWebSocketFrame) msg;
handleCloseFrame(ctx, cwsf);
} else {
writeCloseFrameAndTerminate(ctx, CloseReason.UNSUPPORTED_DATA);
}
}
Aggregations