> 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.
+ *
+ * When we use this to register filters to the ServletContextHandler or perform other
+ * changes prior to the server starting.
+ */
+ public JettyServerConfig register(Consumer callback) {
+ configureCallback.add(callback);
+ return this;
+ }
+
+ /**
+ * Run configuration callbacks prior to starting the server.
+ */
+ void postConfigure() {
+ for (Consumer callback : configureCallback) {
+ callback.accept(this);
+ }
+ }
+}
diff --git a/avaje-j12/src/main/java/io/avaje/jex/jetty/JettyStartServer.java b/avaje-j12/src/main/java/io/avaje/jex/jetty/JettyStartServer.java
new file mode 100644
index 00000000..4d572895
--- /dev/null
+++ b/avaje-j12/src/main/java/io/avaje/jex/jetty/JettyStartServer.java
@@ -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();
+ }
+}
diff --git a/avaje-j12/src/main/java/io/avaje/jex/jetty/JexHandler.java b/avaje-j12/src/main/java/io/avaje/jex/jetty/JexHandler.java
new file mode 100644
index 00000000..c83e4806
--- /dev/null
+++ b/avaje-j12/src/main/java/io/avaje/jex/jetty/JexHandler.java
@@ -0,0 +1,116 @@
+package io.avaje.jex.jetty;
+
+import io.avaje.jex.Context;
+import io.avaje.jex.Jex;
+import io.avaje.jex.Routing;
+import io.avaje.jex.http.NotFoundResponse;
+import io.avaje.jex.spi.SpiContext;
+import io.avaje.jex.spi.SpiRoutes;
+import org.eclipse.jetty.http.HttpURI;
+import org.eclipse.jetty.server.Handler;
+import org.eclipse.jetty.server.Request;
+import org.eclipse.jetty.server.Response;
+import org.eclipse.jetty.util.Callback;
+
+import java.util.Map;
+
+class JexHandler extends Handler.Abstract {
+
+ //private static final String X_HTTP_METHOD_OVERRIDE = "X-HTTP-Method-Override";
+ private final SpiRoutes routes;
+ private final ServiceManager manager;
+ private final StaticHandler staticHandler;
+
+ JexHandler(Jex jex, SpiRoutes routes, ServiceManager manager, StaticHandler staticHandler) {
+ this.routes = routes;
+ this.manager = manager;
+ this.staticHandler = staticHandler;
+ }
+
+ @Override
+ public boolean handle(Request req, Response res, Callback callback) throws Exception {
+
+ //@Override
+ //public void handle(String target, Request baseRequest, HttpServletRequest req, HttpServletResponse res) {
+// try {
+ final Routing.Type routeType = method(req);
+ HttpURI httpURI = req.getHttpURI();
+ String uri = httpURI.getPathQuery();
+ SpiRoutes.Entry route = routes.match(routeType, uri);
+ if (route == null) {
+ var ctx = new JexHttpContext(manager, req, res, uri);
+ routes.inc();
+ try {
+ processNoRoute(ctx, uri, routeType);
+ routes.after(uri, ctx);
+ } catch (Exception e) {
+ handleException(ctx, e);
+ } finally {
+ routes.dec();
+ }
+ } else {
+ final Map params = route.pathParams(uri);
+ var ctx = new JexHttpContext(manager, req, res, route.matchPath(), params);
+ route.inc();
+ try {
+ processRoute(ctx, uri, route);
+ routes.after(uri, ctx);
+ callback.succeeded();
+ } catch (Exception e) {
+ handleException(ctx, e);
+ } finally {
+ route.dec();
+ }
+ }
+ return true;
+// }
+ }
+
+ private void handleException(SpiContext ctx, Exception e) {
+ manager.handleException(ctx, e);
+ }
+
+ private void processRoute(JexHttpContext ctx, String uri, SpiRoutes.Entry route) {
+ routes.before(uri, ctx);
+ ctx.setMode(null);
+ route.handle(ctx);
+ }
+
+ //String target, Request baseRequest,
+ private void processNoRoute(JexHttpContext ctx, String uri, Routing.Type routeType) {
+ routes.before(uri, ctx);
+ if (routeType == Routing.Type.HEAD && hasGetHandler(uri)) {
+ processHead(ctx);
+ return;
+ }
+// if (routeType == Routing.Type.GET || routeType == Routing.Type.HEAD) {
+// // check if handled by static resource
+// if (staticHandler != null && staticHandler.handle(target, baseRequest, ctx.req(), ctx.res())) {
+// return;
+// }
+// // todo: check if handled by singlePageHandler
+// //if (config.inner.singlePageHandler.handle(ctx)) return@tryWithExceptionMapper
+// }
+// if (routeType == Routing.Type.OPTIONS && isCorsEnabled(config)) { // CORS is enabled, so we return 200 for OPTIONS
+// return@tryWithExceptionMapper
+// }
+// if (prefer405) {
+// //&& availableHandlerTypes.isNotEmpty()
+// //val availableHandlerTypes = MethodNotAllowedUtil.findAvailableHttpHandlerTypes(matcher, requestUri)
+// //throw MethodNotAllowedResponse(details = MethodNotAllowedUtil.getAvailableHandlerTypes(ctx, availableHandlerTypes))
+// }
+ throw new NotFoundResponse("uri: " + uri);
+ }
+
+ private void processHead(Context ctx) {
+ ctx.status(200);
+ }
+
+ private boolean hasGetHandler(String uri) {
+ return routes.match(Routing.Type.GET, uri) != null;
+ }
+
+ private Routing.Type method(Request req) {
+ return manager.lookupRoutingType(req.getMethod());
+ }
+}
diff --git a/avaje-j12/src/main/java/io/avaje/jex/jetty/JexHttpContext.java b/avaje-j12/src/main/java/io/avaje/jex/jetty/JexHttpContext.java
new file mode 100644
index 00000000..31333b92
--- /dev/null
+++ b/avaje-j12/src/main/java/io/avaje/jex/jetty/JexHttpContext.java
@@ -0,0 +1,508 @@
+package io.avaje.jex.jetty;
+
+import io.avaje.jex.Context;
+import io.avaje.jex.Routing;
+import io.avaje.jex.UploadedFile;
+import io.avaje.jex.http.RedirectResponse;
+import io.avaje.jex.spi.HeaderKeys;
+import io.avaje.jex.spi.SpiContext;
+import org.eclipse.jetty.http.HttpCookie;
+import org.eclipse.jetty.http.HttpField;
+import org.eclipse.jetty.http.HttpHeader;
+import org.eclipse.jetty.io.Content;
+import org.eclipse.jetty.server.FormFields;
+import org.eclipse.jetty.server.Request;
+import org.eclipse.jetty.server.Response;
+import org.eclipse.jetty.util.Fields;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.io.UncheckedIOException;
+import java.nio.charset.Charset;
+import java.time.Duration;
+import java.util.*;
+import java.util.stream.Stream;
+
+import static java.util.Collections.emptyList;
+import static java.util.Collections.emptyMap;
+
+class JexHttpContext implements SpiContext {
+
+ private final ServiceManager mgr;
+ protected final Request req;
+ private final Response res;
+ private final Map pathParams;
+ private final String matchedPath;
+ private String characterEncoding;
+ private Routing.Type mode;
+ private Map> formParamMap;
+ private Fields queryParams;
+
+ JexHttpContext(ServiceManager mgr, Request req, Response res, String matchedPath) {
+ this.mgr = mgr;
+ this.req = req;
+ this.res = res;
+ this.matchedPath = matchedPath;
+ this.pathParams = emptyMap();
+ }
+
+ JexHttpContext(ServiceManager mgr, Request req, Response res, String matchedPath, Map pathParams) {
+ this.mgr = mgr;
+ this.req = req;
+ this.res = res;
+ this.matchedPath = matchedPath;
+ this.pathParams = pathParams;
+ }
+
+ @Override
+ public void setMode(Routing.Type mode) {
+ this.mode = mode;
+ }
+
+ private String characterEncoding() {
+ if (characterEncoding == null) {
+ characterEncoding = mgr.requestCharset(this);
+ }
+ return characterEncoding;
+ }
+
+ public Request req() {
+ return req;
+ }
+
+ public Response res() {
+ return res;
+ }
+
+ @Override
+ public boolean isCommitted() {
+ return res.isCommitted();
+ }
+
+ @Override
+ public void reset() {
+ res.reset();
+ }
+
+ @Override
+ public Context attribute(String key, Object value) {
+ req.setAttribute(key, value);
+ return this;
+ }
+
+ @SuppressWarnings("unchecked")
+ @Override
+ public T attribute(String key) {
+ return (T) req.getAttribute(key);
+ }
+
+ @Override
+ public String cookie(String name) {
+ List cookies = Request.getCookies(req);
+ if (cookies != null) {
+ for (HttpCookie cookie : cookies) {
+ if (cookie.getName().equals(name)) {
+ return cookie.getValue();
+ }
+ }
+ }
+ return null;
+ }
+
+ @Override
+ public Map cookieMap() {
+ List cookies = Request.getCookies(req);
+ if (cookies == null) {
+ return emptyMap();
+ }
+ final Map map = new LinkedHashMap<>();
+ for (HttpCookie cookie : cookies) {
+ map.put(cookie.getName(), cookie.getValue());
+ }
+ return map;
+ }
+
+ @Override
+ public Context cookie(Cookie cookie) {
+ var newCookie = HttpCookie.build(cookie.name(), cookie.value());
+ var path = cookie.path() == null ? "/" : cookie.path();
+ newCookie.path(path);
+ final String domain = cookie.domain();
+ if (domain != null) {
+ newCookie.domain(domain);
+ }
+ final Duration duration = cookie.maxAge();
+ if (duration != null) {
+ newCookie.maxAge((int) duration.toSeconds());
+ }
+ newCookie.httpOnly(cookie.httpOnly());
+ newCookie.secure(cookie.secure());
+ Response.addCookie(res, newCookie.build());
+ return this;
+ }
+
+ @Override
+ public Context cookie(String name, String value, int maxAge) {
+ var newCookie = HttpCookie.build(name, value)
+ .path("/")
+ .maxAge(maxAge)
+ .build();
+ Response.addCookie(res, newCookie);
+ return this;
+ }
+
+ @Override
+ public Context cookie(String name, String value) {
+ return cookie(name, value, -1);
+ }
+
+ @Override
+ public Context removeCookie(String name) {
+ return removeCookie(name, null);
+ }
+
+ @Override
+ public Context removeCookie(String name, String path) {
+ if (path == null) {
+ path = "/";
+ }
+ var newCookie = HttpCookie.build(name, "")
+ .path(path)
+ .maxAge(0);
+ Response.addCookie(res, newCookie.build());
+ return this;
+ }
+
+ @Override
+ public void redirect(String location) {
+ redirect(location, 302);
+ }
+
+ @Override
+ public void redirect(String location, int statusCode) {
+ //Response.sendRedirect();
+ res.getHeaders().add(HeaderKeys.LOCATION, location);
+ status(statusCode);
+ if (mode == Routing.Type.BEFORE) {
+ throw new RedirectResponse(statusCode);
+ }
+ }
+
+ @Override
+ public void performRedirect() {
+ // do nothing
+ }
+
+ @Override
+ public String matchedPath() {
+ return matchedPath;
+ }
+
+ @Override
+ public InputStream inputStream() {
+ return Request.asInputStream(req);
+ }
+
+ @Override
+ public T bodyAsClass(Class clazz) {
+ return mgr.jsonRead(clazz, this);
+ }
+
+ @Override
+ public byte[] bodyAsBytes() {
+ try {
+ return Content.Source.asByteBuffer(req).array();
+ } catch (IOException e) {
+ throw new UncheckedIOException(e);
+ }
+ }
+
+ @Override
+ public String body() {
+ try {
+ return Content.Source.asString(req, Charset.forName(characterEncoding()));
+ } catch (IOException e) {
+ throw new UncheckedIOException(e);
+ }
+ }
+
+ @Override
+ public long contentLength() {
+ return req.getLength();
+ }
+
+ @Override
+ public Map pathParamMap() {
+ return pathParams;
+ }
+
+ @Override
+ public String pathParam(String name) {
+ return pathParams.get(name);
+ }
+
+ private Fields _queryParams() {
+ if (queryParams == null) {
+ queryParams = Request.extractQueryParameters(req);
+ }
+ return queryParams;
+ }
+
+ @Override
+ public String queryParam(String name) {
+ Fields.Field field = _queryParams().get(name);
+ return field == null ? null : field.getValue();
+ }
+
+ @Override
+ public List queryParams(String name) {
+ Fields.Field field = _queryParams().get(name);
+ return field == null ? emptyList() : field.getValues();
+ }
+
+ @Override
+ public Map queryParamMap() {
+ final Map map = new LinkedHashMap<>();
+ for (Fields.Field field : _queryParams()) {
+ map.put(field.getName(), field.getValue());
+ }
+ return map;
+ }
+
+ @Override
+ public String queryString() {
+ return req.getHttpURI().getQuery();
+ }
+
+ @Override
+ public Map> formParamMap() {
+ if (formParamMap == null) {
+ formParamMap = initFormParamMap();
+ }
+ return formParamMap;
+ }
+
+ private Map> initFormParamMap() {
+ if (isMultipartFormData()) {
+ throw new IllegalStateException("not supported yet");
+ }
+ Map> map = new LinkedHashMap<>();
+ try {
+ for (Fields.Field formField : FormFields.from(req).get()) {
+ map.put(formField.getName(), formField.getValues());
+ }
+ return map;
+ } catch (Throwable e) {
+ throw new RuntimeException(e);
+ }
+ }
+
+ @Override
+ public String scheme() {
+ return req.getHttpURI().getScheme();
+ }
+
+ @Override
+ public Context sessionAttribute(String key, Object value) {
+ req.getSession(true).setAttribute(key, value);
+ return this;
+ }
+
+ @SuppressWarnings("unchecked")
+ @Override
+ public T sessionAttribute(String key) {
+ var session = req.getSession(false);
+ return session == null ? null : (T) session.getAttribute(key);
+ }
+
+ @Override
+ public Map sessionAttributeMap() {
+ final Map map = new LinkedHashMap<>();
+ final var session = req.getSession(false);
+ if (session == null) {
+ return emptyMap();
+ }
+ Set nameSet = session.getAttributeNameSet();
+ for (String name : nameSet) {
+ map.put(name, session.getAttribute(name));
+ }
+ return map;
+ }
+
+ @Override
+ public String url() {
+ return req.getHttpURI().getPath();
+ }
+
+ @Override
+ public String fullUrl() {
+ return req.getHttpURI().getPathQuery();
+ }
+
+ @Override
+ public String contextPath() {
+ String path = req.getContext().getContextPath();
+ return path == null ? "" : path;
+ }
+
+ @Override
+ public Context status(int statusCode) {
+ res.setStatus(statusCode);
+ return this;
+ }
+
+ @Override
+ public int status() {
+ return res.getStatus();
+ }
+
+ @Override
+ public String contentType() {
+ return req.getHeaders().get(HttpHeader.CONTENT_TYPE);
+ }
+
+ @Override
+ public Context contentType(String contentType) {
+ res.getHeaders().add(HttpHeader.CONTENT_TYPE, contentType);
+ return this;
+ }
+
+ public Map headerMap() {
+ Map map = new LinkedHashMap<>();
+ for (HttpField header : req.getHeaders()) {
+ map.put(header.getName(), header.getValue());
+ }
+ return map;
+ }
+
+ @Override
+ public String responseHeader(String key) {
+ return res.getHeaders().get(key);
+ }
+
+ @Override
+ public String header(String key) {
+ return req.getHeaders().get(key);
+ }
+
+ @Override
+ public Context header(String key, String value) {
+ res.getHeaders().add(key, value);
+ return this;
+ }
+
+ @Override
+ public String host() {
+ return req.getHttpURI().getHost();
+ }
+
+ @Override
+ public String ip() {
+ return Request.getRemoteAddr(req);
+ }
+
+ @Override
+ public boolean isMultipart() {
+ final String type = header(HeaderKeys.CONTENT_TYPE);
+ return type != null && type.toLowerCase().contains("multipart/");
+ }
+
+ @Override
+ public boolean isMultipartFormData() {
+ final String type = header(HeaderKeys.CONTENT_TYPE);
+ return type != null && type.toLowerCase().contains("multipart/form-data");
+ }
+
+ @Override
+ public String method() {
+ return req.getMethod();
+ }
+
+ @Override
+ public String path() {
+ return req.getHttpURI().getDecodedPath();
+ }
+
+ @Override
+ public int port() {
+ return Request.getServerPort(req);
+ }
+
+ @Override
+ public String protocol() {
+ //req.getHttpURI().getScheme().
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public Context json(Object bean) {
+ contentType(APPLICATION_JSON);
+ mgr.jsonWrite(bean, this);
+ return this;
+ }
+
+ @Override
+ public Context jsonStream(Stream stream) {
+ contentType(APPLICATION_X_JSON_STREAM);
+ mgr.jsonWriteStream(stream, this);
+ return this;
+ }
+
+ @Override
+ public Context jsonStream(Iterator iterator) {
+ contentType(APPLICATION_X_JSON_STREAM);
+ mgr.jsonWriteStream(iterator, this);
+ return this;
+ }
+
+ /**
+ * Write plain text content to the response.
+ */
+ @Override
+ public Context text(String content) {
+ contentType(TEXT_PLAIN);
+ return write(content);
+ }
+
+ /**
+ * Write html content to the response.
+ */
+ @Override
+ public Context html(String content) {
+ contentType(TEXT_HTML);
+ return write(content);
+ }
+
+ @Override
+ public Context write(String content) {
+ Content.Sink.write(res, true, content, null);
+ return this;
+ }
+
+ @Override
+ public Context render(String name, Map model) {
+ mgr.render(this, name, model);
+ return this;
+ }
+
+ @Override
+ public OutputStream outputStream() {
+ return Content.Sink.asOutputStream(res);
+ }
+
+ @Override
+ public UploadedFile uploadedFile(String name) {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public List uploadedFiles(String name) {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public List uploadedFiles() {
+ throw new UnsupportedOperationException();
+ }
+}
diff --git a/avaje-j12/src/main/java/io/avaje/jex/jetty/PartUploadedFile.java b/avaje-j12/src/main/java/io/avaje/jex/jetty/PartUploadedFile.java
new file mode 100644
index 00000000..4b30c11a
--- /dev/null
+++ b/avaje-j12/src/main/java/io/avaje/jex/jetty/PartUploadedFile.java
@@ -0,0 +1,63 @@
+package io.avaje.jex.jetty;
+
+//import io.avaje.jex.UploadedFile;
+//import jakarta.servlet.http.Part;
+//
+//import java.io.IOException;
+//import java.io.InputStream;
+//import java.io.UncheckedIOException;
+
+/**
+ * UploadedFile using servlet Part.
+ */
+class PartUploadedFile {//implements UploadedFile {
+
+// private final Part part;
+//
+// PartUploadedFile(Part part) {
+// this.part = part;
+// }
+//
+// @Override
+// public String name() {
+// return part.getName();
+// }
+//
+// @Override
+// public String fileName() {
+// return part.getSubmittedFileName();
+// }
+//
+// @Override
+// public InputStream content() {
+// try {
+// return part.getInputStream();
+// } catch (IOException e) {
+// throw new UncheckedIOException(e);
+// }
+// }
+//
+// @Override
+// public String contentType() {
+// return part.getContentType();
+// }
+//
+// @Override
+// public long size() {
+// return part.getSize();
+// }
+//
+// @Override
+// public void delete() {
+// try {
+// part.delete();
+// } catch (IOException e) {
+// throw new UncheckedIOException(e);
+// }
+// }
+//
+// @Override
+// public String toString() {
+// return "name:" + name() + " fileName:" + fileName() + " size:" + size();
+// }
+}
diff --git a/avaje-j12/src/main/java/io/avaje/jex/jetty/ServiceManager.java b/avaje-j12/src/main/java/io/avaje/jex/jetty/ServiceManager.java
new file mode 100644
index 00000000..bea67db0
--- /dev/null
+++ b/avaje-j12/src/main/java/io/avaje/jex/jetty/ServiceManager.java
@@ -0,0 +1,40 @@
+package io.avaje.jex.jetty;
+
+//import io.avaje.jex.UploadedFile;
+//import io.avaje.jex.spi.ProxyServiceManager;
+//import io.avaje.jex.spi.SpiServiceManager;
+//import jakarta.servlet.http.HttpServletRequest;
+//
+//import java.util.List;
+//import java.util.Map;
+
+import io.avaje.jex.spi.ProxyServiceManager;
+import io.avaje.jex.spi.SpiServiceManager;
+
+/**
+ * Jetty specific service manager.
+ */
+class ServiceManager extends ProxyServiceManager {
+ public ServiceManager(SpiServiceManager delegate) {
+ super(delegate);
+ }
+
+// private final MultipartUtil multipartUtil;
+//
+// ServiceManager(SpiServiceManager delegate, MultipartUtil multipartUtil) {
+// super(delegate);
+// this.multipartUtil = multipartUtil;
+// }
+//
+// List uploadedFiles(HttpServletRequest req) {
+// return null;// multipartUtil.uploadedFiles(req);
+// }
+//
+// List uploadedFiles(HttpServletRequest req, String name) {
+// return null; //multipartUtil.uploadedFiles(req, name);
+// }
+
+// Map> multiPartForm(HttpServletRequest req) {
+// return multipartUtil.fieldMap(req);
+// }
+}
diff --git a/avaje-j12/src/test/java/io/avaje/jex/jetty/JettyBuilderTest.java b/avaje-j12/src/test/java/io/avaje/jex/jetty/JettyBuilderTest.java
new file mode 100644
index 00000000..90787d7f
--- /dev/null
+++ b/avaje-j12/src/test/java/io/avaje/jex/jetty/JettyBuilderTest.java
@@ -0,0 +1,13 @@
+package io.avaje.jex.jetty;
+
+import org.junit.jupiter.api.Test;
+
+import static org.junit.jupiter.api.Assertions.*;
+
+class JettyBuilderTest {
+
+ @Test
+ void asd() {
+
+ }
+}
diff --git a/avaje-jex-jetty/pom.xml b/avaje-jex-jetty/pom.xml
index c815a24a..7810bbea 100644
--- a/avaje-jex-jetty/pom.xml
+++ b/avaje-jex-jetty/pom.xml
@@ -12,7 +12,7 @@
11
11
- 11.0.15
+ 12.0.0
false
@@ -39,7 +39,7 @@
com.fasterxml.jackson.core
jackson-databind
- 2.14.0
+ ${jackson.version}
test
diff --git a/avaje-jex-jetty/src/main/java/io/avaje/jex/jetty/ContextUtil.java b/avaje-jex-jetty/src/main/java/io/avaje/jex/jetty/ContextUtil.java
index c986ffbe..cda07232 100644
--- a/avaje-jex-jetty/src/main/java/io/avaje/jex/jetty/ContextUtil.java
+++ b/avaje-jex-jetty/src/main/java/io/avaje/jex/jetty/ContextUtil.java
@@ -1,41 +1,41 @@
package io.avaje.jex.jetty;
-import jakarta.servlet.ServletInputStream;
-import jakarta.servlet.http.HttpServletRequest;
-
-import java.io.*;
+//import jakarta.servlet.ServletInputStream;
+//import jakarta.servlet.http.HttpServletRequest;
+//
+//import java.io.*;
class ContextUtil {
- private static final int DEFAULT_BUFFER_SIZE = 8 * 1024;
-
- private static final int BUFFER_MAX = 65536;
-
- static byte[] readBody(HttpServletRequest req) {
- try {
- final ServletInputStream inputStream = req.getInputStream();
-
- int bufferSize = inputStream.available();
- if (bufferSize < DEFAULT_BUFFER_SIZE) {
- bufferSize = DEFAULT_BUFFER_SIZE;
- } else if (bufferSize > BUFFER_MAX) {
- bufferSize = BUFFER_MAX;
- }
-
- ByteArrayOutputStream os = new ByteArrayOutputStream(bufferSize);
- copy(inputStream, os, bufferSize);
- return os.toByteArray();
- } catch (IOException e) {
- throw new UncheckedIOException(e);
- }
- }
-
- static void copy(InputStream in, OutputStream out, int bufferSize) throws IOException {
- byte[] buffer = new byte[bufferSize];
- int len;
- while ((len = in.read(buffer, 0, bufferSize)) > 0) {
- out.write(buffer, 0, len);
- }
- }
+// private static final int DEFAULT_BUFFER_SIZE = 8 * 1024;
+//
+// private static final int BUFFER_MAX = 65536;
+//
+// static byte[] readBody(HttpServletRequest req) {
+// try {
+// final ServletInputStream inputStream = req.getInputStream();
+//
+// int bufferSize = inputStream.available();
+// if (bufferSize < DEFAULT_BUFFER_SIZE) {
+// bufferSize = DEFAULT_BUFFER_SIZE;
+// } else if (bufferSize > BUFFER_MAX) {
+// bufferSize = BUFFER_MAX;
+// }
+//
+// ByteArrayOutputStream os = new ByteArrayOutputStream(bufferSize);
+// copy(inputStream, os, bufferSize);
+// return os.toByteArray();
+// } catch (IOException e) {
+// throw new UncheckedIOException(e);
+// }
+// }
+//
+// static void copy(InputStream in, OutputStream out, int bufferSize) throws IOException {
+// byte[] buffer = new byte[bufferSize];
+// int len;
+// while ((len = in.read(buffer, 0, bufferSize)) > 0) {
+// out.write(buffer, 0, len);
+// }
+// }
}
diff --git a/avaje-jex-jetty/src/main/java/io/avaje/jex/jetty/JettyJexServer.java b/avaje-jex-jetty/src/main/java/io/avaje/jex/jetty/JettyJexServer.java
index 7253c3a7..d5b23b52 100644
--- a/avaje-jex-jetty/src/main/java/io/avaje/jex/jetty/JettyJexServer.java
+++ b/avaje-jex-jetty/src/main/java/io/avaje/jex/jetty/JettyJexServer.java
@@ -3,12 +3,12 @@
import io.avaje.jex.*;
import io.avaje.jex.spi.SpiRoutes;
import io.avaje.jex.spi.SpiServiceManager;
-import jakarta.servlet.MultipartConfigElement;
+//import jakarta.servlet.MultipartConfigElement;
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.server.session.SessionHandler;
+//import org.eclipse.jetty.server.session.SessionHandler;
import org.eclipse.jetty.util.Uptime;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -34,7 +34,7 @@ class JettyJexServer implements Jex.Server {
this.jexConfig = jex.config();
this.lifecycle = jex.lifecycle();
this.routes = routes;
- this.serviceManager = new ServiceManager(serviceManager, initMultiPart());
+ this.serviceManager = new ServiceManager(serviceManager);//, initMultiPart());
this.config = initConfig(jex.serverConfig());
}
@@ -42,17 +42,17 @@ 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());
- }
+// 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) {
@@ -104,6 +104,7 @@ protected Jex.Server start() {
protected void createServer() {
server = initServer();
+ //server.setErrorHandler();
server.setHandler(initJettyHandler());
if (server.getStopAtShutdown()) {
// do not use Jetty ShutdownHook, use the AppLifecycle one instead
@@ -123,24 +124,25 @@ protected Server initServer() {
protected Handler initJettyHandler() {
var baseHandler = new JexHandler(jex, routes, serviceManager, initStaticHandler());
- 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;
- }
+ 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 fileSources = jex.staticFiles().getSources();
diff --git a/avaje-jex-jetty/src/main/java/io/avaje/jex/jetty/JettyServerConfig.java b/avaje-jex-jetty/src/main/java/io/avaje/jex/jetty/JettyServerConfig.java
index f8c41a17..36349753 100644
--- a/avaje-jex-jetty/src/main/java/io/avaje/jex/jetty/JettyServerConfig.java
+++ b/avaje-jex-jetty/src/main/java/io/avaje/jex/jetty/JettyServerConfig.java
@@ -3,7 +3,7 @@
import io.avaje.jex.ServerConfig;
import org.eclipse.jetty.server.Handler;
import org.eclipse.jetty.server.Server;
-import org.eclipse.jetty.server.session.SessionHandler;
+//import org.eclipse.jetty.server.session.SessionHandler;
import java.util.ArrayList;
import java.util.List;
@@ -18,7 +18,7 @@ public class JettyServerConfig implements ServerConfig {
* Set maxThreads when using default QueuedThreadPool. Defaults to 200.
*/
private int maxThreads;
- private SessionHandler sessionHandler;
+// private SessionHandler sessionHandler;
private Handler contextHandler;
private Server server;
private final List> configureCallback = new ArrayList<>();
@@ -50,17 +50,17 @@ public JettyServerConfig maxThreads(int 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 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;
diff --git a/avaje-jex-jetty/src/main/java/io/avaje/jex/jetty/JexHandler.java b/avaje-jex-jetty/src/main/java/io/avaje/jex/jetty/JexHandler.java
index 33bd44f3..d2a903e8 100644
--- a/avaje-jex-jetty/src/main/java/io/avaje/jex/jetty/JexHandler.java
+++ b/avaje-jex-jetty/src/main/java/io/avaje/jex/jetty/JexHandler.java
@@ -6,14 +6,18 @@
import io.avaje.jex.http.NotFoundResponse;
import io.avaje.jex.spi.SpiContext;
import io.avaje.jex.spi.SpiRoutes;
-import jakarta.servlet.http.HttpServletRequest;
-import jakarta.servlet.http.HttpServletResponse;
+//import jakarta.servlet.http.HttpServletRequest;
+//import jakarta.servlet.http.HttpServletResponse;
+import org.eclipse.jetty.http.HttpURI;
+import org.eclipse.jetty.server.Handler;
import org.eclipse.jetty.server.Request;
+import org.eclipse.jetty.server.Response;
import org.eclipse.jetty.server.handler.AbstractHandler;
+import org.eclipse.jetty.util.Callback;
import java.util.Map;
-class JexHandler extends AbstractHandler {
+class JexHandler extends Handler.Abstract {
//private static final String X_HTTP_METHOD_OVERRIDE = "X-HTTP-Method-Override";
private final SpiRoutes routes;
@@ -27,16 +31,20 @@ class JexHandler extends AbstractHandler {
}
@Override
- public void handle(String target, Request baseRequest, HttpServletRequest req, HttpServletResponse res) {
- try {
+ public boolean handle(Request req, Response res, Callback callback) throws Exception {
+
+ //@Override
+ //public void handle(String target, Request baseRequest, HttpServletRequest req, HttpServletResponse res) {
+// try {
final Routing.Type routeType = method(req);
- final String uri = req.getRequestURI();
+ HttpURI httpURI = req.getHttpURI();
+ String uri = httpURI.getPathQuery();
SpiRoutes.Entry route = routes.match(routeType, uri);
if (route == null) {
var ctx = new JexHttpContext(manager, req, res, uri);
routes.inc();
try {
- processNoRoute(target, baseRequest, ctx, uri, routeType);
+ processNoRoute(ctx, uri, routeType);
routes.after(uri, ctx);
} catch (Exception e) {
handleException(ctx, e);
@@ -50,15 +58,15 @@ public void handle(String target, Request baseRequest, HttpServletRequest req, H
try {
processRoute(ctx, uri, route);
routes.after(uri, ctx);
+ callback.succeeded();
} catch (Exception e) {
handleException(ctx, e);
} finally {
route.dec();
}
}
- } finally {
- baseRequest.setHandled(true);
- }
+ return true;
+// }
}
private void handleException(SpiContext ctx, Exception e) {
@@ -71,20 +79,21 @@ private void processRoute(JexHttpContext ctx, String uri, SpiRoutes.Entry route)
route.handle(ctx);
}
- private void processNoRoute(String target, Request baseRequest, JexHttpContext ctx, String uri, Routing.Type routeType) {
+ //String target, Request baseRequest,
+ private void processNoRoute(JexHttpContext ctx, String uri, Routing.Type routeType) {
routes.before(uri, ctx);
if (routeType == Routing.Type.HEAD && hasGetHandler(uri)) {
processHead(ctx);
return;
}
- if (routeType == Routing.Type.GET || routeType == Routing.Type.HEAD) {
- // check if handled by static resource
- if (staticHandler != null && staticHandler.handle(target, baseRequest, ctx.req(), ctx.res())) {
- return;
- }
- // todo: check if handled by singlePageHandler
- //if (config.inner.singlePageHandler.handle(ctx)) return@tryWithExceptionMapper
- }
+// if (routeType == Routing.Type.GET || routeType == Routing.Type.HEAD) {
+// // check if handled by static resource
+// if (staticHandler != null && staticHandler.handle(target, baseRequest, ctx.req(), ctx.res())) {
+// return;
+// }
+// // todo: check if handled by singlePageHandler
+// //if (config.inner.singlePageHandler.handle(ctx)) return@tryWithExceptionMapper
+// }
// if (routeType == Routing.Type.OPTIONS && isCorsEnabled(config)) { // CORS is enabled, so we return 200 for OPTIONS
// return@tryWithExceptionMapper
// }
@@ -104,7 +113,7 @@ private boolean hasGetHandler(String uri) {
return routes.match(Routing.Type.GET, uri) != null;
}
- private Routing.Type method(HttpServletRequest req) {
+ private Routing.Type method(Request req) {
return manager.lookupRoutingType(req.getMethod());
}
}
diff --git a/avaje-jex-jetty/src/main/java/io/avaje/jex/jetty/JexHttpContext.java b/avaje-jex-jetty/src/main/java/io/avaje/jex/jetty/JexHttpContext.java
index 3c1935af..31333b92 100644
--- a/avaje-jex-jetty/src/main/java/io/avaje/jex/jetty/JexHttpContext.java
+++ b/avaje-jex-jetty/src/main/java/io/avaje/jex/jetty/JexHttpContext.java
@@ -6,9 +6,14 @@
import io.avaje.jex.http.RedirectResponse;
import io.avaje.jex.spi.HeaderKeys;
import io.avaje.jex.spi.SpiContext;
-import jakarta.servlet.http.HttpServletRequest;
-import jakarta.servlet.http.HttpServletResponse;
-import jakarta.servlet.http.HttpSession;
+import org.eclipse.jetty.http.HttpCookie;
+import org.eclipse.jetty.http.HttpField;
+import org.eclipse.jetty.http.HttpHeader;
+import org.eclipse.jetty.io.Content;
+import org.eclipse.jetty.server.FormFields;
+import org.eclipse.jetty.server.Request;
+import org.eclipse.jetty.server.Response;
+import org.eclipse.jetty.util.Fields;
import java.io.IOException;
import java.io.InputStream;
@@ -25,15 +30,16 @@
class JexHttpContext implements SpiContext {
private final ServiceManager mgr;
- protected final HttpServletRequest req;
- private final HttpServletResponse res;
+ protected final Request req;
+ private final Response res;
private final Map pathParams;
private final String matchedPath;
private String characterEncoding;
private Routing.Type mode;
private Map> formParamMap;
+ private Fields queryParams;
- JexHttpContext(ServiceManager mgr, HttpServletRequest req, HttpServletResponse res, String matchedPath) {
+ JexHttpContext(ServiceManager mgr, Request req, Response res, String matchedPath) {
this.mgr = mgr;
this.req = req;
this.res = res;
@@ -41,7 +47,7 @@ class JexHttpContext implements SpiContext {
this.pathParams = emptyMap();
}
- JexHttpContext(ServiceManager mgr, HttpServletRequest req, HttpServletResponse res, String matchedPath, Map pathParams) {
+ JexHttpContext(ServiceManager mgr, Request req, Response res, String matchedPath, Map pathParams) {
this.mgr = mgr;
this.req = req;
this.res = res;
@@ -61,11 +67,11 @@ private String characterEncoding() {
return characterEncoding;
}
- public HttpServletRequest req() {
+ public Request req() {
return req;
}
- public HttpServletResponse res() {
+ public Response res() {
return res;
}
@@ -93,9 +99,9 @@ public T attribute(String key) {
@Override
public String cookie(String name) {
- final jakarta.servlet.http.Cookie[] cookies = req.getCookies();
+ List cookies = Request.getCookies(req);
if (cookies != null) {
- for (jakarta.servlet.http.Cookie cookie : cookies) {
+ for (HttpCookie cookie : cookies) {
if (cookie.getName().equals(name)) {
return cookie.getValue();
}
@@ -106,12 +112,12 @@ public String cookie(String name) {
@Override
public Map cookieMap() {
- final jakarta.servlet.http.Cookie[] cookies = req.getCookies();
+ List cookies = Request.getCookies(req);
if (cookies == null) {
return emptyMap();
}
final Map map = new LinkedHashMap<>();
- for (jakarta.servlet.http.Cookie cookie : cookies) {
+ for (HttpCookie cookie : cookies) {
map.put(cookie.getName(), cookie.getValue());
}
return map;
@@ -119,31 +125,30 @@ public Map cookieMap() {
@Override
public Context cookie(Cookie cookie) {
- final jakarta.servlet.http.Cookie newCookie = new jakarta.servlet.http.Cookie(cookie.name(), cookie.value());
- newCookie.setPath(cookie.path());
- if (newCookie.getPath() == null) {
- newCookie.setPath("/");
- }
+ var newCookie = HttpCookie.build(cookie.name(), cookie.value());
+ var path = cookie.path() == null ? "/" : cookie.path();
+ newCookie.path(path);
final String domain = cookie.domain();
if (domain != null) {
- newCookie.setDomain(domain);
+ newCookie.domain(domain);
}
final Duration duration = cookie.maxAge();
if (duration != null) {
- newCookie.setMaxAge((int)duration.toSeconds());
+ newCookie.maxAge((int) duration.toSeconds());
}
- newCookie.setHttpOnly(cookie.httpOnly());
- newCookie.setSecure(cookie.secure());
- res.addCookie(newCookie);
+ newCookie.httpOnly(cookie.httpOnly());
+ newCookie.secure(cookie.secure());
+ Response.addCookie(res, newCookie.build());
return this;
}
@Override
public Context cookie(String name, String value, int maxAge) {
- final jakarta.servlet.http.Cookie cookie = new jakarta.servlet.http.Cookie(name, value);
- cookie.setPath("/");
- cookie.setMaxAge(maxAge);
- res.addCookie(cookie);
+ var newCookie = HttpCookie.build(name, value)
+ .path("/")
+ .maxAge(maxAge)
+ .build();
+ Response.addCookie(res, newCookie);
return this;
}
@@ -162,21 +167,22 @@ public Context removeCookie(String name, String path) {
if (path == null) {
path = "/";
}
- final jakarta.servlet.http.Cookie cookie = new jakarta.servlet.http.Cookie(name, "");
- cookie.setPath(path);
- cookie.setMaxAge(0);
- res.addCookie(cookie);
+ var newCookie = HttpCookie.build(name, "")
+ .path(path)
+ .maxAge(0);
+ Response.addCookie(res, newCookie.build());
return this;
}
@Override
public void redirect(String location) {
- redirect(location, HttpServletResponse.SC_MOVED_TEMPORARILY);
+ redirect(location, 302);
}
@Override
public void redirect(String location, int statusCode) {
- res.setHeader(HeaderKeys.LOCATION, location);
+ //Response.sendRedirect();
+ res.getHeaders().add(HeaderKeys.LOCATION, location);
status(statusCode);
if (mode == Routing.Type.BEFORE) {
throw new RedirectResponse(statusCode);
@@ -195,11 +201,7 @@ public String matchedPath() {
@Override
public InputStream inputStream() {
- try {
- return req.getInputStream();
- } catch (IOException e) {
- throw new UncheckedIOException(e);
- }
+ return Request.asInputStream(req);
}
@Override
@@ -209,17 +211,25 @@ public T bodyAsClass(Class clazz) {
@Override
public byte[] bodyAsBytes() {
- return ContextUtil.readBody(req);
+ try {
+ return Content.Source.asByteBuffer(req).array();
+ } catch (IOException e) {
+ throw new UncheckedIOException(e);
+ }
}
@Override
public String body() {
- return new String(bodyAsBytes(), Charset.forName(characterEncoding()));
+ try {
+ return Content.Source.asString(req, Charset.forName(characterEncoding()));
+ } catch (IOException e) {
+ throw new UncheckedIOException(e);
+ }
}
@Override
public long contentLength() {
- return req.getContentLengthLong();
+ return req.getLength();
}
@Override
@@ -232,40 +242,37 @@ public String pathParam(String name) {
return pathParams.get(name);
}
+ private Fields _queryParams() {
+ if (queryParams == null) {
+ queryParams = Request.extractQueryParameters(req);
+ }
+ return queryParams;
+ }
+
@Override
public String queryParam(String name) {
- final String[] vals = req.getParameterValues(name);
- if (vals == null || vals.length == 0) {
- return null;
- } else {
- return vals[0];
- }
+ Fields.Field field = _queryParams().get(name);
+ return field == null ? null : field.getValue();
}
@Override
public List queryParams(String name) {
- final String[] vals = req.getParameterValues(name);
- if (vals == null) {
- return emptyList();
- } else {
- return Arrays.asList(vals);
- }
+ Fields.Field field = _queryParams().get(name);
+ return field == null ? emptyList() : field.getValues();
}
@Override
public Map queryParamMap() {
final Map map = new LinkedHashMap<>();
- final Enumeration names = req.getParameterNames();
- while (names.hasMoreElements()) {
- final String key = names.nextElement();
- map.put(key, queryParam(key));
+ for (Fields.Field field : _queryParams()) {
+ map.put(field.getName(), field.getValue());
}
return map;
}
@Override
public String queryString() {
- return req.getQueryString();
+ return req.getHttpURI().getQuery();
}
@Override
@@ -278,40 +285,46 @@ public Map> formParamMap() {
private Map> initFormParamMap() {
if (isMultipartFormData()) {
- return mgr.multiPartForm(req);
- } else {
- return mgr.formParamMap(this, characterEncoding());
+ throw new IllegalStateException("not supported yet");
+ }
+ Map> map = new LinkedHashMap<>();
+ try {
+ for (Fields.Field formField : FormFields.from(req).get()) {
+ map.put(formField.getName(), formField.getValues());
+ }
+ return map;
+ } catch (Throwable e) {
+ throw new RuntimeException(e);
}
}
@Override
public String scheme() {
- return req.getScheme();
+ return req.getHttpURI().getScheme();
}
@Override
public Context sessionAttribute(String key, Object value) {
- req.getSession().setAttribute(key, value);
+ req.getSession(true).setAttribute(key, value);
return this;
}
@SuppressWarnings("unchecked")
@Override
public T sessionAttribute(String key) {
- HttpSession session = req.getSession(false);
+ var session = req.getSession(false);
return session == null ? null : (T) session.getAttribute(key);
}
@Override
public Map sessionAttributeMap() {
final Map map = new LinkedHashMap<>();
- final HttpSession session = req.getSession(false);
+ final var session = req.getSession(false);
if (session == null) {
return emptyMap();
}
- final Enumeration names = session.getAttributeNames();
- while (names.hasMoreElements()) {
- final String name = names.nextElement();
+ Set nameSet = session.getAttributeNameSet();
+ for (String name : nameSet) {
map.put(name, session.getAttribute(name));
}
return map;
@@ -319,19 +332,17 @@ public Map sessionAttributeMap() {
@Override
public String url() {
- return req.getRequestURL().toString();
+ return req.getHttpURI().getPath();
}
@Override
public String fullUrl() {
- final String url = url();
- final String qs = queryString();
- return qs == null ? url : url + "?" + qs;
+ return req.getHttpURI().getPathQuery();
}
@Override
public String contextPath() {
- String path = req.getContextPath();
+ String path = req.getContext().getContextPath();
return path == null ? "" : path;
}
@@ -348,49 +359,47 @@ public int status() {
@Override
public String contentType() {
- return req.getContentType();
+ return req.getHeaders().get(HttpHeader.CONTENT_TYPE);
}
@Override
public Context contentType(String contentType) {
- res.setContentType(contentType);
+ res.getHeaders().add(HttpHeader.CONTENT_TYPE, contentType);
return this;
}
public Map headerMap() {
Map map = new LinkedHashMap<>();
- final Enumeration names = req.getHeaderNames();
- while (names.hasMoreElements()) {
- final String name = names.nextElement();
- map.put(name, req.getHeader(name));
+ for (HttpField header : req.getHeaders()) {
+ map.put(header.getName(), header.getValue());
}
return map;
}
@Override
public String responseHeader(String key) {
- return req.getHeader(key);
+ return res.getHeaders().get(key);
}
@Override
public String header(String key) {
- return req.getHeader(key);
+ return req.getHeaders().get(key);
}
@Override
public Context header(String key, String value) {
- res.setHeader(key, value);
+ res.getHeaders().add(key, value);
return this;
}
@Override
public String host() {
- return req.getHeader(HeaderKeys.HOST);
+ return req.getHttpURI().getHost();
}
@Override
public String ip() {
- return req.getRemoteAddr();
+ return Request.getRemoteAddr(req);
}
@Override
@@ -412,17 +421,18 @@ public String method() {
@Override
public String path() {
- return req.getRequestURI();
+ return req.getHttpURI().getDecodedPath();
}
@Override
public int port() {
- return req.getServerPort();
+ return Request.getServerPort(req);
}
@Override
public String protocol() {
- return req.getProtocol();
+ //req.getHttpURI().getScheme().
+ throw new UnsupportedOperationException();
}
@Override
@@ -466,12 +476,8 @@ public Context html(String content) {
@Override
public Context write(String content) {
- try {
- res.getWriter().write(content);
- return this;
- } catch (IOException e) {
- throw new UncheckedIOException(e);
- }
+ Content.Sink.write(res, true, content, null);
+ return this;
}
@Override
@@ -482,34 +488,21 @@ public Context render(String name, Map model) {
@Override
public OutputStream outputStream() {
- try {
- return res.getOutputStream();
- } catch (IOException e) {
- throw new UncheckedIOException(e);
- }
+ return Content.Sink.asOutputStream(res);
}
@Override
public UploadedFile uploadedFile(String name) {
- final List files = uploadedFiles(name);
- return files.isEmpty() ? null : files.get(0);
+ throw new UnsupportedOperationException();
}
@Override
public List uploadedFiles(String name) {
- if (!isMultipartFormData()) {
- return emptyList();
- } else {
- return mgr.uploadedFiles(req, name);
- }
+ throw new UnsupportedOperationException();
}
@Override
public List uploadedFiles() {
- if (!isMultipartFormData()) {
- return emptyList();
- } else {
- return mgr.uploadedFiles(req);
- }
+ throw new UnsupportedOperationException();
}
}
diff --git a/avaje-jex-jetty/src/main/java/io/avaje/jex/jetty/MultipartUtil.java b/avaje-jex-jetty/src/main/java/io/avaje/jex/jetty/MultipartUtil.java
index dea863bb..5687f61f 100644
--- a/avaje-jex-jetty/src/main/java/io/avaje/jex/jetty/MultipartUtil.java
+++ b/avaje-jex-jetty/src/main/java/io/avaje/jex/jetty/MultipartUtil.java
@@ -1,103 +1,103 @@
package io.avaje.jex.jetty;
-import io.avaje.jex.UploadedFile;
-import jakarta.servlet.MultipartConfigElement;
-import jakarta.servlet.ServletException;
-import jakarta.servlet.http.HttpServletRequest;
-import jakarta.servlet.http.Part;
-
-import java.io.BufferedReader;
-import java.io.IOException;
-import java.io.InputStreamReader;
-import java.io.UncheckedIOException;
-import java.nio.charset.StandardCharsets;
-import java.util.ArrayList;
-import java.util.LinkedHashMap;
-import java.util.List;
-import java.util.Map;
-
-import static java.util.stream.Collectors.joining;
-import static java.util.stream.Collectors.toList;
+//import io.avaje.jex.UploadedFile;
+//import jakarta.servlet.MultipartConfigElement;
+//import jakarta.servlet.ServletException;
+//import jakarta.servlet.http.HttpServletRequest;
+//import jakarta.servlet.http.Part;
+//
+//import java.io.BufferedReader;
+//import java.io.IOException;
+//import java.io.InputStreamReader;
+//import java.io.UncheckedIOException;
+//import java.nio.charset.StandardCharsets;
+//import java.util.ArrayList;
+//import java.util.LinkedHashMap;
+//import java.util.List;
+//import java.util.Map;
+//
+//import static java.util.stream.Collectors.joining;
+//import static java.util.stream.Collectors.toList;
class MultipartUtil {
- private final MultipartConfigElement config;
-
- MultipartUtil(MultipartConfigElement config) {
- this.config = config;
- }
-
- private void setConfig(HttpServletRequest req) {
- req.setAttribute("org.eclipse.jetty.multipartConfig", config);
- }
-
- List uploadedFiles(HttpServletRequest req) {
- try {
- setConfig(req);
- return req.getParts().stream()
- .filter(part -> isFile(part))
- .map(this::toUploaded)
- .collect(toList());
- } catch (IOException e) {
- throw new UncheckedIOException(e);
- } catch (ServletException e) {
- throw new RuntimeException(e);
- }
- }
-
- List uploadedFiles(HttpServletRequest req, String partName) {
- try {
- setConfig(req);
- return req.getParts().stream()
- .filter(part -> part.getName().equals(partName) && isFile(part))
- .map(this::toUploaded)
- .collect(toList());
- } catch (IOException e) {
- throw new UncheckedIOException(e);
- } catch (ServletException e) {
- throw new RuntimeException(e);
- }
- }
-
- UploadedFile toUploaded(Part part) {
- return new PartUploadedFile(part);
- }
-
- Map> fieldMap(HttpServletRequest req) {
- setConfig(req);
- try {
- Map> map = new LinkedHashMap<>();
- for (Part part : req.getParts()) {
- if (isField(part)) {
- final String name = part.getName();
- final String value = readAsString(part);
- map.computeIfAbsent(name, s -> new ArrayList<>()).add(value);
- }
- }
- return map;
- } catch (IOException e) {
- throw new UncheckedIOException(e);
- } catch (ServletException e) {
- throw new RuntimeException(e);
- }
- }
-
- private String readAsString(Part part) {
- try {
- return new BufferedReader(new InputStreamReader(part.getInputStream(), StandardCharsets.UTF_8))
- .lines()
- .collect(joining("\n"));
- } catch (IOException e) {
- throw new UncheckedIOException(e);
- }
- }
-
- private static boolean isFile(Part filePart) {
- return !isField(filePart);
- }
-
- private static boolean isField(Part filePart) {
- return filePart.getSubmittedFileName() == null; // this is what Apache FileUpload does ...
- }
+// private final MultipartConfigElement config;
+//
+// MultipartUtil(MultipartConfigElement config) {
+// this.config = config;
+// }
+//
+// private void setConfig(HttpServletRequest req) {
+// req.setAttribute("org.eclipse.jetty.multipartConfig", config);
+// }
+//
+// List uploadedFiles(HttpServletRequest req) {
+// try {
+// setConfig(req);
+// return req.getParts().stream()
+// .filter(part -> isFile(part))
+// .map(this::toUploaded)
+// .collect(toList());
+// } catch (IOException e) {
+// throw new UncheckedIOException(e);
+// } catch (ServletException e) {
+// throw new RuntimeException(e);
+// }
+// }
+//
+// List uploadedFiles(HttpServletRequest req, String partName) {
+// try {
+// setConfig(req);
+// return req.getParts().stream()
+// .filter(part -> part.getName().equals(partName) && isFile(part))
+// .map(this::toUploaded)
+// .collect(toList());
+// } catch (IOException e) {
+// throw new UncheckedIOException(e);
+// } catch (ServletException e) {
+// throw new RuntimeException(e);
+// }
+// }
+//
+// UploadedFile toUploaded(Part part) {
+// return new PartUploadedFile(part);
+// }
+//
+// Map> fieldMap(HttpServletRequest req) {
+// setConfig(req);
+// try {
+// Map> map = new LinkedHashMap<>();
+// for (Part part : req.getParts()) {
+// if (isField(part)) {
+// final String name = part.getName();
+// final String value = readAsString(part);
+// map.computeIfAbsent(name, s -> new ArrayList<>()).add(value);
+// }
+// }
+// return map;
+// } catch (IOException e) {
+// throw new UncheckedIOException(e);
+// } catch (ServletException e) {
+// throw new RuntimeException(e);
+// }
+// }
+//
+// private String readAsString(Part part) {
+// try {
+// return new BufferedReader(new InputStreamReader(part.getInputStream(), StandardCharsets.UTF_8))
+// .lines()
+// .collect(joining("\n"));
+// } catch (IOException e) {
+// throw new UncheckedIOException(e);
+// }
+// }
+//
+// private static boolean isFile(Part filePart) {
+// return !isField(filePart);
+// }
+//
+// private static boolean isField(Part filePart) {
+// return filePart.getSubmittedFileName() == null; // this is what Apache FileUpload does ...
+// }
}
diff --git a/avaje-jex-jetty/src/main/java/io/avaje/jex/jetty/PartUploadedFile.java b/avaje-jex-jetty/src/main/java/io/avaje/jex/jetty/PartUploadedFile.java
index 712ed3b6..4b30c11a 100644
--- a/avaje-jex-jetty/src/main/java/io/avaje/jex/jetty/PartUploadedFile.java
+++ b/avaje-jex-jetty/src/main/java/io/avaje/jex/jetty/PartUploadedFile.java
@@ -1,63 +1,63 @@
package io.avaje.jex.jetty;
-import io.avaje.jex.UploadedFile;
-import jakarta.servlet.http.Part;
-
-import java.io.IOException;
-import java.io.InputStream;
-import java.io.UncheckedIOException;
+//import io.avaje.jex.UploadedFile;
+//import jakarta.servlet.http.Part;
+//
+//import java.io.IOException;
+//import java.io.InputStream;
+//import java.io.UncheckedIOException;
/**
* UploadedFile using servlet Part.
*/
-class PartUploadedFile implements UploadedFile {
-
- private final Part part;
-
- PartUploadedFile(Part part) {
- this.part = part;
- }
-
- @Override
- public String name() {
- return part.getName();
- }
-
- @Override
- public String fileName() {
- return part.getSubmittedFileName();
- }
-
- @Override
- public InputStream content() {
- try {
- return part.getInputStream();
- } catch (IOException e) {
- throw new UncheckedIOException(e);
- }
- }
-
- @Override
- public String contentType() {
- return part.getContentType();
- }
-
- @Override
- public long size() {
- return part.getSize();
- }
-
- @Override
- public void delete() {
- try {
- part.delete();
- } catch (IOException e) {
- throw new UncheckedIOException(e);
- }
- }
-
- @Override
- public String toString() {
- return "name:" + name() + " fileName:" + fileName() + " size:" + size();
- }
+class PartUploadedFile {//implements UploadedFile {
+
+// private final Part part;
+//
+// PartUploadedFile(Part part) {
+// this.part = part;
+// }
+//
+// @Override
+// public String name() {
+// return part.getName();
+// }
+//
+// @Override
+// public String fileName() {
+// return part.getSubmittedFileName();
+// }
+//
+// @Override
+// public InputStream content() {
+// try {
+// return part.getInputStream();
+// } catch (IOException e) {
+// throw new UncheckedIOException(e);
+// }
+// }
+//
+// @Override
+// public String contentType() {
+// return part.getContentType();
+// }
+//
+// @Override
+// public long size() {
+// return part.getSize();
+// }
+//
+// @Override
+// public void delete() {
+// try {
+// part.delete();
+// } catch (IOException e) {
+// throw new UncheckedIOException(e);
+// }
+// }
+//
+// @Override
+// public String toString() {
+// return "name:" + name() + " fileName:" + fileName() + " size:" + size();
+// }
}
diff --git a/avaje-jex-jetty/src/main/java/io/avaje/jex/jetty/ServiceManager.java b/avaje-jex-jetty/src/main/java/io/avaje/jex/jetty/ServiceManager.java
index 5eb0ddbc..bea67db0 100644
--- a/avaje-jex-jetty/src/main/java/io/avaje/jex/jetty/ServiceManager.java
+++ b/avaje-jex-jetty/src/main/java/io/avaje/jex/jetty/ServiceManager.java
@@ -1,34 +1,40 @@
package io.avaje.jex.jetty;
-import io.avaje.jex.UploadedFile;
+//import io.avaje.jex.UploadedFile;
+//import io.avaje.jex.spi.ProxyServiceManager;
+//import io.avaje.jex.spi.SpiServiceManager;
+//import jakarta.servlet.http.HttpServletRequest;
+//
+//import java.util.List;
+//import java.util.Map;
+
import io.avaje.jex.spi.ProxyServiceManager;
import io.avaje.jex.spi.SpiServiceManager;
-import jakarta.servlet.http.HttpServletRequest;
-
-import java.util.List;
-import java.util.Map;
/**
* Jetty specific service manager.
*/
class ServiceManager extends ProxyServiceManager {
-
- private final MultipartUtil multipartUtil;
-
- ServiceManager(SpiServiceManager delegate, MultipartUtil multipartUtil) {
+ public ServiceManager(SpiServiceManager delegate) {
super(delegate);
- this.multipartUtil = multipartUtil;
}
- List uploadedFiles(HttpServletRequest req) {
- return multipartUtil.uploadedFiles(req);
- }
-
- List uploadedFiles(HttpServletRequest req, String name) {
- return multipartUtil.uploadedFiles(req, name);
- }
-
- Map> multiPartForm(HttpServletRequest req) {
- return multipartUtil.fieldMap(req);
- }
+// private final MultipartUtil multipartUtil;
+//
+// ServiceManager(SpiServiceManager delegate, MultipartUtil multipartUtil) {
+// super(delegate);
+// this.multipartUtil = multipartUtil;
+// }
+//
+// List uploadedFiles(HttpServletRequest req) {
+// return null;// multipartUtil.uploadedFiles(req);
+// }
+//
+// List uploadedFiles(HttpServletRequest req, String name) {
+// return null; //multipartUtil.uploadedFiles(req, name);
+// }
+
+// Map> multiPartForm(HttpServletRequest req) {
+// return multipartUtil.fieldMap(req);
+// }
}
diff --git a/avaje-jex-jetty/src/main/java/io/avaje/jex/jetty/StaticHandler.java b/avaje-jex-jetty/src/main/java/io/avaje/jex/jetty/StaticHandler.java
index 3694c115..172b1314 100644
--- a/avaje-jex-jetty/src/main/java/io/avaje/jex/jetty/StaticHandler.java
+++ b/avaje-jex-jetty/src/main/java/io/avaje/jex/jetty/StaticHandler.java
@@ -1,12 +1,14 @@
package io.avaje.jex.jetty;
import io.avaje.jex.StaticFileSource;
-import jakarta.servlet.http.HttpServletRequest;
-import jakarta.servlet.http.HttpServletResponse;
+//import jakarta.servlet.http.HttpServletRequest;
+//import jakarta.servlet.http.HttpServletResponse;
import org.eclipse.jetty.server.Request;
+import org.eclipse.jetty.server.Response;
import org.eclipse.jetty.server.Server;
import org.eclipse.jetty.server.handler.ResourceHandler;
-import org.eclipse.jetty.util.resource.EmptyResource;
+//import org.eclipse.jetty.util.resource.EmptyResource;
+import org.eclipse.jetty.util.Callback;
import org.eclipse.jetty.util.resource.Resource;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -30,138 +32,142 @@ class StaticHandler {
}
void addStaticFileConfig(StaticFileSource config) {
- ResourceHandler handler;
- if ("/webjars".equals(config.getPath())) {
- handler = new WebjarHandler();
- } else {
- PrefixableHandler h = new PrefixableHandler(config.getUrlPathPrefix());
- h.setResourceBase(getResourcePath(config));
- h.setDirAllowed(false);
- h.setEtags(true);
- handler = h;
- }
- log.info("Static file handler added {}", config);
-
- try {
- handler.setServer(server);
- handler.start();
- } catch (Exception e) {
- throw new RuntimeException("Error starting Jetty static resource handler", e);
- }
- handlers.add(handler);
+// ResourceHandler handler;
+// if ("/webjars".equals(config.getPath())) {
+// handler = new WebjarHandler();
+// } else {
+// PrefixableHandler h = new PrefixableHandler(config.getUrlPathPrefix());
+// //FIXME h.setResourceBase(getResourcePath(config));
+// h.setDirAllowed(false);
+// h.setEtags(true);
+// handler = h;
+// }
+// log.info("Static file handler added {}", config);
+//
+// try {
+// handler.setServer(server);
+// handler.start();
+// } catch (Exception e) {
+// throw new RuntimeException("Error starting Jetty static resource handler", e);
+// }
+// handlers.add(handler);
}
- private String getResourcePath(StaticFileSource config) {
- if (config.getLocation() == StaticFileSource.Location.CLASSPATH) {
- var resource = Resource.newClassPathResource(config.getPath());
- if (resource == null) {
- throw new RuntimeException(noSuchDir(config) + " Depending on your setup, empty folders might not get copied to classpath.");
- }
- return resource.toString();
- }
- final File path = new File(config.getPath());
- if (!path.exists()) {
- throw new RuntimeException(noSuchDir(config) + " path: " + path.getAbsolutePath());
- }
- return config.getPath();
- }
+// private String getResourcePath(StaticFileSource config) {
+// if (config.getLocation() == StaticFileSource.Location.CLASSPATH) {
+// var resource = Resource.newClassPathResource(config.getPath());
+// if (resource == null) {
+// throw new RuntimeException(noSuchDir(config) + " Depending on your setup, empty folders might not get copied to classpath.");
+// }
+// return resource.toString();
+// }
+// final File path = new File(config.getPath());
+// if (!path.exists()) {
+// throw new RuntimeException(noSuchDir(config) + " path: " + path.getAbsolutePath());
+// }
+// return config.getPath();
+// }
private String noSuchDir(StaticFileSource config) {
return "Static resource directory with path: '" + config.getPath() + "' does not exist.";
}
- boolean handle(String target, Request baseRequest, HttpServletRequest req, HttpServletResponse res) {
- for (ResourceHandler handler : handlers) {
- try {
- var resource = handler.getResource(target);
- if (isFile(resource) || isDirectoryWithWelcomeFile(resource, handler, target)) {
-// val maxAge = if (target.startsWith("/immutable/") || handler is WebjarHandler) 31622400 else 0
-// httpResponse.setHeader(HeaderKeys.CACHE_CONTROL, "max-age=$maxAge");
-
- // Remove the default content type because Jetty will not set the correct one
- // if the HTTP response already has a content type set
-// if (precompressStaticFiles && PrecompressingResourceHandler.handle(resource, httpRequest, httpResponse)) {
-// return true
-// }
- res.setContentType(null);
- handler.handle(target, baseRequest, req, res);
- req.setAttribute("handled-as-static-file", true);
-// (httpResponse as JavalinResponseWrapper).outputStream.finalize()
- return true;
- }
- } catch (Exception e) { // it's fine
-// if (!Util.isClientAbortException(e)) {
-// Javalin.log?.error("Exception occurred while handling static resource", e)
-// }
- log.error("Exception occurred while handling static resource", e);
- }
- }
+ boolean handle(Request req, Response res, Callback callback) {
return false;
}
+// boolean handle(String target, Request baseRequest, HttpRequest req, HttpServletResponse res) {
+// for (ResourceHandler handler : handlers) {
+// try {
+// var resource = handler.getResource(target);
+// if (isFile(resource) || isDirectoryWithWelcomeFile(resource, handler, target)) {
+//// val maxAge = if (target.startsWith("/immutable/") || handler is WebjarHandler) 31622400 else 0
+//// httpResponse.setHeader(HeaderKeys.CACHE_CONTROL, "max-age=$maxAge");
+//
+// // Remove the default content type because Jetty will not set the correct one
+// // if the HTTP response already has a content type set
+//// if (precompressStaticFiles && PrecompressingResourceHandler.handle(resource, httpRequest, httpResponse)) {
+//// return true
+//// }
+// res.setContentType(null);
+// handler.handle(target, baseRequest, req, res);
+// req.setAttribute("handled-as-static-file", true);
+//// (httpResponse as JavalinResponseWrapper).outputStream.finalize()
+// return true;
+// }
+// } catch (Exception e) { // it's fine
+//// if (!Util.isClientAbortException(e)) {
+//// Javalin.log?.error("Exception occurred while handling static resource", e)
+//// }
+// log.error("Exception occurred while handling static resource", e);
+// }
+// }
+// return false;
+// }
+
private boolean isFile(Resource resource) {
return resource != null && resource.exists() && !resource.isDirectory();
}
- private boolean isDirectoryWithWelcomeFile(Resource resource, ResourceHandler handler, String target) {
- //String path = target.removeSuffix("/")+"/index.html";
- if (target.endsWith("/")) {
- target = target.substring(0, target.length() - 1);
- }
- String path = target + "/index.html";
- if (resource == null || !resource.isDirectory()) {
- return false;
- }
- try {
- final Resource indexHtml = handler.getResource(path);
- return indexHtml != null && indexHtml.exists();
- } catch (IOException e) {
- log.warn("Error checking for welcome file", e);
- return false;
- }
- }
-
- private static class WebjarHandler extends ResourceHandler {
- @Override
- public Resource getResource(String path) throws IOException {
- final Resource resource = Resource.newClassPathResource("META-INF/resources" + path);
- return (resource != null) ? resource : super.getResource(path);
- }
- }
-
- private static class PrefixableHandler extends ResourceHandler {
-
- private final String urlPathPrefix;
-
- PrefixableHandler(String urlPathPrefix) {
- this.urlPathPrefix = urlPathPrefix;
- }
-
- @Override
- public Resource getResource(String path) throws IOException {
- if (urlPathPrefix.equals("/")) {
- return super.getResource(path); // same as regular ResourceHandler
- }
- String targetPath = target(path);
- if ("".equals(targetPath)) {
- return super.getResource("/"); // directory without trailing '/'
- }
- if (!path.startsWith(urlPathPrefix)) {
- return EmptyResource.INSTANCE;
- }
- if (!targetPath.startsWith("/")) {
- return EmptyResource.INSTANCE;
- } else {
- return super.getResource(targetPath);
- }
- }
-
- private String target(String path) {
- if (path.startsWith(urlPathPrefix)) {
- return path.substring(urlPathPrefix.length());
- } else {
- return path;
- }
- }
- }
+// private boolean isDirectoryWithWelcomeFile(Resource resource, ResourceHandler handler, String target) {
+// //String path = target.removeSuffix("/")+"/index.html";
+// if (target.endsWith("/")) {
+// target = target.substring(0, target.length() - 1);
+// }
+// String path = target + "/index.html";
+// if (resource == null || !resource.isDirectory()) {
+// return false;
+// }
+// try {
+// final Resource indexHtml = handler.getResource(path);
+// return indexHtml != null && indexHtml.exists();
+// } catch (IOException e) {
+// log.warn("Error checking for welcome file", e);
+// return false;
+// }
+// }
+
+// private static class WebjarHandler extends ResourceHandler {
+// @Override
+// public Resource getResource(String path) throws IOException {
+// final Resource resource = Resource.newClassPathResource("META-INF/resources" + path);
+// return (resource != null) ? resource : super.getResource(path);
+// }
+// }
+//
+// private static class PrefixableHandler extends ResourceHandler {
+//
+// private final String urlPathPrefix;
+//
+// PrefixableHandler(String urlPathPrefix) {
+// this.urlPathPrefix = urlPathPrefix;
+// }
+//
+// @Override
+// public Resource getResource(String path) throws IOException {
+// if (urlPathPrefix.equals("/")) {
+// return super.getResource(path); // same as regular ResourceHandler
+// }
+// String targetPath = target(path);
+// if ("".equals(targetPath)) {
+// return super.getResource("/"); // directory without trailing '/'
+// }
+// if (!path.startsWith(urlPathPrefix)) {
+// return EmptyResource.INSTANCE;
+// }
+// if (!targetPath.startsWith("/")) {
+// return EmptyResource.INSTANCE;
+// } else {
+// return super.getResource(targetPath);
+// }
+// }
+//
+// private String target(String path) {
+// if (path.startsWith(urlPathPrefix)) {
+// return path.substring(urlPathPrefix.length());
+// } else {
+// return path;
+// }
+// }
+// }
}
diff --git a/avaje-jex-jetty/src/main/java/module-info.java b/avaje-jex-jetty/src/main/java/module-info.java
index 8dbb3de8..0ccec789 100644
--- a/avaje-jex-jetty/src/main/java/module-info.java
+++ b/avaje-jex-jetty/src/main/java/module-info.java
@@ -8,7 +8,7 @@
requires transitive io.avaje.jex;
//requires io.avaje.jex.jettyx;
requires java.net.http;
- requires transitive jetty.servlet.api;
+ //requires transitive jetty.servlet.api;
requires transitive org.slf4j;
requires transitive org.eclipse.jetty.http;
requires transitive org.eclipse.jetty.server;
diff --git a/pom.xml b/pom.xml
index 9b17193c..84536c36 100644
--- a/pom.xml
+++ b/pom.xml
@@ -31,7 +31,8 @@
avaje-jex-jetty
avaje-jex-jdk
avaje-jex-grizzly
-
+ avaje-j12
+