diff --git a/jetty-documentation/src/main/asciidoc/administration/startup/chapter.adoc b/jetty-documentation/src/main/asciidoc/administration/startup/chapter.adoc index 441d8d47d87..3b63ab8ae5e 100644 --- a/jetty-documentation/src/main/asciidoc/administration/startup/chapter.adoc +++ b/jetty-documentation/src/main/asciidoc/administration/startup/chapter.adoc @@ -28,3 +28,4 @@ include::custom-modules.adoc[] include::startup-xml-config.adoc[] include::startup-unix-service.adoc[] include::startup-windows-service.adoc[] +include::startup-jpms.adoc[] diff --git a/jetty-documentation/src/main/asciidoc/administration/startup/startup-jpms.adoc b/jetty-documentation/src/main/asciidoc/administration/startup/startup-jpms.adoc new file mode 100644 index 00000000000..b6fdb7b9671 --- /dev/null +++ b/jetty-documentation/src/main/asciidoc/administration/startup/startup-jpms.adoc @@ -0,0 +1,190 @@ +// +// ======================================================================== +// Copyright (c) 1995-2018 Mort Bay Consulting Pty. Ltd. +// ======================================================================== +// All rights reserved. This program and the accompanying materials +// are made available under the terms of the Eclipse Public License v1.0 +// and Apache License v2.0 which accompanies this distribution. +// +// The Eclipse Public License is available at +// http://www.eclipse.org/legal/epl-v10.html +// +// The Apache License v2.0 is available at +// http://www.opensource.org/licenses/apache2.0.php +// +// You may elect to redistribute this code under either of these licenses. +// ======================================================================== +// + +[[startup-overview]] +=== Startup using the Java Platform Module System (JPMS) + +Jetty modules are also automatic https://en.wikipedia.org/wiki/Java_Platform_Module_System[JPMS] +modules via the `Automatic-Module-Name` attribute in the jar's `MANIFEST.MF` file. + +This makes possible to run Jetty from the module-path, rather than the class-path. + +We recommend to use JDK 11 or greater due to the fact that JDK 11 removed all the +"enterprise" modules from the JDK. +The classes in these "enterprise" modules were bundled with JDK 8, and present in +"enterprise" modules in JDK 9 and JDK 10. +With JDK 11, these "enterprise" classes are either not available in the JDK (because +their corresponding module was removed), or they are present in a different module. + +Some of these "enterprise" classes are required by Jetty or by applications running +in Jetty, so it is better to use a stable source for those classes by using JDK 11 +or greater. + +==== Starting Jetty on the module-path + +To start Jetty on the module-path, rather than the class-path, it is enough to add +the `--jpms` option to the command line, for example: + +[source, screen, subs="{sub-order}"] +.... +$ mkdir my-jetty-base +$ cd my-jetty-base +$ java -jar $JETTY_HOME/start.jar --add-to-start=http +INFO : server transitively enabled, ini template available with --add-to-start=server +INFO : http initialized in ${jetty.base}/start.ini +INFO : threadpool transitively enabled, ini template available with --add-to-start=threadpool +INFO : Base directory was modified +$ java -jar $JETTY_HOME/start.jar --jpms +.... + +The example above creates a link:#startup-base-and-home[Jetty base directory] and +enables the `http` module using `--add-to-start`. +Then starts Jetty on the module-path using the `--jpms` option. + +---- +[NOTE] +When running on the module-path using the `--jpms` option, the Jetty start mechanism +will fork a second JVM passing it the right JVM options to run on the module-path. + +You will have two JVMs running: one that runs `start.jar` and one that runs Jetty on +the module-path. +---- + +If you are interested in the details of how the command line to run Jetty on the +module-path looks like, you can add the `--dry-run` option: + +[source, screen, subs="{sub-order}"] +.... +$ java -jar $JETTY_HOME/start.jar --jpms --dry-run +.... + +You will see something like this (broken in sections for clarity): + +[source, screen, subs="{sub-order}"] +.... +/opt/openjdk-11+28/bin/java +--module-path /opt/jetty/lib/servlet-api-3.1.jar:/opt/jetty/lib/jetty-schemas-3.1.jar:/opt/jetty/lib/jetty-http-9.4.13-SNAPSHOT.jar:... +--patch-module servlet.api=/opt/jetty/lib/jetty-schemas-3.1.jar +--module org.eclipse.jetty.xml/org.eclipse.jetty.xml.XmlConfiguration /opt/jetty/etc/jetty-threadpool.xml /opt/jetty/etc/jetty.xml ... +.... + +The `--module-path` option specifies the list of Jetty jars. This list depends +on the Jetty modules that have been enabled via `--add-to-start`. + +The `--patch-module` option is necessary for Servlet and JSP Containers to find XML DTDs +and XML Schemas required to validate the various XML files present in web applications +(such as `web.xml` and others). + +The `--module` option tells the JVM to run main class `XmlConfiguration` from the +`org.eclipse.jetty.xml` module, with the given XML files as program arguments. + +When the JVM starts, module `org.eclipse.jetty.xml` is added to the set of JPMS +_root modules_; all other Jetty modules, being automatic, will be resolved and added +to the module graph; jars that are not modules such as `servlet-api-3.1.jar` are on +the module-path and therefore will be made automatic modules by the JVM (hence the +derived module name `servlet.api` for this jar, referenced by the `--patch-module` +command line option above). + +==== Advanced JPMS Configuration + +Web applications may need additional services from the Servlet Container, such as +JDBC `DataSource` references or JTA `UserTransaction` references. + +For example, for JDBC it is typical to store in JNDI a reference to the connection +pool's `DataSource` (for example `com.zaxxer.hikari.HikariDataSource`) or a +reference directly to the JDBC driver's `DataSource` (for example +`com.mysql.jdbc.jdbc2.optional.MysqlDataSource`). +Jetty needs to be able to instantiate those classes and therefore needs to be able +to load those classes and all their super-classes, among which `javax.sql.DataSource`. + +When Jetty runs on the class-path, this is easily achieved by using a +link:#custom-modules[custom module]: + +[source, screen, subs="{sub-order}"] +.mysql.mod +.... +[description] +MySQL module + +[lib] +lib/mysql/mysql-connector-java-*.jar +.... + +However, when running on the module-path, things are quite different. + +Class `javax.sql.DataSource` is in a JDK bundled module named `java.sql`, which is +not automatic (it's a proper JPMS module) and it is not in the _root modules_ set; +because it is not an automatic module, it is not added to the module graph, and +therefore needs to be added explicitly using the JVM command line `--add-modules`. + +To add the JPMS module `java.sql` to the module graph, you need to modify +`mysql.mod` in the following way: + +[source, screen, subs="{sub-order}"] +.mysql.mod +.... +[description] +MySQL module + +[lib] +lib/mysql/mysql-connector-java-*.jar + +[jpms] +add-modules: java.sql +.... + +The new `[jpms]` section is only used when Jetty is started on the module-path +via the `--jpms` command line option. + +Assuming that `mysql-connector-java-*.jar` is a non JPMS modular jar, or an +automatic JPMS modular jar, the Jetty start mechanism will add +`mysql-connector-java-*.jar` to the module-path, and will add the JVM command +line option `--add-modules java.sql`. + +If `mysql-connector-java-*.jar` were a proper JPMS modular jar with name +(for example) `com.mysql.jdbc`, then it would need to be explicitly added to +the module graph, in this way: + +[source, screen, subs="{sub-order}"] +.mysql.mod +.... +[description] +MySQL module + +[lib] +lib/mysql/mysql-connector-java-*.jar + +[jpms] +add-modules: com.mysql.jdbc +.... + +Now we don't need to add JPMS module `java.sql` explicitly because it would be +a dependency of the `com.mysql.jdbc` module and therefore automatically added +to the module graph. + +The `[jpms]` section has the following format: + +[source, screen, subs="{sub-order}"] +.... +[jpms] +add-modules: (,)* +patch-module: =(:)* +add-opens: /=(,)* +add-exports: /=(,)* +add-reads: =(,)* +....