Vaadin 10 rendering is missing with Jetty embedded server

I managed to run my Vaadin 10 sample application within an embedded Jetty 9 server. But the resulting page just contains invisible “code” and no visible rendering.
I get an empty page. Showing the page’s source I find something like below.
Something seems to be missing that applies this code to a proper HTML rendering.

<!doctype html><html lang="en"><head><meta http-equiv="Content-Type" content="text/html; charset=utf-8"><meta http-equiv="X-UA-Compatible" content="IE=edge"><base href="."><meta name="viewport" content="width=device-width, initial-scale=1.0"><style type="text/css">body {height:100vh;width:100vw;margin:0;}.v-reconnect-dialog {position: absolute;top: 1em;right: 1em;border: 1px solid black;padding: 1em;z-index: 10000;}.v-system-error {color: red;background: white;position: absolute;top: 1em;right: 1em;border: 1px solid black;padding: 1em;z-index: 10000;pointer-events: auto;}</style><script type="text/javascript">//<![CDATA[
(function() {	var apps = {};	var widgetsets = {};					var log;	if (typeof console === undefined || !window.location.search.match(/[&?]
debug(&|$)/)) {		/* If no console.log present, just use a no-op */		log = function() {};	} else if (typeof console.log === "function") {		/* If it's a function, use it with apply */		log = function() {			console.log.apply(console, arguments);		};	} else {		/* In IE, its a native function for which apply is not defined, but it works		 without a proper 'this' reference */		log = console.log;	}		var isWidgetsetLoaded = function(widgetset) {		var className = widgetset.replace(/\./g, "_");		return (typeof window[className]
) != "undefined";	};		var loadWidgetset = function(url, widgetset) {		if (widgetsets[widgetset]
) {			return;		}		log("load widgetset", url, widgetset);		setTimeout(function() {			if (!isWidgetsetLoaded(widgetset)) {				alert("Failed to load the widgetset: " + url);			}		}, 15000);			var scriptTag = document.createElement('script');		scriptTag.setAttribute('type', 'text/javascript');		scriptTag.setAttribute('src', url);		document.getElementsByTagName('head')[0]
.appendChild(scriptTag);				widgetsets[widgetset]
 = {			pendingApps: []		};	};		var isInitializedInDom = function(appId) {		var appDiv = document.getElementById(appId);		if (!appDiv) {			return false;		}		for ( var i = 0; i < appDiv.childElementCount; i++) {			var className = appDiv.childNodes[i]
.className;			/* If the app div contains a child with the class			"v-app-loading" we have only received the HTML			but not yet started the widget set			(UIConnector removes the v-app-loading div). */			if (className && className.indexOf("v-app-loading") != -1) {				return false;			}		}		return true;	};		/* 	 * Needed for Testbench compatibility, but prevents any Vaadin 7 app from	 * bootstrapping unless the legacy vaadinBootstrap.js file is loaded before	 * this script.	 */    window.Vaadin = window.Vaadin || {};	window.Vaadin.Flow = window.Vaadin.Flow || {        clients: {},		initApplication: function(appId, config) {			var testbenchId = appId.replace(/-\d+$/, '');						if (apps[appId]
) {				if (window.Vaadin && window.Vaadin.Flow && window.Vaadin.Flow.clients && window.Vaadin.Flow.clients[testbenchId]
 && window.Vaadin.Flow.clients[testbenchId]
.initializing) {					throw "Application " + appId + " is already being initialized";				}				if (isInitializedInDom(appId)) {					throw "Application " + appId + " already initialized";				}			}				log("init application", appId, config);						window.Vaadin.Flow.clients[testbenchId]
 = {					isActive: function() {						return true;					},					initializing: true			};						var getConfig = function(name) {				var value = config[name]
;				return value;			};						/* Export public data */			var app = {				getConfig: getConfig			};			apps[appId]
 = app;						if (!window.name) {				window.name =  appId + '-' + Math.random();			}				var widgetset = "client";			widgetsets[widgetset]
 = {					pendingApps: []				};			if (widgetsets[widgetset]
.callback) {				log("Starting from bootstrap", appId);				widgetsets[widgetset]
.callback(appId);			}  else {				log("Setting pending startup", appId);				widgetsets[widgetset]
.pendingApps.push(appId);			}				return app;		},		getAppIds: function() {			var ids = [ ]
;			for (var id in apps) {				if (apps.hasOwnProperty(id)) {					ids.push(id);				}			}			return ids;		},		getApp: function(appId) {			return apps[appId]
;		},		registerWidgetset: function(widgetset, callback) {			log("Widgetset registered", widgetset);			var ws = widgetsets[widgetset]
;			if (ws && ws.pendingApps) {				ws.callback = callback;				for(var i = 0; i < ws.pendingApps.length; i++) {					var appId = ws.pendingApps[i]
;					log("Starting from register widgetset", appId);					callback(appId);				}				ws.pendingApps = null;			}		}	};		log('Flow bootstrap loaded');		if (typeof window.__gwtStatsEvent != 'function') {window.Vaadin.Flow.gwtStatsEvents = [];window.__gwtStatsEvent = function(event) {window.Vaadin.Flow.gwtStatsEvents.push(event); return true;};};		var uidl = {
    "syncId": 0,
    "clientId": 0,
    "constants": {
        "F8oCtNArLiI=": {
            "event.shiftKey": false,
            "event.metaKey": false,
            "event.detail": false,
            "event.ctrlKey": false,
            "event.clientX": false,
            "event.clientY": false,
            "event.altKey": false,
            "event.button": false,
            "event.screenY": false,
            "event.screenX": false
        }
    },
    "changes": [
        {
            "node": 1,
            "type": "put",
            "key": "tag",
            "feat": 0,
            "value": "body"
        },
        {
            "node": 1,
            "type": "splice",
            "feat": 2,
            "index": 0,
            "addNodes": [
                54
            ]
        },
		
[...]
 skipped long list of nodes [...]


        {
            "node": 54,
            "type": "put",
            "key": "width",
            "feat": 12,
            "value": "100%"
        }
    ],
    "timings": [
        0,
        -1
    ],
    "Vaadin-Security-Key": "f815b80a-a2bf-4479-8326-958b5f38a284",
    "Vaadin-Push-ID": "b59f63c3-e2bc-4f94-9e3b-93478b3d7ce3"
};	var config = {
    "frontendUrlEs6": "context://frontend/",
    "frontendUrlEs5": "context://frontend/",
    "versionInfo": {
        "vaadinVersion": "1.0.4",
        "atmosphereVersion": "2.4.24.vaadin1"
    },
    "sessExpMsg": {
        "caption": null,
        "message": null,
        "url": null
    },
    "contextRootUrl": "./",
    "debug": true,
    "requestTiming": true,
    "heartbeatInterval": 300,
    "v-uiId": 0
};	config.uidl = uidl;    window.Vaadin.Flow.initApplication("ROOT-2521314", config);})();//]]></script><script type="text/javascript" defer src="./VAADIN/static/client/client-CAF80B1F92BD4481C6D5EC01BC2D55AE.cache.js"></script><link rel="import" href="./frontend/bower_components/vaadin-button/src/vaadin-button.html"><link rel="import" href="./frontend/bower_components/vaadin-ordered-layout/src/vaadin-horizontal-layout.html"><link rel="import" href="./frontend/bower_components/vaadin-ordered-layout/src/vaadin-vertical-layout.html"><link rel="import" href="./frontend/bower_components/vaadin-lumo-styles/color.html"><link rel="import" href="./frontend/bower_components/vaadin-lumo-styles/typography.html"><link rel="import" href="./frontend/bower_components/vaadin-lumo-styles/sizing.html"><link rel="import" href="./frontend/bower_components/vaadin-lumo-styles/spacing.html"><link rel="import" href="./frontend/bower_components/vaadin-lumo-styles/style.html"><link rel="import" href="./frontend/bower_components/vaadin-lumo-styles/icons.html"><script id="_theme-header-injection">
function _inlineHeader(tag, content){
var customStyle = document.createElement(tag);
customStyle.innerHTML= content;
var firstScript=document.head.querySelector('script');
document.head.insertBefore(customStyle,firstScript);
}
_inlineHeader('custom-style','<style include="lumo-color lumo-typography"></style>');
document.head.removeChild(document.getElementById('_theme-header-injection'));
</script></head><body><noscript>You have to enable javascript in your browser to use this web site.</noscript></body></html>

The crucial part seems to be

<script type="text/javascript" defer src="./VAADIN/static/client/client-CAF80B1F92BD4481C6D5EC01BC2D55AE.cache.js"></script><link rel="import" href="./frontend/bower_components/vaadin-button/src/vaadin-button.html"><link rel="import" href="./frontend/bower_components/vaadin-ordered-layout/src/vaadin-horizontal-layout.html"><link rel="import" href="./frontend/bower_components/vaadin-ordered-layout/src/vaadin-vertical-layout.html"><link rel="import" href="./frontend/bower_components/vaadin-lumo-styles/color.html"><link rel="import" href="./frontend/bower_components/vaadin-lumo-styles/typography.html"><link rel="import" href="./frontend/bower_components/vaadin-lumo-styles/sizing.html"><link rel="import" href="./frontend/bower_components/vaadin-lumo-styles/spacing.html"><link rel="import" href="./frontend/bower_components/vaadin-lumo-styles/style.html"><link rel="import" href="./frontend/bower_components/vaadin-lumo-styles/icons.html">

at the end of the block

After loading the initial page the subsequent get requests like

Request(GET //127.0.0.1:8080/VAADIN/static/client/client-CAF80B1F92BD4481C6D5EC01BC2D55AE.cache.js)@12688d8d

and

Request(GET //127.0.0.1:8080/frontend/bower_components/vaadin-button/src/vaadin-button.html)@766b35ec

etc.

just return a

HTTP/1.1 404 Not Found
Date: Wed, 28 Nov 2018 12:57:39 GMT
Cache-Control: must-revalidate,no-cache,no-store
Content-Type: text/html;charset=iso-8859-1

How has Jetty to be configured to route these requests to the Vaadin code that can handle those content?

Here is an up to date [step by step tutorial]
(https://vaadin.com/tutorials/embedded-jetty-server-in-vaadin-flow) on how to get embedded Jetty into your Vaadin Flow app.

Hope this can help! :slight_smile:

– A^2