Skip to content

Commit

Permalink
Jetty 12.0.x 12191 alt debug listener (#12254)
Browse files Browse the repository at this point in the history
* Issue #12191 reinstate debug listener modules

---------

Co-authored-by: Greg Wilkins <gregw@webtide.com>
  • Loading branch information
janbartel and gregw authored Sep 30, 2024
1 parent a1dbb72 commit 97ff548
Show file tree
Hide file tree
Showing 14 changed files with 543 additions and 149 deletions.
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 @@ -109,11 +109,26 @@ The module properties are:
include::{jetty-home}/modules/cross-origin.mod[tags=documentation]
----

You must configure at least the property `jetty.crossorigin.allowedOriginPatterns` to allow one or more origins.
[[debuglog]]
== Module `debuglog`

The `debuglog` module logs extra information about request processing.

This module installs the `DebugHandler` into the handler tree and logs information into a rollover log file.
By default, the location of the log file is `$JETTY_BASE/logs`, although this can be configured via the `jetty.debuglog.dir`.
The name of the log file is of the form: `yyyy_mm_dd.debug.log`, for example `2024-10-01.debug.log`.
All deployed contexts will write to the same log file.

Note that if a request uses asynchronous processing, the log event for the completion of handling may occur out of order with the log event for the continuation of processing.

If more precise logging of request processing is required - including well-ordered async processing events - or you wish to constrain request debug logging to particular contexts only, then configure an ee-specific `DebugListener` for each context instead of using this module.

The module properties are:

----
include::{jetty-home}/modules/debuglog.mod[tags=documentation]
----

It is recommended that you consider configuring also the property `jetty.crossorigin.allowCredentials`.
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-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));

This comment has been minimized.

Copy link
@vmassol

vmassol Nov 18, 2024

Hi, On the XWiki project and after upgrading from Jetty 12.0.12 to 12.0.15 we're now seeing in the logs:

2024-11-18 10:32:08,209 [CommonsExecStreamPumper-pool-37-thread-1] - SET BASE RESOURCE to /home/urli/Github/xwiki-platform/xwiki-platform-core/xwiki-platform-flamingo/xwiki-platform-flamingo-skin/xwiki-platform-flamingo-skin-test/xwiki-platform-flamingo-skin-test-docker/target/hsqldb_embedded-default-default-jetty_standalone-default-firefox/jetty/webapps/xwiki

Is this log wanted (and in this case, what can we do to fix it? :)), or is it some debug leftover?

Thanks a a lot

This comment has been minimized.

Copy link
@joakime

joakime Nov 18, 2024

Contributor

We don't use System.err like this elsewhere.
It is a left over from debugging IMO.

This comment has been minimized.

Copy link
@sbordet

sbordet Nov 18, 2024

Contributor

Removed in 6baadeb.

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

0 comments on commit 97ff548

Please sign in to comment.