Search code examples
javaspring-bootwicketrenderer

Wicket 9: usage of JavaScriptFilteredIntoFooterHeaderResponse seems to cause trouble with renderHead


I'm using Wicket 9 by including wicket-spring-boot-starter 3.0.4 .

In my demo project, it's necessary to put JavaScript at the end of <body>. So I followed the explanations in https://ci.apache.org/projects/wicket/guide/9.x/single.html#_put_javascript_inside_page_body

I also added resources (CSS and JS) via an implementation of Component#renderHead(IHeaderReponse) in my page.

All works as expected with Wicket 8 (from wicket-spring-boot-starter 2.1.9).

With Wicket 9 , to make my App run, I first put webApplication.getCspSettings().blocking().disabled(); in WicketApplicationInitConfiguration#init(WebApplication). My App starts, but the generated Page doesn't contain a <head> section, and so the app doesn't work because of missing resources.

To make the <head> element appear in my page with all references, I commented out all code that refers to the rendering of JavaScript in <body>. But my app doesn't work with this "workaround".

Am I doing something wrong?

@ApplicationInitExtension
public class DemoWicketInitializer implements WicketApplicationInitConfiguration {
    @Override
    public void init(WebApplication webApplication) {

        webApplication.getCspSettings().blocking().disabled();

        webApplication.getHeaderResponseDecorators().add(response -> new ResourceAggregator(
                new JavaScriptFilteredIntoFooterHeaderResponse(response, "scripts")));

        webApplication.getMarkupSettings().setDefaultMarkupEncoding("UTF-8");    
    }
}
@WicketHomePage
public class MyPage extends WebPage {

    @Override
    public void renderHead(IHeaderResponse response) {
        super.renderHead(response);

        response.render(JavaScriptHeaderItem.forUrl(
            "https://api.mapbox.com/mapbox-gl-js/v1.8.1/mapbox-gl.js"));
        response.render(JavaScriptHeaderItem.forUrl(
            "https://api.mapbox.com/mapbox-gl-js/plugins/mapbox-gl-draw/v1.0.9/mapbox-gl-draw.js"));

        // this piece of JS has to appear in <body>. ################################
        response.render(JavaScriptHeaderItem.forReference(new PackageResourceReference(getClass(),
                "js/demoMapbox.js")));

        response.render(CssHeaderItem.forUrl(
            "https://api.mapbox.com/mapbox-gl-js/v1.8.1/mapbox-gl.css"));
        response.render(CssHeaderItem.forUrl(
            "https://api.mapbox.com/mapbox-gl-js/plugins/mapbox-gl-draw/v1.0.9/mapbox-gl-draw.css"));
        }

    public MyPage(PageParameters parameters) {
            // some components

            add(new HeaderResponseContainer("scriptBlock", "scripts"));
    }

}
<?xml version="1.0" encoding="UTF-8"?>
<html xmlns="http://www.w3.org/1999/xhtml" xmlns:wicket="http://wicket.apache.org" lang="de">
<head>
</head>
<body>
<h1>Wicket und Mapbox</h1>

<div id="ndsmap" style="width: 800px; height: 500px"></div>

<a href="#" wicket:id="sendPostDrawingAction">als POST</a><br>

<h4>Zeichnung als GeoJSON</h4>
<p wicket:id="drawingJson"></p>
<h4>Polygone WGS84</h4>
<p wicket:id="geoWGS84"></p>
<h4>Polygone UTM32N</h4>
<p wicket:id="geoUTM32N"></p>

<wicket:container wicket:id="scriptBlock"/>

</body>
</html>
public class ServletInitializer extends SpringBootServletInitializer {

    @Override
    protected SpringApplicationBuilder configure(SpringApplicationBuilder application) {
        return application.sources(DemoWicketMapboxApplication.class);
    }

}

Solution

  • it looks like CSP mechanism is interfering with JavaScriptFilteredIntoFooterHeaderResponse. I will open an issue about this on JIRA. In the meantime as workaround you can use setHeaderResponseDecorator (which is deprecated) instead of getHeaderResponseDecorators:

    setHeaderResponseDecorator(response -> new ResourceAggregator(
                new JavaScriptFilteredIntoFooterHeaderResponse(response, "scripts")));
    

    This should make your app work.

    UPDATE

    as pointed out on jira this is not a bug. Since now we already add a ResourceAggregator by default with CSP, to add a further response decorator we should do the following:

    getHeaderResponseDecorators().add(response -> 
     new JavaScriptFilteredIntoFooterHeaderResponse(response, "scripts"));
    

    We will update the documentation for Wicket 9.x and its migration guide accordingly.