Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Jetty 12.0.x 12191 alt debug listener #12254

Merged
merged 14 commits into from
Sep 30, 2024
Merged
Show file tree
Hide file tree
Changes from 10 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -202,40 +202,92 @@ $ java -jar $JETTY_HOME/start.jar -Dmyapps.dir=/opt/myapps
[[env-context-xml]]
== Deploying Environment Specific Context XML Files

A xref:xml/index.adoc[Jetty context XML file] file can be applied to _all_ webapps deployed to a particular `environment` by adding a file named `{ee-all}.properties` containing the location of the file.
xref:xml/index.adoc[Jetty context XML file] files can be applied to _all_ webapps deployed to a particular `environment`.

This environment-specific Jetty context XML file will be applied to the webapps _before_ any context XML file associated with the webapp.
Thus, it can be used to configure general defaults to all webapps for a given `environment`, allowing a webapp-specific context XML file to further refine or override that configuration.
Add a properties file to the deployment directory that contains a property naming the location of the xml file to apply.
The properties file name must be prefixed by the name of the `environment`.
For example `ee8.properties, ee8-more.properties ee8-other.properties` would all apply to all contexts deployed in the `ee8` environment.

If the property file(s) contain one or more properties whose names are prefixed with `org.eclipse.jetty.deploy.environmentXml`, then their values are used as additional context XML files to apply to all contexts deployed in the corresponding environment.
So for example `org.eclipse.jetty.deploy.environmentXml, org.eclipse.jetty.deploy.environmentXml.more, org.eclipse.jetty.deploy.environmentXml.other` are all acceptable as names.
Each property configures the location of a context XML file to apply to a context when it is being created and deployed.
The location may be either absolute or relative to _the parent of the deployment directory_.
So if your webapp deployment directory is `$JETTY_BASE/webapps`, then `$JETTY_BASE` will be used to resolve any relative filenames.

All environment-specific Jetty context XML files will be applied to the webapp _before_ any context XML file associated with the webapp.
The order in which they are applied is determined by _the name of the properties that define them_.

IMPORTANT: The contents of the environment specific context XML file may only contain references to classes appropriate for that environment.

The `{ee-all}.properties` file must be in the same directory as the webapp being deployed.
It must contain the property `jetty.deploy.environmentXml` set to the location of the context XML file.
The location may be either absolute or relative to the parent of the deployment directory (usually `$JETTY_BASE`).
For example, given the previous example of a `$JETTY_BASE/webapps/wiki.xml` and its accompanying `$JETTY_BASE/webapps/wiki.properties` file that declares the `wiki` webapp should be deployed to environment `{ee-current}`, files called `$JETTY_BASE/webapps/{ee-current}.properties` and `$JETTY_BASE/webapps/{ee-current}-feature.properties` can be defined to further configure the webapp.

For example, given the previous example of a `$JETTY_BASE/webapps/wiki.xml` and its accompanying `$JETTY_BASE/webapps/wiki.properties` file that declares the `wiki` webapp should be deployed to environment `{ee-current}`, a file called `$JETTY_BASE/webapps/{ee-current}.properties` can be defined containing the following:
The `{ee-current}.properties` file contains:

.{ee-current}.properties
[,properties,subs=attributes+]
----
jetty.deploy.environmentXml=etc/{ee-current}-context.xml
----

The `{ee-current}-feature.properties` file contains:

.{ee-current}-feature.properties
[,properties,subs=attributes+]
----
jetty.deploy.environmentXml.feature=etc/{ee-current}-feature.xml
----

The `{ee-current}-context.xml` file contains:

.{ee-current}-context.xml
[,xml,subs="attributes+,+quotes"]
----
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE Configure PUBLIC "-//Jetty//Configure//EN" "https://jetty.org/configure_10_0.dtd">

<Configure id="wac" class="org.eclipse.jetty.{ee-current}.webapp.WebAppContext">
<Call name="setAttribute">
<Arg>common</Arg>
<Arg>value</Arg>
</Call>
</Configure>
----

The `{ee-current}-feature.xml` file contains:

.{ee-current}-feature.xml
[,xml,subs="attributes+,+quotes"]
----
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE Configure PUBLIC "-//Jetty//Configure//EN" "https://jetty.org/configure_10_0.dtd">

<Configure id="wac" class="org.eclipse.jetty.{ee-current}.webapp.WebAppContext">
<Call name="addEventListener">
<Arg>
<New class="com.example.MyListenerFeature"/>
</Arg>
</Call>
</Configure>
----


The directory structure would look like this:

.directory structure
[,properties,subs=attributes+]
----
$JETTY_BASE
├── etc
│ └── {ee-current}-context.xml
└── webapps
├── {ee-current}.properties
├── wiki.properties
└── wiki.xml
|- etc
│ |-{ee-current}-context.xml
| |-{ee-current}-feature.xml
|- webapps
|-{ee-current}.properties
|-{ee-current}-feature.properties
|-wiki.properties
|- wiki.xml
----

The contents of the `$JETTY_BASE/etc/{ee-current}-context.xml` file will be applied to the `wiki` webapp instance _before_ the `wiki.xml`, allowing the contents of the latter to override the contents of the former.
The contents of the `$JETTY_BASE/etc/{ee-current}-context.xml` then `$JETTY_BASE/etc/{ee-current}-feature.xml` files will be applied to the `wiki` webapp instance _before_ `wiki.xml`, allowing the contents of the latter to override the contents of the former.

== WEB-INF/jetty-{ee-all}-web.xml

Expand Down Expand Up @@ -264,7 +316,7 @@ The JNDI entry must be _defined_ in a xref:jndi/index.adoc#xml[Jetty XML file],
<Configure id="wac" class="org.eclipse.jetty.{ee-current}.webapp.WebAppContext">
<Set name="contextPath">/mywebapp</Set>
<Set name="war">/opt/webapps/mywebapp.war</Set>
#<New class="org.eclipse.jetty.plus.jndi.Resource">
<New class="org.eclipse.jetty.plus.jndi.Resource">
<Arg><Ref refid="wac"/></Arg>
<Arg>jdbc/myds</Arg>
<Arg>
Expand All @@ -274,7 +326,7 @@ The JNDI entry must be _defined_ in a xref:jndi/index.adoc#xml[Jetty XML file],
<Set name="password">password</Set>
</New>
</Arg>
</New>#
</New>
</Configure>
----

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -99,6 +99,20 @@ It is recommended that you consider configuring also the property `jetty.crossor
When set to `true`, clients send cookies and authentication headers in cross-origin requests to your domain.
When set to `false`, cookies and authentication headers are not sent.

[[eeN-debug]]
== Module `{ee-all}-debug`
include::{jetty-home}/modules/ee10-debug.mod[tags=description]
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There is N, all and 10 in this paragraph


Enabling this module produces a log file that is useful to debug incoming traffic.
It will log entry and exit points of HTTP requests as well as the response code.

Multiple versions of this module exist (`{ee-all}-debug`) to support each Jakarta EE platform's version of the Java Servlet specification.
Jetty's configuration properties are identical across these versions; the configuration properties for the `{ee-current}-debug` Jetty module are:

----
include::{jetty-home}/modules/ee10-debug.mod[tags=ini-template]
----

[[eeN-deploy]]
== Module `{ee-all}-deploy`

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,12 +24,15 @@
import java.nio.file.Paths;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Comparator;
import java.util.HashMap;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.Objects;
import java.util.Properties;
import java.util.function.Supplier;
import java.util.stream.Collectors;
import java.util.stream.Stream;

import org.eclipse.jetty.deploy.App;
Expand Down Expand Up @@ -302,7 +305,10 @@ else if (Supplier.class.isAssignableFrom(context.getClass()))
initializeContextPath(contextHandler, path);

if (Files.isDirectory(path))
{
contextHandler.setBaseResource(ResourceFactory.of(this).newResource(path));
System.err.println("SET BASE RESOURCE to " + path);
}

//TODO think of better way of doing this
//pass through properties as attributes directly
Expand Down Expand Up @@ -356,25 +362,79 @@ public ContextHandler createContextHandler(final App app) throws Exception
if (contextHandlerClassName != null)
context = Class.forName(contextHandlerClassName).getDeclaredConstructor().newInstance();

//add in environment-specific properties
//Add in environment-specific properties:
// allow multiple eeXX[-zzz].properties files, ordered lexically
// allow each to contain jetty.deploy.environmentXml[.zzzz] properties
// accumulate all properties for substitution purposes
// order all jetty.deploy.environmentXml[.zzzz] properties lexically
// apply the context xml files named by the ordered jetty.deploy.environmentXml[.zzzz] properties
String env = app.getEnvironmentName() == null ? "" : app.getEnvironmentName();
Path envProperties = app.getPath().getParent().resolve(env + ".properties");
if (Files.exists(envProperties))

if (StringUtil.isNotBlank(env))
{
try (InputStream stream = Files.newInputStream(envProperties))
List<Path> envPropertyFiles = new ArrayList<>();
Path parent = app.getPath().getParent();

//Get all environment specific properties files for this environment,
//order them according to the lexical ordering of the filenames
try (Stream<Path> paths = Files.list(parent))
{
envPropertyFiles = paths.filter(Files::isRegularFile)
.map(p -> parent.relativize(p))
.filter(p ->
{
String name = p.getName(0).toString();
if (!name.endsWith(".properties"))
return false;
if (!name.startsWith(env))
return false;
return true;
}).sorted().collect(Collectors.toList());
}

if (LOG.isDebugEnabled())
LOG.debug("Environment property files {}", envPropertyFiles);

Map<String, Path> envXmlFilenameMap = new HashMap<>();
for (Path file : envPropertyFiles)
{
Properties p = new Properties();
p.load(stream);
p.stringPropertyNames().forEach(k -> properties.put(k, p.getProperty(k)));
Path resolvedFile = parent.resolve(file);
if (Files.exists(resolvedFile))
{
Properties tmp = new Properties();
try (InputStream stream = Files.newInputStream(resolvedFile))
{
tmp.load(stream);
//put each property into our substitution pool
tmp.stringPropertyNames().forEach(k -> properties.put(k, tmp.getProperty(k)));
}
}
}

String str = properties.get(Deployable.ENVIRONMENT_XML);
if (!StringUtil.isEmpty(str))
//extract any properties that name environment context xml files
for (Map.Entry<String, String> entry : properties.entrySet())
{
Path envXmlPath = Paths.get(str);
if (!envXmlPath.isAbsolute())
envXmlPath = getMonitoredDirResource().getPath().getParent().resolve(envXmlPath);
String name = Objects.toString(entry.getKey(), "");
if (name.startsWith(Deployable.ENVIRONMENT_XML))
{
//ensure all environment context xml files are absolute paths
Path envXmlPath = Paths.get(entry.getValue().toString());
if (!envXmlPath.isAbsolute())
envXmlPath = getMonitoredDirResource().getPath().getParent().resolve(envXmlPath);
//accumulate all properties that name environment xml files so they can be ordered
envXmlFilenameMap.put(name, envXmlPath);
}
}

//order the environment context xml files according to the name of their properties
List<String> sortedEnvXmlProperties = envXmlFilenameMap.keySet().stream().sorted().toList();

//apply each environment context xml file
for (String property : sortedEnvXmlProperties)
{
Path envXmlPath = envXmlFilenameMap.get(property);
if (LOG.isDebugEnabled())
LOG.debug("Applying environment specific context file {}", envXmlPath);
context = applyXml(context, envXmlPath, env, properties);
}
}
Expand Down Expand Up @@ -427,9 +487,10 @@ else if (!Files.isDirectory(path) && !FileID.isWebArchive(path))
throw new IllegalStateException("Unknown ContextHandler class " + contextHandlerClassName + " for " + app);

context = contextHandlerClass.getDeclaredConstructor().newInstance();
properties.put(Deployable.WAR, path.toString());
}

//set a backup value for the path to the war in case it hasn't already been set
properties.put(Deployable.WAR, path.toString());
return initializeContextHandler(context, path, properties);
}
finally
Expand Down
Loading
Loading