You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Currently the Views rendering (ReactViewsRenderer::render) cannot be async, if happens that it's, it fails with io.netty.util.IllegalReferenceCountException: refCnt: 0.
In my case I'm using micronaut-views-react and my Jasascript waits for a Java Mono.
Despite the docs says that's not supported, I was able to workaround that by implementing my own ViewFilter where I create a Publisher from the Writable returned by ReactViewsRenderer::render, basically the idea is to wait until Writer::write gets called.
So I wonder whether something like this can be implemented to support async "rendering".
I copied the ViewsFilter (removing some logic I didn't need in my case), and "delay" the response until the Writer::write gets called.
It's only waiting for the first call to write, but leaving subscriber.onComplete(); only in flush and close should support multiple calls. As micronaut-views-react does not call neither flush nor close I had to call subscriber.onComplete(); in write too.
public final Publisher<MutableHttpResponse<?>> doFilter(HttpRequest<?> request,
ServerFilterChain chain) {
return Flux.from(chain.proceed(request))
.switchMap(response -> {
Object body = response.body();
String view = viewsResolver.resolveView(request, response).orElse(null);
if (view == null || !view.equals("App")) { // Only use this for my App View
return Flux.just(response);
}
MediaType type = UTF8_HTML;
Optional<ViewsRenderer> optionalViewsRenderer = viewsRendererLocator.resolveViewsRenderer(view, type.getName(), body);
if(optionalViewsRenderer.isEmpty()) {
return Flux.just(response);
}
ModelAndView<?> modelAndView = new ModelAndView<>(view, ((ModelAndView<?>) body).getModel().orElse(null));
viewsModelDecorator.decorate(request, modelAndView);
Writable writable = optionalViewsRenderer.get().render(view, modelAndView.getModel().orElse(null), request);
return Flux.from((Publisher<String>) subscriber -> {
subscriber.onSubscribe(new Subscription() {
@Override
public void request(long n)
{
try
{
writable.writeTo(new Writer() {
@Override
public void write(char[] buffer, int off, int len) throws IOException
{
subscriber.onNext(String.valueOf(buffer));
subscriber.onComplete();
}
@Override
public void flush() throws IOException
{
subscriber.onComplete();
}
@Override
public void close() throws IOException
{
subscriber.onComplete();
}
});
}
catch (Exception e)
{
subscriber.onError(e);
}
}
@Override
public void cancel()
{
subscriber.onComplete();
}
});
}).map(b -> response.body(b).contentType(type));
});
}
The text was updated successfully, but these errors were encountered:
Feature description
Currently the Views rendering (
ReactViewsRenderer::render
) cannot be async, if happens that it's, it fails withio.netty.util.IllegalReferenceCountException: refCnt: 0
.In my case I'm using
micronaut-views-react
and my Jasascript waits for a JavaMono
.Despite the docs says that's not supported, I was able to workaround that by implementing my own
ViewFilter
where I create aPublisher
from theWritable
returned byReactViewsRenderer::render
, basically the idea is to wait untilWriter::write
gets called.So I wonder whether something like this can be implemented to support async "rendering".
I copied the
ViewsFilter
(removing some logic I didn't need in my case), and "delay" the response until theWriter::write
gets called.It's only waiting for the first call to
write
, but leavingsubscriber.onComplete();
only inflush
andclose
should support multiple calls. Asmicronaut-views-react
does not call neitherflush
norclose
I had to callsubscriber.onComplete();
inwrite
too.The text was updated successfully, but these errors were encountered: