//
// ========================================================================
// Copyright (c) 1995-2020 Mort Bay Consulting Pty Ltd and others.
//
// This program and the accompanying materials are made available under
// the terms of the Eclipse Public License 2.0 which is available at
// https://www.eclipse.org/legal/epl-2.0
//
// This Source Code may also be made available under the following
// Secondary Licenses when the conditions for such availability set
// forth in the Eclipse Public License, v. 2.0 are satisfied:
// the Apache License v2.0 which is available at
// https://www.apache.org/licenses/LICENSE-2.0
//
// SPDX-License-Identifier: EPL-2.0 OR Apache-2.0
// ========================================================================
//

[[jsp-support]]
=== Configuring JSP

This document provides information about configuring Java Server Pages (JSP) for Jetty.

[[which-jsp-implementation]]
==== Which JSP Implementation

Jetty uses Jasper from http://tomcat.apache.org/tomcat-8.0-doc/jasper-howto.html[Apache] as the default JSP container implementation.

By default the Jetty distribution enables the JSP link:#startup-modules[module], and by default, this module is set to Apache Jasper.

[source, plain, subs="{sub-order}"]
----
include::{SRCDIR}/jetty-home/src/main/resources/modules/jsp.mod[]
----

Note that the availability of some JSP features may depend on which JSP container implementation you are using.
Note also that it may not be possible to precompile your JSPs with one container and deploy to the other.

===== Logging

The Apache Jasper logging system is bridged to the jetty logging system.
Thus, you can enable logging for jsps in the same way you have setup for your webapp.
For example, assuming you are using Jetty's default StdErr logger, you would enable DEBUG level logging for jsps by adding the system property `-Dorg.apache.jasper.LEVEL=DEBUG` to the command line.

===== JSPs and Embedding

If you have an embedded setup for your webapp and wish to use JSPs, you will need to ensure that a JSP engine is correctly initialized.

For Apache, a Servlet Specification 3.1 style link:#servlet-container-initializers[ServletContainerInitializer] is used to accomplish this.
You will need to ensure that this ServletContainerInitializer is run by jetty. Perhaps the easiest way to do this is to enable annotations processing so that Jetty automatically discovers and runs it.
The link:#embedded-examples[Embedded Examples] section includes a link:#embedded-webapp-jsp[worked code example] of how to do this.

Alternatively, you can manually wire in the appropriate ServletContainerInitializer as shown in the https://github.com/jetty-project/embedded-jetty-jsp/blob/master/src/main/java/org/eclipse/jetty/demo/Main.java[embedded-jetty-jsp] example on https://github.com/jetty-project[GitHub], in which case you will not need the jetty-annotations jar on your classpath, nor include the AnnotationConfiguration in the list of link:#webapp-configurations[configuration classes].

==== Precompiling JSPs

You can either follow the instructions on precompilation provided by Apache, or if you are using Maven for your builds, you can use the link:#jetty-jspc-maven-plugin[jetty-jspc-maven] plugin to do it for you.

If you have precompiled your JSPs, and have customized the output package prefix (which is `org.apache.jsp` by default), you should configure your webapp context to tell Jetty about this custom package name.
You can do this using a servlet context init-param called `org.eclipse.jetty.servlet.jspPackagePrefix`.

For example, suppose you have precompiled your JSPs with the custom package prefix of `com.acme`, then you would add the following lines to your `web.xml` file:

[source, xml, subs="{sub-order}"]
----
  <context-param>
    <param-name>org.eclipse.jetty.servlet.jspPackagePrefix</param-name>
    <param-value>com.acme</param-value>
  </context-param>
----

____
[NOTE]
Both Jetty Maven plugins - link:#jetty-jspc-maven-plugin[jetty-jspc-maven-plugin] and the link:#jetty-maven-plugin[jetty-maven-plugin] - will only use Apache Jasper.
____

[[compiling-jsps]]
===== Apache JSP Container

By default, the Apache JSP container will look for the Eclipse Java Compiler (jdt).
The Jetty distribution ships a copy of this in `{$jetty.home}/lib/apache-jsp`.
If you wish to use a different compiler, you will need to configure the `compilerClassName` init-param on the `JspServlet` with the name of the class.

.Understanding Apache JspServlet Parameters
[cols=",,,",options="header",]
|=======================================================================
|init param |Description |Default |`webdefault.xml`

|checkInterval |If non-zero and `development` is `false`, background jsp recompilation is enabled. This value is the interval in seconds between background recompile checks.
               |0 |–
|classpath |The classpath is dynamically generated if the context has a URL classloader. The `org.apache.catalina.jsp_classpath`
context attribute is used to add to the classpath, but if this is not set, this `classpath` configuration item is added to the classpath instead.` |- |–

|classdebuginfo |Include debugging info in class file. |TRUE |–

|compilerClassName |If not set, defaults to the Eclipse jdt compiler. |- |–

|compiler |Used if the Eclipse jdt compiler cannot be found on the
classpath. It is the classname of a compiler that Ant should invoke. |–
|–

|compilerTargetVM |Target vm to compile for. |1.8 |1.8

|compilerSourceVM |Sets source compliance level for the jdt compiler.
|1.8 |1.8

|development |If `true` recompilation checks occur at the frequency governed by `modificationTestInterval`. |TRUE |–

|displaySourceFragment |Should a source fragment be included in
exception messages |TRUE |–

|dumpSmap |Dump SMAP JSR45 info to a file. |FALSE |–

|enablePooling |Determines whether tag handler pooling is enabled. |TRUE |–

|engineOptionsClass |Allows specifying the Options class used to
configure Jasper. If not present, the default EmbeddedServletOptions
will be used. |- |–

|errorOnUseBeanInvalidClassAttribute |Should Jasper issue an error when
the value of the class attribute in an useBean action is not a valid
bean class |TRUE |–

|fork |Only relevant if you use Ant to compile jsps: by default Jetty will use the Eclipse jdt compiler.|TRUE |-

|genStrAsCharArray |Option for generating Strings as char arrays. |FALSE |–

|ieClassId |The class-id value to be sent to Internet Explorer when
using <jsp:plugin> tags. |clsid:8AD9C840-044E-11D1-B3E9-00805F499D93 |–

|javaEncoding |Pass through the encoding to use for the compilation.
|UTF8 |–

|jspIdleTimeout |The amount of time in seconds a JSP can be idle before
it is unloaded. A value of zero or less indicates never unload. |-1 |–

|keepgenerated |Do you want to keep the generated Java files around?
|TRUE |–

|mappedFile |Support for mapped Files. Generates a servlet that has a
print statement per line of the JSP file  |TRUE |–

|maxLoadedJsps |The maximum number of JSPs that will be loaded for a web
application. If more than this number of JSPs are loaded, the least
recently used JSPs will be unloaded so that the number of JSPs loaded at
any one time does not exceed this limit. A value of zero or less
indicates no limit. |-1 |–

|modificationTestInterval |If `development=true`, interval between
recompilation checks, triggered by a request. |4 |–

|quoteAttributeEL | When EL is used in an attribute value on a JSP page, should the rules for quoting of attributes described in JSP.1.6 be applied to the expression
                 |TRUE |-

|recompileOnFail |If a JSP compilation fails should the
modificationTestInterval be ignored and the next access trigger a
re-compilation attempt? Used in development mode only and is disabled by
default as compilation may be expensive and could lead to excessive
resource usage. |FALSE |–

|scratchDir |Directory where servlets are generated. The default is the value of the context attribute `javax.servlet.context.tempdir`, or the system property `java.io.tmpdir` if the context attribute is not set. |– |–

|strictQuoteEscaping |Should the quote escaping required by section JSP.1.6 of the JSP specification be applied to scriplet expression.
             |TRUE|-

|suppressSmap |Generation of SMAP info for JSR45 debugging. |FALSE |–

|trimSpaces |Should template text that consists entirely of whitespace be removed from the output (true), replaced with a single space (single) or left unchanged (false)? Note that if a JSP page or tag file specifies a trimDirectiveWhitespaces value of true, that will take precedence over this configuration setting for that page/tag.
trimmed? |FALSE |–

|xpoweredBy |Generate an X-Powered-By response header. |FALSE |FALSE

|=======================================================================

[[configuring-jsp-for-jetty]]
===== Configuration

The JSP engine has many configuration parameters.
Some parameters affect only precompilation, and some affect runtime recompilation checking.
Parameters also differ among the various versions of the JSP engine.
This page lists the configuration parameters, their meanings, and their default settings.
Set all parameters on the `org.eclipse.jetty.jsp.JettyJspServlet` instance defined in the link:#webdefault-xml[`webdefault.xml`] file.

____
[NOTE]
Be careful: for all of these parameters, if the value you set doesn't take effect, try using all lower case instead of camel case, or capitalizing only some of the words in the name, as JSP is inconsistent in its parameter naming strategy.
____

[[modifying-configuration]]
==== Modifying Configuration

[[overriding-webdefault.xml]]
===== Overriding `webdefault.xml`

You can make a copy of the link:#webdefault-xml[{$jetty.home}/etc/webdefault.xml] that ships with Jetty, apply your changes, and use it instead of the shipped version.
The example below shows how to do this when using the Jetty Maven plugin.

[source, xml, subs="{sub-order}"]
----
  <plugin>
    <groupId>org.eclipse.jetty</groupId>
    <artifactId>jetty-maven-plugin</artifactId>
    <configuration>
      <webApp>
        <defaultsDescriptor>src/main/resources/webdefault.xml</defaultsDescriptor>
      </webApp>
  </plugin>
----

If you are using the Jetty distribution, and you want to change the JSP settings for just one or a few of your webapps, copy the `{$jetty.home}/etc/webdefault.xml` file somewhere, modify it, and then use a link:#intro-jetty-configuration-contexts[context xml] file to set this file as the `defaultsDescriptor` for your webapp. Here's a snippet:

[source, xml, subs="{sub-order}"]
----
 <Configure class=>"org.eclipse.jetty.webapp.WebAppContext">

   <Set name=>"contextPath">/foo</Set>
   <Set name=>"war"><SystemProperty name=>"jetty.home" >default=>"."/>/webapps/foobar.war</Set>
   <Set name=>"defaultsDescriptor">/home/smith/dev/webdefault.xml</Set>

 </Configure>
----

If you want to change the JSP settings for all webapps, edit the `{$jetty.home}/etc/webdefaults.xml` file directly instead.

[[configuring-jsp-servlet-in-web.xml]]
===== Configuring the JSP Servlet in web.xml

Another option is to add an entry for the JSPServlet to the `WEB-INF/web.xml` file of your webapp and change or add init-params.
You may also add (but not remove) servlet-mappings.
You can use the entry in link:#webdefault-xml[{$jetty.home}/etc/webdefault.xml] as a starting point.

[source, xml, subs="{sub-order}"]
----
 <servlet id="jsp">
     <servlet-name>jsp</servlet-name>
     <servlet-class>org.eclipse.jetty.jsp.JettyJspServlet</servlet-class>
     <init-param>
         <param-name>keepgenerated</param-name>
         <param-value>true</param-value>
     </init-param>
     ...

     <load-on-startup>0</load-on-startup>
   </servlet>

   <servlet-mapping>
     <servlet-name>jsp</servlet-name>
     <url-pattern>*.jsp</url-pattern>
     <url-pattern>*.jspf</url-pattern>
     <url-pattern>*.jspx</url-pattern>
     <url-pattern>*.xsp</url-pattern>
     <url-pattern>*.JSP</url-pattern>
     <url-pattern>*.JSPF</url-pattern>
     <url-pattern>*.JSPX</url-pattern>
     <url-pattern>*.XSP</url-pattern>
   </servlet-mapping>

   <servlet id="my-servlet">
     <servlet-name>myServlet</servlet-name>
     <servlet-class>com.acme.servlet.MyServlet</servlet-class>
      ...
----

[[jsp-async-support]]
===== Configuring Async Support

By default, Jetty does not enable async support for the JSP servlet.
Configuring the JSP servlet for async is relatively easy - simply define the `async-supported` parameter as `true` in either your `webdefault.xml` or the `web.xml` for a specific context.

[source, xml, subs="{sub-order}"]
----
<servlet id="jsp">
  <servlet-name>jsp</servlet-name>
  <async-supported>true</async-supported>
</servlet>
----

[[using-jstl-taglibs-for-jetty7-jetty8]]
==== Using JSTL Taglibs

The JavaServer Pages Standlard Tag Library (JSTL) is part of the Jetty distribution and is automatically put on the classpath when you link:#which-jsp-implementation[select your flavour of JSP].
It is also automatically on the classpath for the Jetty Maven plugin, which uses the Apache JSP engine.

===== Embedding

If you are using Jetty in an embedded scenario, and you need to use JSTL, then you must ensure that the JSTL jars are included on the _container's_ classpath - that is the classpath that is the _parent_ of the webapp's classpath.
This is a restriction that arises from the JavaEE specification.

====== Apache JSP

You will need to put the jars that are present in the `{$jetty.home}/lib/apache-jstl` directory onto the _container's_ classpath.
The Apache JSP engine will find the JSTL tag definitions inside these jars during startup.

As an efficiency enhancement, you can have jetty examine the JSTL jars to find the tags, and pre-feed them into the Apache JSP engine.
This is more efficient, because jetty will only scan the jars you tell it to, whereas the Apache JSP engine will scan every jar, which can be time-consuming in applications with a lot of jars on the container classpath.

To take advantage of this efficiency enhancement, set up the link:#container-include-jar-pattern[org.eclipse.jetty.server.webapp.ContainerIncludeJarPattern] to include a http://docs.oracle.com/javase/7/docs/api/java/util/regex/Pattern.html[pattern] that will match the names of the JSTL jars.
The link:#embedded-examples[Embedded Examples] section includes a link:#embedded-webapp-jsp[worked code example] of how to do this.
Below is a snippet from the example:

[source, java, subs="{sub-order}"]
----
  webapp.setAttribute("org.eclipse.jetty.server.webapp.ContainerIncludeJarPattern",".*/[^/]*taglibs.*\\.jar$");
----

[[using-jsf-taglibs]]
==== Using JSF Taglibs

The following sections provide information about using JSF TagLibs with Jetty Standalone and the Jetty Maven Plugin.

[[using-jsf-taglibs-with-jetty-standalone]]
===== Using JSF Taglibs with Jetty Distribution

If you want to use JSF with your webapp, you need to copy the JSF implementation Jar (whichever Jar contains the `META-INF/*.tld` files from your chosen JSF implementation) into Jetty's shared container lib directory.
You can either put them into the lib directory for Apache `{$jetty.home}/lib/apache-jsp` or put them into `{$jetty.home}/lib/ext`.

[[using-jsf-taglibs-with-jetty-maven-plugin]]
===== Using JSF Taglibs with Jetty Maven Plugin

You should make your JSF jars dependencies of the plugin and _not_ the webapp itself.
For example:

[source, xml, subs="{sub-order}"]
----
   <plugin>
    <groupId>org.eclipse.jetty</groupId>
    <artifactId>jetty-maven-plugin</artifactId>
    <configuration>
       <webApp>
         <contextPath>/${artifactId}</contextPath>
       </webApp>
       <scanIntervalSeconds>5</scanIntervalSeconds>
    </configuration>
    <dependencies>
      <dependency>
        <groupId>com.sun.faces</groupId>
        <artifactId>jsf-api</artifactId>
        <version>2.0.8</version>
      </dependency>
      <dependency>
        <groupId>com.sun.faces</groupId>
        <artifactId>jsf-impl</artifactId>
        <version>2.0.8</version>
     </dependency>
    </dependencies>
  </plugin>
----
