-
Notifications
You must be signed in to change notification settings - Fork 1
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
22 changed files
with
1,654 additions
and
509 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,36 @@ | ||
<?xml version="1.0" encoding="UTF-8"?> | ||
<project xmlns="http://maven.apache.org/POM/4.0.0" | ||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" | ||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> | ||
<modelVersion>4.0.0</modelVersion> | ||
<parent> | ||
<groupId>io.avaje</groupId> | ||
<artifactId>avaje-jex-parent</artifactId> | ||
<version>2.6-SNAPSHOT</version> | ||
</parent> | ||
|
||
<artifactId>avaje-j12</artifactId> | ||
|
||
<properties> | ||
<maven.compiler.source>21</maven.compiler.source> | ||
<maven.compiler.target>21</maven.compiler.target> | ||
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> | ||
<jetty.version>12.0.0</jetty.version> | ||
<surefire.useModulePath>false</surefire.useModulePath> | ||
</properties> | ||
|
||
<dependencies> | ||
<dependency> | ||
<groupId>io.avaje</groupId> | ||
<artifactId>avaje-jex</artifactId> | ||
<version>2.6-SNAPSHOT</version> | ||
</dependency> | ||
|
||
<dependency> | ||
<groupId>org.eclipse.jetty</groupId> | ||
<artifactId>jetty-server</artifactId> | ||
<version>${jetty.version}</version> | ||
</dependency> | ||
</dependencies> | ||
|
||
</project> |
59 changes: 59 additions & 0 deletions
59
avaje-j12/src/main/java/io/avaje/jex/jetty/JettyBuilder.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,59 @@ | ||
package io.avaje.jex.jetty; | ||
|
||
import io.avaje.jex.Jex; | ||
import io.avaje.jex.JexConfig; | ||
import org.eclipse.jetty.server.Connector; | ||
import org.eclipse.jetty.server.Server; | ||
import org.eclipse.jetty.server.ServerConnector; | ||
import org.eclipse.jetty.util.thread.QueuedThreadPool; | ||
import org.eclipse.jetty.util.thread.ThreadPool; | ||
import org.slf4j.Logger; | ||
import org.slf4j.LoggerFactory; | ||
|
||
import java.lang.reflect.Constructor; | ||
|
||
/** | ||
* Build the Jetty Server. | ||
*/ | ||
class JettyBuilder { | ||
|
||
private static final Logger log = LoggerFactory.getLogger(JettyBuilder.class); | ||
|
||
private final JexConfig jexConfig; | ||
private final JettyServerConfig jettyConfig; | ||
|
||
JettyBuilder(Jex jex, JettyServerConfig jettyConfig) { | ||
this.jexConfig = jex.config(); | ||
this.jettyConfig = jettyConfig; | ||
} | ||
|
||
Server build() { | ||
Server jetty = new Server(pool()); | ||
ServerConnector connector = new ServerConnector(jetty); | ||
connector.setPort(jexConfig.port()); | ||
if (jexConfig.host() != null ) { | ||
connector.setHost(jexConfig.host()); | ||
} | ||
jetty.setConnectors(new Connector[]{connector}); | ||
return jetty; | ||
} | ||
|
||
private ThreadPool pool() { | ||
if (jexConfig.virtualThreads()) { | ||
return virtualThreadBasePool(); | ||
} else { | ||
return jettyConfig.maxThreads() == 0 ? new QueuedThreadPool() : new QueuedThreadPool(jettyConfig.maxThreads()); | ||
} | ||
} | ||
|
||
private ThreadPool virtualThreadBasePool() { | ||
try { | ||
final Class<?> aClass = Class.forName("io.avaje.jex.jetty.threadpool.VirtualThreadPool"); | ||
final Constructor<?> constructor = aClass.getConstructor(); | ||
return (ThreadPool) constructor.newInstance(); | ||
} catch (Exception e) { | ||
throw new IllegalStateException("Failed to start Loom threadPool", e); | ||
} | ||
} | ||
|
||
} |
168 changes: 168 additions & 0 deletions
168
avaje-j12/src/main/java/io/avaje/jex/jetty/JettyJexServer.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,168 @@ | ||
package io.avaje.jex.jetty; | ||
|
||
import io.avaje.jex.spi.SpiRoutes; | ||
import io.avaje.jex.spi.SpiServiceManager; | ||
import org.eclipse.jetty.server.Connector; | ||
import org.eclipse.jetty.server.Handler; | ||
import org.eclipse.jetty.server.Server; | ||
import org.eclipse.jetty.server.ServerConnector; | ||
import org.eclipse.jetty.util.Uptime; | ||
import org.slf4j.Logger; | ||
import org.slf4j.LoggerFactory; | ||
|
||
import java.util.List; | ||
|
||
class JettyJexServer implements Jex.Server { | ||
|
||
private static final Logger log = LoggerFactory.getLogger(Jex.class); | ||
|
||
private final Jex jex; | ||
private final SpiRoutes routes; | ||
private final ServiceManager serviceManager; | ||
private final JettyServerConfig config; | ||
private final AppLifecycle lifecycle; | ||
private final long startTime; | ||
private final JexConfig jexConfig; | ||
private Server server; | ||
|
||
JettyJexServer(Jex jex, SpiRoutes routes, SpiServiceManager serviceManager) { | ||
this.startTime = System.currentTimeMillis(); | ||
this.jex = jex; | ||
this.jexConfig = jex.config(); | ||
this.lifecycle = jex.lifecycle(); | ||
this.routes = routes; | ||
this.serviceManager = new ServiceManager(serviceManager);//, initMultiPart()); | ||
this.config = initConfig(jex.serverConfig()); | ||
} | ||
|
||
private JettyServerConfig initConfig(ServerConfig config) { | ||
return config == null ? new JettyServerConfig() : (JettyServerConfig) config; | ||
} | ||
|
||
// MultipartUtil initMultiPart() { | ||
// return new MultipartUtil(initMultipartConfigElement(jexConfig.multipartConfig())); | ||
// } | ||
// | ||
// MultipartConfigElement initMultipartConfigElement(UploadConfig uploadConfig) { | ||
// if (uploadConfig == null) { | ||
// final int fileThreshold = jexConfig.multipartFileThreshold(); | ||
// return new MultipartConfigElement(System.getProperty("java.io.tmpdir"), -1, -1, fileThreshold); | ||
// } | ||
// return new MultipartConfigElement(uploadConfig.location(), uploadConfig.maxFileSize(), uploadConfig.maxRequestSize(), uploadConfig.fileSizeThreshold()); | ||
// } | ||
|
||
@Override | ||
public void onShutdown(Runnable onShutdown) { | ||
lifecycle.onShutdown(onShutdown, Integer.MAX_VALUE); | ||
} | ||
|
||
@Override | ||
public void restart() { | ||
try { | ||
server.start(); | ||
logOnStart(server); | ||
lifecycle.status(AppLifecycle.Status.STARTED); | ||
} catch (Exception e) { | ||
throw new RuntimeException(e); | ||
} | ||
} | ||
|
||
@Override | ||
public void shutdown() { | ||
try { | ||
log.trace("starting shutdown"); | ||
lifecycle.status(AppLifecycle.Status.STOPPING); | ||
routes.waitForIdle(30); | ||
server.stop(); | ||
log.trace("server http listeners stopped"); | ||
lifecycle.status(AppLifecycle.Status.STOPPED); | ||
} catch (Exception e) { | ||
throw new RuntimeException(e); | ||
} | ||
} | ||
|
||
@Override | ||
public int port() { | ||
return server.getURI().getPort(); | ||
} | ||
|
||
protected Jex.Server start() { | ||
try { | ||
createServer(); | ||
server.start(); | ||
logOnStart(server); | ||
lifecycle.registerShutdownHook(this::shutdown); | ||
lifecycle.status(AppLifecycle.Status.STARTED); | ||
return this; | ||
} catch (Exception e) { | ||
throw new IllegalStateException("Error starting server", e); | ||
} | ||
} | ||
|
||
protected void createServer() { | ||
server = initServer(); | ||
//server.setErrorHandler(); | ||
server.setHandler(initJettyHandler()); | ||
if (server.getStopAtShutdown()) { | ||
// do not use Jetty ShutdownHook, use the AppLifecycle one instead | ||
server.setStopAtShutdown(false); | ||
} | ||
config.server(server); | ||
config.postConfigure(); | ||
} | ||
|
||
protected Server initServer() { | ||
Server server = config.server(); | ||
if (server != null) { | ||
return server; | ||
} | ||
return new JettyBuilder(jex, config).build(); | ||
} | ||
|
||
protected Handler initJettyHandler() { | ||
var baseHandler = new JexHandler(jex, routes, serviceManager, initStaticHandler()); | ||
return baseHandler; | ||
// if (!config.sessions()) { | ||
// return baseHandler; | ||
// } | ||
// var sessionHandler = initSessionHandler(); | ||
// sessionHandler.setHandler(baseHandler); | ||
// return sessionHandler; | ||
} | ||
|
||
// protected SessionHandler initSessionHandler() { | ||
// SessionHandler sh = config.sessionHandler(); | ||
// return sh == null ? defaultSessionHandler() : sh; | ||
// } | ||
// | ||
// protected SessionHandler defaultSessionHandler() { | ||
// SessionHandler sh = new SessionHandler(); | ||
// sh.setHttpOnly(true); | ||
// return sh; | ||
// } | ||
|
||
protected StaticHandler initStaticHandler() { | ||
final List<StaticFileSource> fileSources = jex.staticFiles().getSources(); | ||
if (fileSources == null || fileSources.isEmpty()) { | ||
return null; | ||
} | ||
StaticHandlerFactory factory = new StaticHandlerFactory(); | ||
return factory.build(server, jex, fileSources); | ||
} | ||
|
||
private void logOnStart(org.eclipse.jetty.server.Server server) { | ||
long startup = System.currentTimeMillis() - startTime; | ||
for (Connector c : server.getConnectors()) { | ||
String virtualThreads = jexConfig.virtualThreads() ? "with virtualThreads" : ""; | ||
if (c instanceof ServerConnector) { | ||
ServerConnector sc = (ServerConnector) c; | ||
String host = (sc.getHost() == null) ? "0.0.0.0" : sc.getHost(); | ||
log.info("Listening with {} {}:{} in {}ms @{}ms {}", sc.getProtocols(), host, sc.getLocalPort(), startup, Uptime.getUptime(), virtualThreads); | ||
} else { | ||
log.info("bind to {} in {}ms @{}ms {}", c, startup, Uptime.getUptime(), virtualThreads); | ||
} | ||
} | ||
} | ||
|
||
|
||
} |
108 changes: 108 additions & 0 deletions
108
avaje-j12/src/main/java/io/avaje/jex/jetty/JettyServerConfig.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,108 @@ | ||
package io.avaje.jex.jetty; | ||
|
||
import io.avaje.jex.ServerConfig; | ||
import org.eclipse.jetty.server.Handler; | ||
import org.eclipse.jetty.server.Server; | ||
|
||
import java.util.ArrayList; | ||
import java.util.List; | ||
import java.util.function.Consumer; | ||
|
||
public class JettyServerConfig implements ServerConfig { | ||
|
||
private boolean sessions = true; | ||
private boolean security = true; | ||
|
||
/** | ||
* Set maxThreads when using default QueuedThreadPool. Defaults to 200. | ||
*/ | ||
private int maxThreads; | ||
// private SessionHandler sessionHandler; | ||
private Handler contextHandler; | ||
private Server server; | ||
private final List<Consumer<JettyServerConfig>> configureCallback = new ArrayList<>(); | ||
|
||
public boolean sessions() { | ||
return sessions; | ||
} | ||
|
||
public JettyServerConfig sessions(boolean sessions) { | ||
this.sessions = sessions; | ||
return this; | ||
} | ||
|
||
public boolean security() { | ||
return security; | ||
} | ||
|
||
public JettyServerConfig security(boolean security) { | ||
this.security = security; | ||
return this; | ||
} | ||
|
||
public int maxThreads() { | ||
return maxThreads; | ||
} | ||
|
||
public JettyServerConfig maxThreads(int maxThreads) { | ||
this.maxThreads = maxThreads; | ||
return this; | ||
} | ||
|
||
// public SessionHandler sessionHandler() { | ||
// return sessionHandler; | ||
// } | ||
// | ||
// /** | ||
// * Set the SessionHandler to use. When not set one is created automatically. | ||
// */ | ||
// public JettyServerConfig sessionHandler(SessionHandler sessionHandler) { | ||
// this.sessionHandler = sessionHandler; | ||
// return this; | ||
// } | ||
|
||
public Handler contextHandler() { | ||
return contextHandler; | ||
} | ||
|
||
/** | ||
* Set the Jetty Handler to use. When not set one is created automatically. | ||
*/ | ||
public JettyServerConfig contextHandler(Handler contextHandler) { | ||
this.contextHandler = contextHandler; | ||
return this; | ||
} | ||
|
||
public Server server() { | ||
return server; | ||
} | ||
|
||
/** | ||
* Set the Jetty Server to use. When not set one is created automatically. | ||
*/ | ||
public JettyServerConfig server(Server server) { | ||
this.server = server; | ||
return this; | ||
} | ||
|
||
/** | ||
* Register a callback that is executed after the server and contextHandler have been | ||
* created but before the server has started. | ||
* <p> | ||
* When we use this to register filters to the ServletContextHandler or perform other | ||
* changes prior to the server starting. | ||
*/ | ||
public JettyServerConfig register(Consumer<JettyServerConfig> callback) { | ||
configureCallback.add(callback); | ||
return this; | ||
} | ||
|
||
/** | ||
* Run configuration callbacks prior to starting the server. | ||
*/ | ||
void postConfigure() { | ||
for (Consumer<JettyServerConfig> callback : configureCallback) { | ||
callback.accept(this); | ||
} | ||
} | ||
} |
17 changes: 17 additions & 0 deletions
17
avaje-j12/src/main/java/io/avaje/jex/jetty/JettyStartServer.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,17 @@ | ||
package io.avaje.jex.jetty; | ||
|
||
import io.avaje.jex.Jex; | ||
import io.avaje.jex.spi.SpiRoutes; | ||
import io.avaje.jex.spi.SpiServiceManager; | ||
import io.avaje.jex.spi.SpiStartServer; | ||
|
||
/** | ||
* Configure and starts the underlying Jetty server. | ||
*/ | ||
public class JettyStartServer implements SpiStartServer { | ||
|
||
@Override | ||
public Jex.Server start(Jex jex, SpiRoutes routes, SpiServiceManager serviceManager) { | ||
return new JettyJexServer(jex, routes, serviceManager).start(); | ||
} | ||
} |
Oops, something went wrong.