I have used single jetty.xml and added my contexts and http configuration here to handle my requests. I have followed this approach as I was using old jetty 6 earlier and was upgrading to 9 where they have divided the files and I was confused with the configurations mentioned in newer jetty.
<?xml version="1.0"?>
<!DOCTYPE Configure PUBLIC "-//Jetty//Configure//EN" "http://www.eclipse.org/jetty/configure_9_3.dtd">
<!-- =============================================================== -->
<!-- Documentation of this file format can be found at: -->
<!-- https://www.eclipse.org/jetty/documentation/current/ -->
<!-- -->
<!-- Additional configuration files are available in $JETTY_HOME/etc -->
<!-- and can be mixed in. See start.ini file for the default -->
<!-- configuration files. -->
<!-- -->
<!-- For a description of the configuration mechanism, see the -->
<!-- output of: -->
<!-- java -jar start.jar -? -->
<!-- =============================================================== -->
<!-- =============================================================== -->
<!-- Configure a Jetty Server instance with an ID "Server" -->
<!-- Other configuration files may also configure the "Server" -->
<!-- ID, in which case they are adding configuration to the same -->
<!-- instance. If other configuration have a different ID, they -->
<!-- will create and configure another instance of Jetty. -->
<!-- Consult the javadoc of o.e.j.server.Server for all -->
<!-- configuration that may be set here. -->
<!-- =============================================================== -->
<Configure id="Server" class="org.eclipse.jetty.server.Server">
<New id="threadPool" class="org.eclipse.jetty.util.thread.QueuedThreadPool">
<Set name="minThreads" type="int"><Property name="jetty.threadPool.minThreads" deprecated="threads.min" default="10"/></Set>
<Set name="maxThreads" type="int"><Property name="jetty.threadPool.maxThreads" deprecated="threads.max" default="200"/></Set>
<Set name="reservedThreads" type="int"><Property name="jetty.threadPool.reservedThreads" default="-1"/></Set>
<Set name="idleTimeout" type="int"><Property name="jetty.threadPool.idleTimeout" deprecated="threads.timeout" default="60000"/></Set>
<Set name="detailedDump" type="boolean"><Property name="jetty.threadPool.detailedDump" default="false"/></Set>
</New>
<!-- =========================================================== -->
<!-- Add shared Scheduler instance -->
<!-- =========================================================== -->
<Call name="addBean">
<Arg>
<New class="org.eclipse.jetty.util.thread.ScheduledExecutorScheduler">
<Arg name="name"><Property name="jetty.scheduler.name"/></Arg>
<Arg name="daemon" type="boolean"><Property name="jetty.scheduler.daemon" default="false" /></Arg>
<Arg name="threads" type="int"><Property name="jetty.scheduler.threads" default="-1" /></Arg>
</New>
</Arg>
</Call>
<Set name="handler">
<New id="Handlers" class="org.eclipse.jetty.server.handler.HandlerCollection">
<Set name="handlers">
<Array type="org.eclipse.jetty.server.Handler">
<Item>
<New id="Contexts" class="org.eclipse.jetty.server.handler.ContextHandlerCollection"/>
</Item>
<!-- <Item>-->
<!-- <New id="DefaultHandler" class="org.eclipse.jetty.server.handler.DefaultHandler"/>-->
<!-- </Item>-->
<Item>
<New id="RequestLog" class="org.eclipse.jetty.server.handler.RequestLogHandler"/>
</Item>
</Array>
</Set>
</New>
</Set>
<!-- ======================================================= -->
<!-- Configure a Context for CTS -->
<!-- ======================================================= -->
<New class="org.eclipse.jetty.servlet.ServletContextHandler">
<Arg>
<Ref id="Contexts"/>
</Arg>
<Arg>/cts</Arg>
<Set name="resourceBase">
<SystemProperty name="jetty.home" default="."/>/</Set>
<Set name="sessionHandler">
<New class="org.eclipse.jetty.server.session.SessionHandler"/>
</Set>
<Call name="addServlet">
<Arg>com.documentum.cts.webservices.remote.TransformationServlet</Arg>
<Arg>/</Arg>
</Call>
</New>
<New class="org.eclipse.jetty.servlet.ServletContextHandler">
<Arg>
<Ref id="Contexts"/>
</Arg>
<Arg>/cts/resource</Arg>
<Set name="resourceBase">
<SystemProperty name="jetty.home" default="."/>/../resource/</Set>
<Call name="addServlet">
<Arg>com.documentum.cts.webservices.remote.FileProxyServlet</Arg>
<Arg>/</Arg>
</Call>
</New>
<!-- =========================================================== -->
<!-- Http Configuration. -->
<!-- This is a common configuration instance used by all -->
<!-- connectors that can carry HTTP semantics (HTTP, HTTPS, etc.)-->
<!-- It configures the non wire protocol aspects of the HTTP -->
<!-- semantic. -->
<!-- -->
<!-- This configuration is only defined here and is used by -->
<!-- reference from other XML files such as jetty-http.xml, -->
<!-- jetty-https.xml and other configuration files which -->
<!-- instantiate the connectors. -->
<!-- -->
<!-- Consult the javadoc of o.e.j.server.HttpConfiguration -->
<!-- for all configuration that may be set here. -->
<!-- =========================================================== -->
<Call name="addConnector">
<Arg>
<New id="httpConnector" class="org.eclipse.jetty.server.ServerConnector">
<Arg name="server">
<Ref refid="Server" />
</Arg>
<Set name="host">
<SystemProperty name="jetty.http.host"/>
</Set>
<Set name="port">
<Property name="jetty.http.port" deprecated="jetty.port" default="9096" />
</Set>
<Set name="idleTimeout">
<Property name="jetty.http.idleTimeout" deprecated="http.timeout" default="30000"/>
</Set>
<Get name="SelectorManager">
<Set name="connectTimeout"><Property name="jetty.http.connectTimeout" default="15000"/></Set>
</Get>
</New>
</Arg>
</Call>
<!-- =========================================================== -->
<!-- Set the default handler structure for the Server -->
<!-- A handler collection is used to pass received requests to -->
<!-- both the ContextHandlerCollection, which selects the next -->
<!-- handler by context path and virtual host, and the -->
<!-- DefaultHandler, which handles any requests not handled by -->
<!-- the context handlers. -->
<!-- Other handlers may be added to the "Handlers" collection, -->
<!-- for example the jetty-requestlog.xml file adds the -->
<!-- RequestLogHandler after the default handler -->
<!-- =========================================================== -->
<Ref id="RequestLog">
<Set name="requestLog">
<New id="RequestLogImpl" class="org.eclipse.jetty.server.NCSARequestLog">
<Set name="filename">
<SystemProperty name="jetty.logs" default="../logs"/>/ws.request_yyyy_mm_dd.log</Set>
<Set name="filenameDateFormat">yyyy_MM_dd</Set>
<Set name="retainDays">90</Set>
<Set name="append">true</Set>
<Set name="extended">true</Set>
<Set name="logCookies">false</Set>
<Set name="LogTimeZone">GMT</Set>
</New>
</Set>
</Ref>
<!-- =========================================================== -->
<!-- extra server options -->
<!-- =========================================================== -->
<Set name="stopAtShutdown"><Property name="jetty.server.stopAtShutdown" default="true"/></Set>
<Set name="stopTimeout"><Property name="jetty.server.stopTimeout" default="5000"/></Set>
<Set name="dumpAfterStart"><Property name="jetty.server.dumpAfterStart" deprecated="jetty.dump.start" default="false"/></Set>
<Set name="dumpBeforeStop"><Property name="jetty.server.dumpBeforeStop" deprecated="jetty.dump.stop" default="false"/></Set>
</Configure>
Following code has been written to call this configuration:
Server myServer;
File theConfigFile = new File( "C://jetty//etc//jetty.xml" );
XmlConfiguration theXmlConfiguration = new XmlConfiguration( theConfigFile.toURL() );
theXmlConfiguration.configure( myServer );
myServer.start();
I want to stick to the approach of configuring jetty with xml configuration and enable http in SSL mode. Is it possible to achieve this? Any help provided will be really helpful.
Oh boy, there's many things to talk about here.
It's not great idea to dump a large variety of issues into a single question on stackoverflow!
<Ref>
properly. it's <Ref refid="otherid">
, not <Ref id="idtothisref">
ServletContextHandler
or WebAppContext
to bind the location in the handler tree or to define the context Path. These should be defined in XML as being within the location of the handler tree you want them.Scheduler
, the way you have it now, you'll have 2 schedulers!DefaultHandler
is a critical component of Jetty and many things will break if you remove it.RequestLogHandler
on Jetty 9, it was deprecated in Jetty 8 and only exists in Jetty 9 to prevent breaking configs (you don't actually have a fully functional RequestLog
using the handler approach, use the server approach.NCSARequestLog
is deprecated as well, don't use that, use CustomRequestLog
with a specific RequestLog.Writer
specified.ServletContextHandler
definitions declare a resourceBase
but then add a servlet on the default servlet url-pattern of /
. This is a conflicting combination of behavior.
resourceBase
and a DefaultServlet
on the default servlet url-pattern of /
(which is also named "default" per spec),DefaultServlet
so that you have a sane ServletContext
(this means a lot, including error handling, error dispatch, http cache responses, missing resources, non-path resource requests, full http spec path normalization rules, etc. And that's just the surface things that DefaultServlet
gives you along with a long list of other ServletContext spec defined required features)/cts/resource
is invalid and will not work. This kind of pattern is best done with url-pattern
within an existing context.
Your usage of the XmlConfiguration
class doesn't use the properties features, or the ID Map that is built into the XmlConfiguration
class, so that means all of your usages of <Property>
and <SystemProperty>
and id="foo"
references in your XML are not expanded or valid.
Either use XmlConfiguration
properly, or remove all of the <Property>
and <SystemProperty>
elements in your XML.
What this means ...
<!-- in your XML -->
<Set name="maxThreads" type="int"><Property name="jetty.threadPool.maxThreads" deprecated="threads.max" default="200"/></Set>
<!-- should be -->
<Set name="maxThreads" type="int">200</Set>
But why go to that extreme just to avoid using XmlConfiguration
properly?
Using XmlConfiguration
without properties is no different than just using embedded-jetty directly, so skip the XML and just go embedded-jetty (way easier).
If you want to use XmlConfiguration
properly, continue to read on.
First, don't redo what exists in Jetty already, use it. This means taking the existing XML, the existing default properties, and using XmlConfiguration
properly.
In your example XML the only "custom" thing is your 2 ServletContextHandlers
, which can be their own XML files easily.
First lets show you how you can do those 2 custom XML using straight up jetty-home and jetty-base, which uses XML and properties with XmlConfiguration
as well.
I'll assume you have the classes for com.documentum.cts.webservices.remote.TransformationServlet
and com.documentum.cts.webservices.remote.FileProxyServlet
in a JAR somewhere (we'll call it app.jar
for this demo).
So follow along ...
$ curl -O https://repo1.maven.org/maven2/org/eclipse/jetty/jetty-home/9.4.44.v20210927/jetty-home-9.4.44.v20210927.tar.gz
$ tar -zxf jetty-home-9.4.44.v20210927.tar.gz
$ mkdir my-jetty-base
[my-jetty-base]$ java -jar ../jetty-home-9.4.44.v20210927/start.jar --add-to-start=http,https,deploy,ext
[my-jetty-base]$ cp $HOME/projects/documentum/context.xml webapps/
[my-jetty-base]$ cp $HOME/projects/documentum/target/app.jar lib/ext
[my-jetty-base]$ mkdir webapps/context
[my-jetty-base]$ mkdir ctx-file-resources
[my-jetty-base]$ tree -F
.
├── ctx-file-resources/
├── etc/
│ └── keystore
├── lib/
│ └── ext/
│ └── app.jar
├── start.ini
└── webapps/
└── context.xml
5 directories, 4 files
[my-jetty-base]$ cat webapps/context.xml
<?xml version="1.0"?>
<!DOCTYPE Configure PUBLIC "-//Jetty//Configure//EN" "http://www.eclipse.org/jetty/configure_9_3.dtd">
<Configure id="custom-context" class="org.eclipse.jetty.servlet.ServletContextHandler">
<Set name="contextPath">/ctx</Set>
<Set name="resourceBase"><Property name="jetty.webapps"/>/context</Set>
<Call name="addServlet">
<Arg>com.custom.TranServlet</Arg>
<Arg>/*</Arg>
</Call>
<Call id="fileProxHolder" name="addServlet">
<Arg>com.custom.FileProxServlet</Arg>
<Arg>/resource/*</Arg>
<Call name="setInitParameter">
<Arg>resourcesPath</Arg>
<Arg><Property name="jetty.base"/>/ctx-file-resources</Arg>
</Call>
</Call>
</Configure>
Now if we start this server ...
[]$ cd my-jetty-base
[my-jetty-base]$ java -jar ../jetty-home-9.4.44.v20210927/start.jar
2021-10-29 11:16:11.446:INFO::main: Logging initialized @407ms to org.eclipse.jetty.util.log.StdErrLog
2021-10-29 11:16:11.696:INFO:oejs.Server:main: jetty-9.4.44.v20210927; built: 2021-09-27T23:02:44.612Z; git: 8da83308eeca865e495e53ef315a249d63ba9332; jvm 11.0.12+7
2021-10-29 11:16:11.712:INFO:oejdp.ScanningAppProvider:main: Deployment monitor [file:///home/joakim/code/jetty/distros/bases/my-jetty-base/webapps/] at interval 1
2021-10-29 11:16:11.748:INFO:oejsh.ContextHandler:main: Started o.e.j.s.ServletContextHandler@1500b2f3{/ctx,file:///home/joakim/code/jetty/distros/bases/my-jetty-base/webapps/context,AVAILABLE}
2021-10-29 11:16:11.767:INFO:oejs.AbstractConnector:main: Started ServerConnector@12ec64c4{HTTP/1.1, (http/1.1)}{0.0.0.0:8080}
2021-10-29 11:16:11.796:INFO:oejus.SslContextFactory:main: x509=X509@4f704591(jetty,h=[jetty.eclipse.org],a=[],w=[]) for Server@3ddc6915[provider=null,keyStore=file:///home/joakim/code/jetty/distros/bases/my-jetty-base/etc/keystore,trustStore=file:///home/joakim/code/jetty/distros/bases/my-jetty-base/etc/keystore]
2021-10-29 11:16:11.796:INFO:oejus.SslContextFactory:main: x509=X509@704deff2(mykey,h=[jetty server],a=[],w=[]) for Server@3ddc6915[provider=null,keyStore=file:///home/joakim/code/jetty/distros/bases/my-jetty-base/etc/keystore,trustStore=file:///home/joakim/code/jetty/distros/bases/my-jetty-base/etc/keystore]
2021-10-29 11:16:11.872:INFO:oejs.AbstractConnector:main: Started ServerConnector@435f001f{SSL, (ssl, http/1.1)}{0.0.0.0:8443}
2021-10-29 11:16:11.873:INFO:oejs.Server:main: Started @834ms
There you go, you've the minimal necessary to have your ServletContextHandler
running.
It can serve http://localhost:8080/ctx/
and http://localhost:8080/ctx/resource/
with only 1 context.
Supports both http and https at the same time.
No webapp, no war, etc.
But if you still want to do this entirely in XML on your own, use XmlConfiguration
properly.
There's an example of this at the Eclipse Jetty Embedded Cookbook
See: XmlServer
, note
that this links to the jetty-9.4.x
branch version, there's also a jetty-10.0.x
and jetty-11.0.x
version on their own branches as well.
Important Note: Jetty 9.4.x is in maintenance mode and is being wound down, only bug fixes and security patches are going into that major version.
The mainline stable branches on Eclipse Jetty are current Jetty 10.0.x and 11.0.x, use those for new development.
To use XmlConfiguration
properly, you have to be aware of the separate XML, properties, and ID Maps.
The normal execution loop of XmlConfiguration
is as follows ...
/**
* Configure for the list of XML Resources and Properties.
*
* @param xmls the xml resources (in order of execution)
* @param properties the properties to use with the XML
* @return the ID Map of configured objects (key is the id name in the XML, and the value is configured object)
* @throws Exception if unable to create objects or read XML
*/
public static Map<String, Object> configure(List<Resource> xmls, Map<String, String> properties) throws Exception
{
Map<String, Object> idMap = new HashMap<>();
// Configure everything
for (Resource xmlResource : xmls)
{
XmlConfiguration configuration = new XmlConfiguration(xmlResource);
configuration.getIdMap().putAll(idMap);
configuration.getProperties().putAll(properties);
configuration.configure();
idMap.putAll(configuration.getIdMap());
}
return idMap;
}
This takes a list of XML (in the correct order of execution), and a properties map.
The XML are loaded in sequence and you get a Map of <id-string>
to <configured-object>
returned.
The example linked above has a complete example, with XML from jetty-home (unmodified), and some custom XML to include new functionality. It even includes the SSL / HTTPS layer and shows how to configure it (via properties). And it shows how to setup the list of XML and the Properties. Along with how to get the Server out of the ID Map.
For the best success treat the XML from jetty-home as read-only, don't modify it, don't edit it, you don't need to.
Honest, don't change the XML, you don't have to do it. In the 200+ million installs of Jetty 9.4 there hasn't been one verified case of
needing to change/edit the XML from jetty-home (people think they need to, but that's just because they don't understand how
to use the Jetty XML or the XmlConfiguration
properly, and each example given to us as "proof" that they need to edit the XML
has been shown with often multiple ways where you don't need to).
We believe in this so much that the XML in jetty-home is now read-only!