Introduction¶
Being a long-term Eclipse Foundation project Jetty is a Java web server and Java Servlet container providing support for Java Servlet API, HTTP/1.1, HTTP/2, Web Socket and FastCGI. Additionally it provides support for OSGi, JMX, JNDI, JAAS and others.
Golden Code chose Jetty as the HTTP backend as it is easily full-featured and standard based, flexible and extensible, asynchronous, enterprise scalable and has small footprint.
FWD uses Jetty in version 12.0.22.
Integration¶
Jetty is embedded in the FWD server process. FWD server is fully responsible for its life time. It is initialized and started during FWD server bootstrap and shut down during FWD server tear down. FWD uses the Jetty API.
The main Jetty API class is org.eclipse.jetty.server.Server. It aggregates a thread pool of HTTP request receivers and request handlers. The incoming HTTP requests are dispatched with the receivers and eventually passed to one or more registered handlers. For better illustration see a simple example of an embedded Jetty in a Java process.
public class HelloWorld extends AbstractHandler { @Override public void handle(String target, Request baseRequest, HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException { // Declare response encoding and types response.setContentType("text/html; charset=utf-8"); // Declare response status code response.setStatus(HttpServletResponse.SC_OK); // Write back response response.getWriter().println("<h1>Hello World</h1>"); // Inform Jetty that this request has now been handled baseRequest.setHandled(true); } public static void main(String[] args) throws Exception { Server server = new Server(8080); server.setHandler(new HelloWorld()); server.start(); server.join(); } }
FWD integrates Jetty in a similar way. It initializes a set of handlers and passes them to a created Server instance.
Handlers are the main integration point in the Jetty API. They implement the "business logic" for every particular request. A handler class is any class implementing the interface org.eclipse.jetty.server.Handler. There are many ready made Jetty API classes implementing various types of handlers. From the simplest ones providing the basic request needs (org.eclipse.jetty.server.handler.AbstractHandler) to the more complex ones like org.eclipse.jetty.server.handler.ContextHandler for handling only a particular subset of the request paths or org.eclipse.jetty.webapp.WebAppContext used to programmatically create a full-featured Java web application. For all the Jetty API details please refer to the Jetty documentation.
Endpoints¶
There are several built-in services exposed by the embedded Jetty instance. These implement some of the 4GL services to support the converted native applications and also extend the capabilities of the converted applications. FWD also allows deploying any compliant Java web application.
Built-in services¶
| Name | Context (base URL path) | Handler Class | Description |
|---|---|---|---|
| Admin | /admin | see below | FWD administration UI. |
| Web UI (ChUI) | /chui | com.goldencode.p2j.main.WebHandler |
The login page for the character based user interface (FWD client). |
| Web UI (GUI) | /gui | com.goldencode.p2j.main.WebHandler |
The login page for the graphic based user interface (FWD client). |
| Embedded Web GUI | /embedded | com.goldencode.p2j.main.EmbeddedPageHandler |
The login page for FWD client running in embedded mode. |
| REST | /rest | com.goldencode.p2j.rest.RestHandler |
Processes the REST requests and delegates the calls to the mapped service. |
| SOAP | /ws | com.goldencode.p2j.soap.SoapHandler |
Processes SOAP service requests and delegate the calls to the mapped service. |
| Web Service | /web | com.goldencode.p2j.main.WebServiceHandler |
Processes the HTTP requests and delegates them to the mapped WebHandler legacy classes. |
All the built-in services run on the same port number configured in the directory in the hive adminPort.
Configuration¶
There are several parameters exposed in the server directory altering the embedded Jetty instance behavior.
| Name | Type | Default Value | Description |
|---|---|---|---|
| adminPort | integer | 9443 | The port number Jetty will listen on for the incoming HTTPS requests of all the build-in services. |
| maxOutputBufferSize | integer | 1048576 | The size in bytes of the output buffer used to aggregate HTTP output. |
| maxOutputAggregationSize | integer | 8192 | The maximum size in bytes for HTTP output to be aggregated. |
| maxIdleTimeout | integer | -1 | The idle timeout in ms for I/O operations during the handling of an HTTP request. -1 is interpreted as an infinite timeout. |
| maxResponseHeaderSize | integer | 8192 | The maximum allowed size in bytes for an HTTP response header. |
| maxRequestHeaderSize | integer | 8192 | The maximum allowed size in bytes for an HTTP request header. |
Thread Pool¶
These nodes are read from the server's directory section (server/<id>/, falling back to server/default/).
| Node | Type | Default | Description |
|---|---|---|---|
JettyThreadPool/minThreads |
integer | 8 | Web server threads kept alive. Also the number of FWD contexts a stateless web app creates up front. |
JettyThreadPool/maxThreads |
integer | 200 | Web server threads which may run at once. Also the upper bound of a stateless web app's FWD context pool. |
JettyThreadPool/idleTimeout |
integer | 60000 | Milliseconds an idle thread is kept. Also how long an unused pooled FWD context lives before it is reaped. |
Security¶
All the endpoints by default use HTTPS protocol (HTTP over SSL) or can be configured to use HTTPS. FWD supports Conscrypt, Bouncy Castle or the default SSL provider bundled with the Java runtime environment in use.
On top of the channel security protocol all the endpoints integrate with the standard security mechanism provided by FWD server.
The authentication mechanism, which integrates with FWD server security, is implemented in LegacyServiceHandler. Any handler extending this class will also benefit from its security features. These include com.goldencode.p2j.rest.RestHandler, com.goldencode.p2j.soap.SoapHandler and com.goldencode.p2j.main.WebServiceHandler.
If authentication is enabled for the particular handler in server directory (see below the list of security related directory parameters) LegacyServiceHandler will authenticate all the requests in its handle method. It passes the request to one of the subclasses of com.goldencode.p2j.main.WebServiceAuth. Each subclass implements a single authentication mechanism. Currently only BasicAuth is implemented where the client of the service must pass the authentication credentials. BasicAuth uses the credentials and passes them to SecurityManager.authWebRequest. authWebRequest checks the credentials and if it finds a match it considers the request authenticated (the caller successfully identified). In the second step BasicAuth does an authorization of the request by the call to SecurityManager.createWebRequestContext. createWebRequestContext will create an access token, a corresponding security context and will return the access token to BasicAuth. BasicAuth will
check whether the target request is authorized with a call to WebServiceResource and if the authorization is successful stores the access token in the response header. Subsequent requests having this access token will succeed.
Security related directory parameters¶
| Hive | Type | Default Value | Description |
|---|---|---|---|
| <type>/authentication/enabled | boolean | false | When set to true enables authentication on the service. |
| <type>/authentication/type | string | "basic" | Allows to change the type of authentication. Currently only "basic" is supported. |
| <type>/authentication/timeout | integer | 0 | Session security context timeout in seconds. After the timeout expires the access token used by the clients of the service and the related security context will no longer be valid. If set to 0 the context will be expired only after an explicit logout. |
| <type>/authentication/login_path | string | null | The login path recognized by BasicAuth class. Request with this path will authenticate the request. |
| <type>/authentication/logout_path | string | "/fwdlogout" | Invalidates the access token established during authorization and the related security context. |
<type> in the table above can be interpreted as the handler type. It is one of "rest", "soap" and "WebHandler" for RestHandler, SoapHandler and WebServiceHandler classes respectively.
Web Applications¶
A 3rd party web application (WAR) can be hosted by the FWD server. Each one is configured under the <name>WebApp node, where <name> is the name the application is registered with:
| Node | Type | Default | Description |
|---|---|---|---|
port |
integer | Insecure port. At least one of port / secureport is required. |
|
secureport |
integer | Secure port. Needs keyStore, storePassword and entryPassword. |
|
basepath |
string | / |
Base path serving the web app. |
warfile |
string | (app specific) | WAR file, relative to the FWD server's working directory. |
sessionTimeout |
integer | 3600 | HTTP session timeout, in seconds. |
mode |
string | stateless |
stateful or stateless (case-insensitive), see below. Any other value stops the web app from starting. |
Every request passes through WebAuthFilter (WebAuthFilterEE10 for jakarta web apps). The filter authenticates with the FWD server and gives the servlet a context switcher in the fwd.switcher session attribute, so FWD appserver calls run in the requester's context.
Session Mode¶
| stateful | stateless (default) | |
|---|---|---|
| FWD context | Authenticated on the first request of an HTTP session and reused by the later requests of that session | Leased from a pool of FWD contexts for the duration of each request, then returned |
| State between requests | Kept (shared variables, persistent procedures, etc. survive) | None. Every request starts clean |
| HTTP session | Tracked normally (cookie) | Not tracked: no cookie is sent, the session is private to its request and is invalidated when the request ends |
| Session end | SessionCleaner terminates the FWD session when the HTTP session is destroyed (timeout or invalidation) |
The pool manages context lifetime, so no session listener is registered |
| Intended for | Stateful web UIs | REST endpoints |
If mode is not configured, the server logs a WARNING and uses stateless. Before 11794a, web apps always behaved as stateful. A web app that relies on state being kept across the requests of an HTTP session must now set mode to stateful explicitly.
Stateless Context Pool¶
- The pool is sized from the
JettyThreadPoolnodes (see above):minThreadscontexts are created up front, at mostmaxThreadsexist, and contexts unused foridleTimeoutms are reaped. The reaper runs every 30 seconds. - When no context is free, a request waits up to 5 seconds. If none becomes free, the request gets HTTP 503 with
Retry-After: 1. - The sizing assumes a request holds its context only while its thread runs. A request using
startAsynckeeps its context until the async request completes, so a web app that uses async requests heavily may need higher thread counts.
External Servlet Containers¶
When a web app is deployed in its own Jetty server (connectors obtained from GenericWebServer) or another container, there is no <name>WebApp/mode node to read. The web app registers the filter in its own web.xml and selects the mode with the fwd.sessionmode init parameter, set either on the filter or as a context parameter:
<filter>
<filter-name>fwdAuth</filter-name>
<filter-class>com.goldencode.p2j.web.WebAuthFilter</filter-class>
<init-param>
<param-name>fwd.sessionmode</param-name>
<param-value>stateful</param-value>
</init-param>
</filter>
<!-- required for stateful only; SessionCleanerEE10 for jakarta web apps -->
<listener>
<listener-class>com.goldencode.p2j.web.GenericWebServer$SessionCleaner</listener-class>
</listener>
- If
fwd.sessionmodeis not set, the filter logs a WARNING and usesstateless. - A
statefulweb app must declareSessionCleaner(orSessionCleanerEE10); otherwise its FWD sessions are never terminated. Astatelessweb app needs no listener. - The pool is still sized from the FWD server's
JettyThreadPoolnodes. On this path those nodes don't describe the container that actually serves the requests, so set them to match it. - Do not declare the filter in the
web.xmlof a web app hosted by the FWD server, because the server already registers it. Registering it twice logs a WARNING and creates two separate context pools.
© 2004-2026 Golden Code Development Corporation. ALL RIGHTS RESERVED.