Skip to content

Commit

Permalink
#11 Initial implementation of QuickStart
Browse files Browse the repository at this point in the history
  • Loading branch information
mvysny committed Mar 15, 2023
1 parent 4cd41a0 commit b78dc5f
Show file tree
Hide file tree
Showing 3 changed files with 124 additions and 9 deletions.
1 change: 1 addition & 0 deletions vaadin-boot/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ dependencies {

// Embedded Jetty dependencies
api("org.eclipse.jetty:jetty-webapp:${properties["jetty_version"]}")
api("org.eclipse.jetty:jetty-quickstart:${properties["jetty_version"]}")
api("org.eclipse.jetty.websocket:websocket-jakarta-server:${properties["jetty_version"]}")

// opens url in a browser; Vaadin dependency
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
package com.github.mvysny.vaadinboot;

import org.eclipse.jetty.quickstart.ExtraXmlDescriptorProcessor;
import org.eclipse.jetty.quickstart.QuickStartGeneratorConfiguration;
import org.eclipse.jetty.util.resource.Resource;
import org.eclipse.jetty.webapp.WebAppContext;
import org.jetbrains.annotations.NotNull;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.*;

/**
* Helper methods for Jetty Quick Start mode.
*/
class JettyQuickStart {
public static boolean quickstartXmlExists(@NotNull Resource webroot) {
try {
return webroot.getResource("WEB-INF/quickstart-web.xml").exists();
} catch (IOException e) {
throw new RuntimeException(e);
}
}

public static void createQuickStartXml(@NotNull WebAppContext context) throws IOException {
context.setAttribute(ExtraXmlDescriptorProcessor.class.getName(), new ExtraXmlDescriptorProcessor());
final String xml = new File("quickstart-web.xml").getAbsolutePath();
try (OutputStream out = new BufferedOutputStream(new FileOutputStream(xml))) {
new QuickStartGeneratorConfiguration().generateQuickStartWebXml(context, out);
}
log.info("Created Jetty QuickStart configuration at " + xml + ". Place the file into src/main/resources/webapp/WEB-INF/quickstart-web.xml of your webapp and ");
}

private static final Logger log = LoggerFactory.getLogger(JettyQuickStart.class);
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,15 +2,16 @@

import com.vaadin.open.Open;
import jakarta.servlet.Servlet;
import org.eclipse.jetty.quickstart.QuickStartConfiguration;
import org.eclipse.jetty.server.Server;
import org.eclipse.jetty.util.resource.Resource;
import org.eclipse.jetty.webapp.WebAppContext;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.annotations.VisibleForTesting;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.File;
import java.net.InetSocketAddress;
import java.net.MalformedURLException;
import java.time.Duration;
Expand Down Expand Up @@ -234,6 +235,10 @@ public void start() throws Exception {
server.start();
log.debug("Jetty Server started");

if (createQuickStartXml) {
JettyQuickStart.createQuickStartXml(context);
}

final Duration startupDuration = Duration.ofMillis(System.currentTimeMillis() - startupMeasurementSince);
System.out.println("\n\n=================================================\n" +
"Started in " + startupDuration + ". Running on " + Env.dumpHost() + "\n" +
Expand All @@ -251,16 +256,21 @@ public void start() throws Exception {
@NotNull
protected WebAppContext createWebAppContext() throws MalformedURLException {
final WebAppContext context = new WebAppContext();
context.setBaseResource(Env.findWebRoot());
final Resource webRoot = Env.findWebRoot();
context.setBaseResource(webRoot);
context.setContextPath(contextRoot);
context.addServlet(servlet, "/*");
// this will properly scan the classpath for all @WebListeners, including the most important
// com.vaadin.flow.server.startup.ServletContextListeners.
// See also https://mvysny.github.io/vaadin-lookup-vs-instantiator/
// Jetty documentation: https://www.eclipse.org/jetty/documentation/jetty-12/operations-guide/index.html#og-annotations-scanning
context.setAttribute("org.eclipse.jetty.server.webapp.ContainerIncludeJarPattern", ".*\\.jar|.*/classes/.*");
context.setConfigurationDiscovered(true);
context.getServletContext().setExtendedListenerTypes(true);
if (JettyQuickStart.quickstartXmlExists(webRoot)) {
context.setAttribute(QuickStartConfiguration.MODE, QuickStartConfiguration.Mode.QUICKSTART);
context.addConfiguration(new QuickStartConfiguration());
} else {
// this will properly scan the classpath for all @WebListeners, including the most important
// com.vaadin.flow.server.startup.ServletContextListeners.
// See also https://mvysny.github.io/vaadin-lookup-vs-instantiator/
// Jetty documentation: https://www.eclipse.org/jetty/documentation/jetty-12/operations-guide/index.html#og-annotations-scanning
context.setAttribute("org.eclipse.jetty.server.webapp.ContainerIncludeJarPattern", ".*\\.jar|.*/classes/.*");
context.setConfigurationDiscovered(true);
}
return context;
}

Expand Down Expand Up @@ -290,4 +300,73 @@ public void stop(@NotNull String reason) {

@NotNull
private static final Logger log = LoggerFactory.getLogger(VaadinBoot.class);

@NotNull
private QuickStartMode quickStartMode = QuickStartMode.Off;

/**
* Jetty can optionally start faster if we don't classpath-scan for resources,
* and instead pass in a QuickStart XML file with all resources listed.
* <p></p>
* This is mandatory for native mode.
* <p></p>
* See
* <a href="https://www.eclipse.org/jetty/documentation/jetty-12/operations-guide/index.html#og-quickstart">Jetty QuickStart documentation</a>
* for more details; see
* <a href="https://www.eclipse.org/jetty/documentation/jetty-12/programming-guide/index.html#jetty-effective-web-xml-goal">Jetty Maven plugin</a>
* documentation as well. Also see <a href="https://github.com/mvysny/vaadin-boot/issues/11">Issue #11</a>.
* @param quickStartMode the new quick start mode, defaults to {@link QuickStartMode#Off}.
* @return this
*/
@NotNull
public VaadinBoot withQuickStartMode(@NotNull QuickStartMode quickStartMode) {
this.quickStartMode = quickStartMode;
return this;
}

private boolean createQuickStartXml = false;

/**
* Defaults to false. If true, a <code>quickstart-web.xml</code> file for your app is created in the
* current working directory when Jetty starts.
* <p></p>
* Workaround until we are able to generate the XML file during the compile time, via a Maven/Gradle plugin.
* @return this
*/
@NotNull
public VaadinBoot createQuickStartXml() {
createQuickStartXml = true;
return this;
}

public enum QuickStartMode {
/**
* Never use Jetty Quick Start - always use classpath scanning.
*/
Off {
@Override
public boolean isQuickstartEnabled() {
return false;
}
},
/**
* Use Jetty Quick Start only when running in Vaadin production mode.
*/
Production {
@Override
public boolean isQuickstartEnabled() {
return Env.isVaadinProductionMode;
}
},
/**
* Use Jetty Quick Start, both in dev and in production mode.
*/
Always {
@Override
public boolean isQuickstartEnabled() {
return true;
}
};
public abstract boolean isQuickstartEnabled();
}
}

0 comments on commit b78dc5f

Please sign in to comment.