This issue has been created
 
 
XWiki Platform / cid:jira-generated-image-avatar-6989112f-d070-4f90-8a1f-b5459443f1a6 XWIKI-24007 Open

Macro returning a MacroBlock is not displayed by the BlockAsyncRenderer

 
View issue   ยท   Add comment
 

Issue created

 
cid:jira-generated-image-avatar-9dff10f9-3628-49d6-b1fe-86b78bf99e71 Teodor Caras created this issue on 11/Feb/26 11:35
 
Summary: Macro returning a MacroBlock is not displayed by the BlockAsyncRenderer
Issue Type: cid:jira-generated-image-avatar-6989112f-d070-4f90-8a1f-b5459443f1a6 Bug
Affects Versions: 14.10.20, 17.10.2
Assignee: Unassigned
Attachments: image-2026-02-11-12-33-06-534.png, image-2026-02-11-12-33-40-114.png
Components: Rendering - Async
Created: 11/Feb/26 11:35
Priority: cid:jira-generated-image-static-major-5af967f6-7b3e-47e3-8f5d-474745a1c034 Major
Reporter: Teodor Caras
Description:

Created a kind-of-minimal example that can reproduce the issue. I tried to create the examples in Groovy components but didnt manage.

Macro class:

@Component
@Singleton
@Named("test123")
public class TestClass extends AbstractMacro<Object>
{
    @Inject
    private ComponentManager componentManager;

    @Inject
    private BlockAsyncRendererExecutor executor;

    public TestClass()
    {
        super("TestClass");
    }

    @Override
    public boolean supportsInlineMode()
    {
        return false;
    }

    @Override
    public List<Block> execute(Object parameters, String content, MacroTransformationContext context)
        throws MacroExecutionException
    {
        AsyncRendererConfiguration configuration = new AsyncRendererConfiguration();

        Block result = null;

        try {
            TestAsyncRenderer asyncRenderer =
                componentManager.getInstance(TestAsyncRenderer.class);
            asyncRenderer.initialize(this, context);
            result = executor.execute(asyncRenderer, configuration);
        } catch (JobException | RenderingException | ComponentLookupException e) {
            throw new RuntimeException(e);
        }
        return result instanceof CompositeBlock ? result.getChildren() : Collections.singletonList(result);
    }

    public List<Block> internalExecute()
    {
        return Collections.singletonList(new MacroBlock("info", Collections.emptyMap(), "Hello there", false));
    }
}

Async renderer class:

@Component(roles = TestAsyncRenderer.class)
public class TestAsyncRenderer extends AbstractBlockAsyncRenderer
{
    private TestClass testClass;

    private MacroTransformationContext context;

    private Syntax targetSyntax;

    public void initialize(TestClass testClass, MacroTransformationContext context)
    {
        this.context = context;
        this.testClass = testClass;
        this.targetSyntax = context.getTransformationContext().getTargetSyntax();
    }

    @Override
    protected Block execute(boolean async, boolean cached) throws RenderingException
    {
        List<Block> result = testClass.internalExecute();
        return new GroupBlock(result);
    }

    @Override
    public boolean isInline()
    {
        return false;
    }

    @Override
    public Syntax getTargetSyntax()
    {
        return targetSyntax;
    }

    @Override
    public List<String> getId()
    {
        return createId("test", "async", "renderer", RandomUtils.nextInt());
    }

    @Override
    public boolean isAsyncAllowed()
    {
        return true;
    }

    @Override
    public boolean isCacheAllowed()
    {
        return false;
    }
} 

Result:

The page containing the macro call `test123` is empty. If the page has the `async=false` query parameter, then the page displays the `info` macro as expected.

44578_image-2026-02-11-12-33-06-534.png

44577_image-2026-02-11-12-33-40-114.png

A workaround to this issue would be to render the `info` block macro into xwiki syntax and the parse it with the `MacroContentParser`.

Im also not sure if the macro returning the `MacroBlock` is problematic, the async renderer or if its a problem in the platform.