CAUSEWAY-3733: Migrate from PDFJS 3.x to 4.x
diff --git a/extensions/vw/pdfjs/wicket/integration/src/main/java/org/apache/causeway/extensions/pdfjs/wkt/integration/CausewayModuleExtPdfjsWicketIntegration.java b/extensions/vw/pdfjs/wicket/integration/src/main/java/org/apache/causeway/extensions/pdfjs/wkt/integration/CausewayModuleExtPdfjsWicketIntegration.java
index 487a1a0..c0ddea2 100644
--- a/extensions/vw/pdfjs/wicket/integration/src/main/java/org/apache/causeway/extensions/pdfjs/wkt/integration/CausewayModuleExtPdfjsWicketIntegration.java
+++ b/extensions/vw/pdfjs/wicket/integration/src/main/java/org/apache/causeway/extensions/pdfjs/wkt/integration/CausewayModuleExtPdfjsWicketIntegration.java
@@ -22,7 +22,6 @@
 import org.apache.wicket.protocol.http.WebApplication;
 
 import org.springframework.context.annotation.Configuration;
-import org.springframework.context.annotation.Import;
 
 import org.apache.causeway.viewer.wicket.model.causeway.WicketApplicationInitializer;
 
@@ -32,9 +31,6 @@
  * @since 2.0 {@index}
  */
 @Configuration
-@Import({
-
-})
 public class CausewayModuleExtPdfjsWicketIntegration
 implements WicketApplicationInitializer {
 
@@ -43,7 +39,10 @@
         // pdf.js cmap support
         val resourceGuard =
                 (SecurePackageResourceGuard) webApplication.getResourceSettings().getPackageResourceGuard();
+        // allows *.bcmap, otherwise Wicket throws 'Access denied to (static) package resource'
         resourceGuard.addPattern("+*.bcmap");
+        // allows *.mjs, otherwise Wicket throws 'Access denied to (static) package resource'
+        resourceGuard.addPattern("+*.mjs");
     }
 
     public static PdfJsVersion getPdfJsVersion() {
diff --git a/extensions/vw/pdfjs/wicket/integration/src/main/java/org/apache/causeway/extensions/pdfjs/wkt/integration/PdfJsVersion.java b/extensions/vw/pdfjs/wicket/integration/src/main/java/org/apache/causeway/extensions/pdfjs/wkt/integration/PdfJsVersion.java
index 8a50f87..ac5b13b 100644
--- a/extensions/vw/pdfjs/wicket/integration/src/main/java/org/apache/causeway/extensions/pdfjs/wkt/integration/PdfJsVersion.java
+++ b/extensions/vw/pdfjs/wicket/integration/src/main/java/org/apache/causeway/extensions/pdfjs/wkt/integration/PdfJsVersion.java
@@ -18,16 +18,19 @@
  */
 package org.apache.causeway.extensions.pdfjs.wkt.integration;
 
+import org.apache.wicket.markup.head.JavaScriptReferenceType;
+
 import lombok.Getter;
 import lombok.RequiredArgsConstructor;
 
 @RequiredArgsConstructor
 public enum PdfJsVersion {
-    //V2_X("v2plus", "pdfjs-dist/2.16.105"),
-    //V3_X("v2plus", "pdfjs-dist/3.11.174"),
-    V4_X("v2plus", "pdfjs-dist/4.2.67")
+    V2_X("v2x3x", "pdfjs-dist/2.16.105", JavaScriptReferenceType.TEXT_JAVASCRIPT),
+    V3_X("v2x3x", "pdfjs-dist/3.11.174", JavaScriptReferenceType.TEXT_JAVASCRIPT),
+    V4_X("v4", "pdfjs-dist/4.2.67", JavaScriptReferenceType.MODULE)
     ;
     @Getter private final String integrationScriptSuffix;
     @Getter private final String webjarPath;
+    @Getter private final JavaScriptReferenceType javascriptRefType;
 
 }
diff --git a/extensions/vw/pdfjs/wicket/integration/src/main/java/org/apache/causeway/extensions/pdfjs/wkt/integration/res/PdfJsIntegrationReference.java b/extensions/vw/pdfjs/wicket/integration/src/main/java/org/apache/causeway/extensions/pdfjs/wkt/integration/res/PdfJsIntegrationReference.java
index ab3081d..ad5ac3e 100644
--- a/extensions/vw/pdfjs/wicket/integration/src/main/java/org/apache/causeway/extensions/pdfjs/wkt/integration/res/PdfJsIntegrationReference.java
+++ b/extensions/vw/pdfjs/wicket/integration/src/main/java/org/apache/causeway/extensions/pdfjs/wkt/integration/res/PdfJsIntegrationReference.java
@@ -20,6 +20,7 @@
 
 import org.apache.wicket.markup.head.HeaderItem;
 import org.apache.wicket.markup.head.JavaScriptHeaderItem;
+import org.apache.wicket.markup.head.JavaScriptReferenceType;
 import org.apache.wicket.markup.head.OnDomReadyHeaderItem;
 import org.apache.wicket.request.resource.JavaScriptResourceReference;
 
@@ -40,15 +41,19 @@
 
     private PdfJsIntegrationReference() {
         super(PdfJsIntegrationReference.class,
-                String.format("pdfjs-integration-%s.js",
-                        CausewayModuleExtPdfjsWicketIntegration.getPdfJsVersion().getIntegrationScriptSuffix()));
+                String.format("pdfjs-integration-%s.%s",
+                        CausewayModuleExtPdfjsWicketIntegration.getPdfJsVersion().getIntegrationScriptSuffix(),
+                        CausewayModuleExtPdfjsWicketIntegration.getPdfJsVersion().getJavascriptRefType()==JavaScriptReferenceType.MODULE
+                        ? "mjs"
+                        : "js"));
     }
 
     /**
      * @return this resource reference singleton instance as header item
      */
     public static HeaderItem asHeaderItem() {
-        return JavaScriptHeaderItem.forReference(instance());
+        return JavaScriptHeaderItem.forReference(instance())
+                .setType(CausewayModuleExtPdfjsWicketIntegration.getPdfJsVersion().getJavascriptRefType());
     }
 
     public static OnDomReadyHeaderItem domReadyScript(
diff --git a/extensions/vw/pdfjs/wicket/integration/src/main/java/org/apache/causeway/extensions/pdfjs/wkt/integration/res/PdfJsReference.java b/extensions/vw/pdfjs/wicket/integration/src/main/java/org/apache/causeway/extensions/pdfjs/wkt/integration/res/PdfJsReference.java
index 63730eb..85cf2cf 100644
--- a/extensions/vw/pdfjs/wicket/integration/src/main/java/org/apache/causeway/extensions/pdfjs/wkt/integration/res/PdfJsReference.java
+++ b/extensions/vw/pdfjs/wicket/integration/src/main/java/org/apache/causeway/extensions/pdfjs/wkt/integration/res/PdfJsReference.java
@@ -20,6 +20,7 @@
 
 import org.apache.wicket.markup.head.HeaderItem;
 import org.apache.wicket.markup.head.JavaScriptHeaderItem;
+import org.apache.wicket.markup.head.JavaScriptReferenceType;
 
 import org.apache.causeway.extensions.pdfjs.wkt.integration.CausewayModuleExtPdfjsWicketIntegration;
 
@@ -38,15 +39,19 @@
         new PdfJsReference();
 
     private PdfJsReference() {
-        super(String.format("%s/build/pdf.min.js",
-                CausewayModuleExtPdfjsWicketIntegration.getPdfJsVersion().getWebjarPath()));
+        super(String.format("%s/build/pdf.min.%s",
+                CausewayModuleExtPdfjsWicketIntegration.getPdfJsVersion().getWebjarPath(),
+                CausewayModuleExtPdfjsWicketIntegration.getPdfJsVersion().getJavascriptRefType()==JavaScriptReferenceType.MODULE
+                    ? "mjs"
+                    : "js"));
     }
 
     /**
      * @return this resource reference singleton instance as header item
      */
     public static HeaderItem asHeaderItem() {
-        return JavaScriptHeaderItem.forReference(instance());
+        return JavaScriptHeaderItem.forReference(instance())
+                .setType(CausewayModuleExtPdfjsWicketIntegration.getPdfJsVersion().getJavascriptRefType());
     }
 
 }
diff --git a/extensions/vw/pdfjs/wicket/integration/src/main/java/org/apache/causeway/extensions/pdfjs/wkt/integration/res/PdfJsWorkerReference.java b/extensions/vw/pdfjs/wicket/integration/src/main/java/org/apache/causeway/extensions/pdfjs/wkt/integration/res/PdfJsWorkerReference.java
index d3657d8..e450344 100644
--- a/extensions/vw/pdfjs/wicket/integration/src/main/java/org/apache/causeway/extensions/pdfjs/wkt/integration/res/PdfJsWorkerReference.java
+++ b/extensions/vw/pdfjs/wicket/integration/src/main/java/org/apache/causeway/extensions/pdfjs/wkt/integration/res/PdfJsWorkerReference.java
@@ -20,6 +20,7 @@
 
 import org.apache.wicket.markup.head.HeaderItem;
 import org.apache.wicket.markup.head.JavaScriptHeaderItem;
+import org.apache.wicket.markup.head.JavaScriptReferenceType;
 import org.apache.wicket.request.Url;
 import org.apache.wicket.request.cycle.RequestCycle;
 
@@ -41,15 +42,19 @@
         new PdfJsWorkerReference();
 
     private PdfJsWorkerReference() {
-        super(String.format("%s/build/pdf.worker.min.js",
-                CausewayModuleExtPdfjsWicketIntegration.getPdfJsVersion().getWebjarPath()));
+        super(String.format("%s/build/pdf.worker.min.%s",
+                CausewayModuleExtPdfjsWicketIntegration.getPdfJsVersion().getWebjarPath(),
+                CausewayModuleExtPdfjsWicketIntegration.getPdfJsVersion().getJavascriptRefType()==JavaScriptReferenceType.MODULE
+                    ? "mjs"
+                    : "js"));
     }
 
     /**
      * @return this resource reference singleton instance as header item
      */
     public static HeaderItem asHeaderItem() {
-        return JavaScriptHeaderItem.forReference(instance());
+        return JavaScriptHeaderItem.forReference(instance())
+                .setType(CausewayModuleExtPdfjsWicketIntegration.getPdfJsVersion().getJavascriptRefType());
     }
 
     public static String workerUrl() {
diff --git a/extensions/vw/pdfjs/wicket/integration/src/main/java/org/apache/causeway/extensions/pdfjs/wkt/integration/res/pdfjs-integration-v2plus.js b/extensions/vw/pdfjs/wicket/integration/src/main/java/org/apache/causeway/extensions/pdfjs/wkt/integration/res/pdfjs-integration-v2x3x.js
similarity index 100%
rename from extensions/vw/pdfjs/wicket/integration/src/main/java/org/apache/causeway/extensions/pdfjs/wkt/integration/res/pdfjs-integration-v2plus.js
rename to extensions/vw/pdfjs/wicket/integration/src/main/java/org/apache/causeway/extensions/pdfjs/wkt/integration/res/pdfjs-integration-v2x3x.js
diff --git a/extensions/vw/pdfjs/wicket/integration/src/main/java/org/apache/causeway/extensions/pdfjs/wkt/integration/res/pdfjs-integration-v4.mjs b/extensions/vw/pdfjs/wicket/integration/src/main/java/org/apache/causeway/extensions/pdfjs/wkt/integration/res/pdfjs-integration-v4.mjs
new file mode 100644
index 0000000..d04bf76
--- /dev/null
+++ b/extensions/vw/pdfjs/wicket/integration/src/main/java/org/apache/causeway/extensions/pdfjs/wkt/integration/res/pdfjs-integration-v4.mjs
@@ -0,0 +1,426 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one
+ *  or more contributor license agreements.  See the NOTICE file
+ *  distributed with this work for additional information
+ *  regarding copyright ownership.  The ASF licenses this file
+ *  to you under the Apache License, Version 2.0 (the
+ *  "License"); you may not use this file except in compliance
+ *  with the License.  You may obtain a copy of the License at
+ *
+ *        http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing,
+ *  software distributed under the License is distributed on an
+ *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ *  KIND, either express or implied.  See the License for the
+ *  specific language governing permissions and limitations
+ *  under the License.
+ */
+;(function ($, undefined) {
+
+    'use strict';
+
+	if (!pdfjsLib.getDocument) {
+	  console.error("Missing pdf.mjs prerequisites.");
+	  exit;
+	}
+
+    if (typeof(WicketStuff) !== 'object') {
+        window.WicketStuff = {};
+    }
+
+    if (typeof(WicketStuff.PDFJS) === 'object') {
+        return;
+    }
+
+    WicketStuff.PDFJS = {
+        Topic: {
+            TOTAL_PAGES: 'Wicket.PDFJS.TotalPages',
+            NEXT_PAGE: 'Wicket.PDFJS.NextPage',
+            PREVIOUS_PAGE: 'Wicket.PDFJS.PreviousPage',
+            PAGE_TO: 'Wicket.PDFJS.PageTo',
+            ZOOM_TO: 'Wicket.PDFJS.ZoomTo',
+            HEIGHT_TO: 'Wicket.PDFJS.HeightTo',
+            CURRENT_PAGE: 'Wicket.PDFJS.CurrentPage',
+            CURRENT_ZOOM : 'Wicket.PDFJS.CurrentZoom',
+            CURRENT_HEIGHT : 'Wicket.PDFJS.CurrentHeight',
+            CURRENT_PRINT_PAGE : 'Wicket.PDFJS.CurrentPrintPage',
+            PRINT : 'Wicket.PDFJS.Print'
+        },
+
+        init: function (config) {
+
+            pdfjsLib.GlobalWorkerOptions.workerSrc = config.workerUrl;
+
+            var pdfDoc = null,
+                pageNum = config.initialPage || 1,
+                pageRendering = false,
+                pageNumPending = null,
+                scaleValue = config.initialScale || "1.0",
+                scale = 1.0,    // will be initialized below, based on config.initialScale
+                autoScale = "", // will be initialized below, based on config.initialScale
+                canvas = $('#'+config.canvasId)[0],
+                canvasDiv = $(canvas).parent(),
+                ctx = canvas.getContext('2d'),
+                abortingPrinting = false;
+
+            var scaleValueFloat = parseFloat(scaleValue);
+            if (isNaN(scaleValueFloat)){
+                autoScale = config.initialScale;
+            } else {
+                scale = parseFloat(scaleValueFloat.toFixed(2));
+            }
+
+            var MIN_SCALE = 0.25;
+            var MAX_SCALE = 10.0;
+            var DEFAULT_SCALE_DELTA = 1.1;
+            var MAX_AUTO_SCALE = 1.25;
+
+            var container = $('#'+canvas.id).closest('.pdfPanel');
+
+            $(canvasDiv).height(config.initialHeight || 800);
+            canvas.height = 2000;
+            canvas.width = container.width();
+
+            $(window).on('resize', function(){
+                  var win = $(this); //this = window
+
+                  var container = $('#'+canvas.id).closest('.pdfPanel');
+
+                  canvas.width = container.width();
+
+                  queueRenderPage(pageNum);
+
+            });
+
+
+            function printDocument() {
+                pageRendering = true;
+                abortingPrinting = false;
+                var pages = pdfDoc.numPages;
+
+                var pc = $('<div/>');
+                pc.attr('id', 'pdf-js-print-container');
+                $('body').append(pc);
+
+                for (var i = 0; i < pages; i++){
+                   var wrapper = $('<div/>');
+                   pc.append(wrapper);
+                }
+
+                for (var i = 1; i <= pages; i++){
+                    printPage(i, pages);
+                }
+            }
+
+            function cleanUp(error) {
+                if (abortingPrinting) { return; }
+
+                if (error) {
+                    abortingPrinting = true;
+                    var printError = -1; // use -1 to indicate error printing
+                    Wicket.Event.publish(WicketStuff.PDFJS.Topic.CURRENT_PRINT_PAGE, printError, {"canvasId": config.canvasId});
+                }
+
+                pageRendering = false;
+                var body = $('body').removeAttr('pdf-js-printing');
+                $('#pdf-js-print-container').remove();
+            }
+
+
+            function printPage(num, total) {
+
+                // Using promise to fetch the page
+                pdfDoc.getPage(num).then(function(page) {
+                    if (abortingPrinting) { return; }
+
+                    var viewport = page.getViewport({scale: 1});
+                    var offScreenCanvas = $('<canvas/>')[0];
+                    offScreenCanvas.width = viewport.width;
+                    offScreenCanvas.height = viewport.height;
+                    var offScreenCanvasCtx = offScreenCanvas.getContext('2d');
+
+                    // Render PDF page into canvas context
+                    var renderContext = {
+                        canvasContext: offScreenCanvasCtx,
+                        viewport: viewport
+                    };
+
+                    var renderTask = page.render(renderContext);
+                    // Wait for rendering to finish
+                    renderTask.promise.then(function () {
+                        var img = $('<img/>')[0];
+                        $(img).width(viewport.width);
+                        $(img).height(viewport.height);
+
+                        img.onload = function() {
+                            if (abortingPrinting) { return; }
+
+                            // image loaded so append to appropriate div.
+                            var wrapper = $('#pdf-js-print-container > div:nth-child(' + num + ')');
+                            var renderedPages = 0;
+
+                            if (wrapper.length) {
+                                wrapper.append(img);
+                                // get count of loaded images so that once all loaded we can print
+                                renderedPages = $('#pdf-js-print-container img').length;
+                                // publish for progress bar
+                                Wicket.Event.publish(WicketStuff.PDFJS.Topic.CURRENT_PRINT_PAGE, renderedPages, {"canvasId": config.canvasId});
+                            }
+
+                            if (renderedPages === total) {
+                                try {
+                                   $('body').attr('pdf-js-printing', true);
+                                   print.call(window);
+                                }
+                                catch(e) {
+                                   cleanUp(true);
+                                }
+                                finally{
+                                   //  will do nothing if we have already aborted
+                                   cleanUp(false);
+                                }
+                            } else if (renderedPages === 0 || renderedPages > total) {
+                                // should be at least one so abort printing
+                                // don't see how can ever be greater but treat as error as well;
+                                cleanUp(true);
+                            }
+                        }
+
+                        img.onerror = function() {
+                            if (abortingPrinting) { return; }
+                            cleanUp(true);
+                        }
+
+                        img.src = offScreenCanvas.toDataURL();
+                    });
+                   });
+            }
+
+
+            /**
+             * If another page rendering in progress, waits until the rendering is
+             * finished. Otherwise, executes rendering immediately.
+             */
+            function queueRenderPage(num) {
+                if (pageRendering) {
+                    pageNumPending = num;
+                } else {
+                    renderPage(num);
+                }
+            }
+
+            function renderIfRescaled(newScale, newAutoScale){
+                if (newAutoScale && newAutoScale !== autoScale) {
+                    autoScale = newAutoScale;
+
+                    queueRenderPage(pageNum);
+                }
+                else if (newScale !== scale){
+                    autoScale = "";
+                    scale = newScale;
+
+                    queueRenderPage(pageNum);
+                }
+            }
+
+            function calculateAutoScale(page) {
+
+                var viewport = page.getViewport({scale: 1});
+                var pageWidth = viewport.width;
+                var pageHeight = viewport.height;
+
+                var containerWidth = $(canvasDiv).width();
+                var containerHeight = $(canvasDiv).height();
+
+                //console.log("page      (width, height) = (" + pageWidth      + "," + pageHeight      + ")")
+                //console.log("container (width, height) = (" + containerWidth + "," + containerHeight + ")")
+
+                var pageWidthScale = containerWidth / pageWidth;
+                var pageHeightScale = containerHeight / pageHeight;
+
+                switch (autoScale) {
+                case 'page-actual':
+                    return 0.99; // if set to 1, then see two 100% in the drop-down; not sure why...
+                case 'page-width':
+                    return pageWidthScale;
+                case 'page-height':
+                    return pageHeightScale;
+                case 'page-fit':
+                    return Math.min(pageWidthScale, pageHeightScale);
+                case 'auto':
+                    var isLandscape = pageWidth > pageHeight;
+                    var horizontalScale = isLandscape ? Math.min(pageHeightScale, pageWidthScale) : pageWidthScale;
+                    return Math.min(MAX_AUTO_SCALE, horizontalScale);
+                default:
+                    return scale;
+                }
+            }
+
+            /**
+             * Displays previous page.
+             */
+            Wicket.Event.subscribe(WicketStuff.PDFJS.Topic.PREVIOUS_PAGE, function (jqEvent, data) {
+                if (config.canvasId !== data.canvasId || pageNum <= 1) {
+                    return;
+                }
+                pageNum--;
+
+                queueRenderPage(pageNum);
+            });
+
+            /**
+             * Displays next page.
+             */
+            Wicket.Event.subscribe(WicketStuff.PDFJS.Topic.NEXT_PAGE, function (jqEvent, data) {
+                if (config.canvasId !== data.canvasId || pageNum >= pdfDoc.numPages) {
+                    return;
+                }
+                pageNum++;
+
+                queueRenderPage(pageNum);
+            });
+
+            /**
+             * Displays selected page
+             */
+            Wicket.Event.subscribe(WicketStuff.PDFJS.Topic.PAGE_TO, function (jqEvent, data) {
+                if (config.canvasId !== data.canvasId) {
+                    return;
+                }
+                if (!data.page || data.page > pdfDoc.numPages || data.page < 1 || data.page === pageNum) {
+                    return;
+                }
+                pageNum = data.page;
+
+                queueRenderPage(pageNum);
+            });
+
+             Wicket.Event.subscribe(WicketStuff.PDFJS.Topic.ZOOM_TO, function (jqEvent, data) {
+                  if (config.canvasId !== data.canvasId || !data.scale) {
+                      return;
+                  }
+
+                  scaleValue = data.scale;
+
+                  var scaleValueFloat = parseFloat(scaleValue);
+                  var newScale;
+                  var newAutoScale;
+                  if (isNaN(scaleValueFloat)){
+                      newAutoScale = scaleValue;
+                  }
+                  else {
+                      newScale = parseFloat(scaleValueFloat.toFixed(2));
+                  }
+
+                  renderIfRescaled(newScale, newAutoScale);
+              });
+
+             Wicket.Event.subscribe(WicketStuff.PDFJS.Topic.HEIGHT_TO, function (jqEvent, data) {
+                  if (config.canvasId !== data.canvasId || !data.height) {
+                      return;
+                  }
+                  var previousHeight = $(canvasDiv).height();
+                  var newHeight = data.height;
+
+                  $(canvasDiv).height(newHeight);
+
+                  queueRenderPage(pageNum);
+
+              });
+
+            /**
+             * Print document
+             */
+            Wicket.Event.subscribe(WicketStuff.PDFJS.Topic.PRINT, function (jqEvent, data) {
+                 if (config.canvasId !== data.canvasId) {
+                    return;
+                 }
+
+                 if (pageRendering) {
+                    // rendering or printing
+                    return;
+                 }
+
+                 printDocument();
+            });
+
+            function boundedPageNumber(num) {
+                if(num > pdfDoc.numPages) {
+                    return pdfDoc.numPages;
+                }
+                if(num < 1) {
+                    return 1;
+                }
+                return num;
+            }
+
+            /**
+             * Get page info from document, resize canvas accordingly, and render page.
+             * @param num Page number.
+             */
+            function renderPage(num_) {
+	
+				const num = boundedPageNumber(num_);
+	
+				// console.log("renderPage: " + num);
+	
+                pageRendering = true;
+                // Using promise to fetch the page
+                pdfDoc.getPage(num).then(function(page) {
+
+                    if (autoScale) {
+                        scale = calculateAutoScale(page);
+                    }
+                    
+					//console.log("page ready for rendering, scale: " + scale);
+
+                    var viewport = page.getViewport({scale: scale});
+                    canvas.height = viewport.height;
+                    canvas.width = viewport.width;
+                    
+                    //console.log("viewport.height: " + viewport.height);
+                    //console.log("viewport.width: " + viewport.width);
+
+                    // Render PDF page into canvas context
+                    var renderContext = {
+                        canvasContext: ctx,
+                        viewport: viewport
+                    };
+                    var renderTask = page.render(renderContext);
+                    // Wait for rendering to finish
+                    renderTask.promise.then(function () {
+                        pageRendering = false;
+                        if (pageNumPending !== null) {
+                            // New page rendering is pending
+                                renderPage(pageNumPending);
+                                pageNumPending = null;
+                            }
+                        });
+                        Wicket.Event.publish(WicketStuff.PDFJS.Topic.CURRENT_PAGE, pageNum, {"canvasId": config.canvasId});
+                        Wicket.Event.publish(WicketStuff.PDFJS.Topic.CURRENT_ZOOM, scaleValue, {"canvasId": config.canvasId});
+                        Wicket.Event.publish(WicketStuff.PDFJS.Topic.CURRENT_HEIGHT, $(canvasDiv).height(), {"canvasId": config.canvasId});
+                });
+            }
+
+			//console.log("url: " + config.documentUrl);
+			//console.log("cMapUrl: " + config.cmapsUrl);
+			//console.log("canvasId: " + config.canvasId);
+
+            /**
+             * Asynchronously downloads PDF.
+             */
+	        const loadingTask = pdfjsLib.getDocument({
+	          url: config.documentUrl,
+	          cMapUrl: config.cmapsUrl,
+	          cMapPacked: true,
+	          enableXfa: false,
+	        });
+            loadingTask.promise.then(function (pdfDoc_) {
+                pdfDoc = pdfDoc_;
+                Wicket.Event.publish(WicketStuff.PDFJS.Topic.TOTAL_PAGES, pdfDoc.numPages, {"canvasId": config.canvasId});
+                renderPage(pageNum);
+            });
+        }
+    };
+})(jQuery);
diff --git a/viewers/wicket/viewer/src/main/java/org/apache/causeway/viewer/wicket/viewer/wicketapp/config/WebjarsInitWkt.java b/viewers/wicket/viewer/src/main/java/org/apache/causeway/viewer/wicket/viewer/wicketapp/config/WebjarsInitWkt.java
index 168faeb..150dd9b 100644
--- a/viewers/wicket/viewer/src/main/java/org/apache/causeway/viewer/wicket/viewer/wicketapp/config/WebjarsInitWkt.java
+++ b/viewers/wicket/viewer/src/main/java/org/apache/causeway/viewer/wicket/viewer/wicketapp/config/WebjarsInitWkt.java
@@ -20,8 +20,14 @@
 
 import org.apache.wicket.protocol.http.WebApplication;
 
+import org.springframework.boot.web.server.MimeMappings;
+import org.springframework.boot.web.server.WebServerFactoryCustomizer;
+import org.springframework.boot.web.servlet.server.AbstractServletWebServerFactory;
+import org.springframework.boot.web.servlet.server.ConfigurableServletWebServerFactory;
 import org.springframework.context.annotation.Configuration;
+import org.springframework.context.annotation.Import;
 
+import org.apache.causeway.commons.internal.base._Casts;
 import org.apache.causeway.viewer.wicket.model.causeway.WicketApplicationInitializer;
 
 import de.agilecoders.wicket.webjars.WicketWebjars;
@@ -29,6 +35,9 @@
 import de.agilecoders.wicket.webjars.settings.WebjarsSettings;
 
 @Configuration
+@Import({
+    WebjarsInitWkt.JavaScriptModuleMimeSupport.class
+})
 public class WebjarsInitWkt implements WicketApplicationInitializer {
 
     @Override
@@ -37,4 +46,18 @@
         WicketWebjars.install(webApplication, settings);
     }
 
+    @Configuration
+    public static class JavaScriptModuleMimeSupport
+    implements WebServerFactoryCustomizer<ConfigurableServletWebServerFactory> {
+        @Override
+        public void customize(final ConfigurableServletWebServerFactory factory) {
+            var mappings = _Casts.castTo(AbstractServletWebServerFactory.class, factory)
+                .map(AbstractServletWebServerFactory::getMimeMappings)
+                .orElseGet(()->new MimeMappings(MimeMappings.DEFAULT));
+            mappings.remove("mjs");
+            mappings.add("mjs", "application/javascript;charset=utf-8");
+            factory.setMimeMappings(mappings);
+        }
+    }
+
 }