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

No jars added when using a folder in extraClasspath of the webapp context xml file #5129

Closed
asiemsuk opened this issue Aug 7, 2020 · 6 comments · Fixed by #5131
Closed
Assignees
Labels
Bug For general bugs on Jetty side Microsoft Windows For issues unique to Microsoft Windows

Comments

@asiemsuk
Copy link

asiemsuk commented Aug 7, 2020

Jetty version
9.4.31.v20200723

Java version
jvm 1.8.0_231-b11

OS type/version
Windows 10 64-bit

Description
I have a folder with a couple of jars:
E:\path\to\libs\jar1.jar
E:\path\to\libs\jar2.jar

In my webapp context xml file, I have this line:
<Set name="extraClasspath">E:\path\to\libs\</Set>

I am starting the server with this command:
java -Dorg.eclipse.jetty.webapp.WebAppClassLoader.LEVEL=DEBUG -jar start.jar

The server starts correctly and shows this line:
2020-08-07 10:26:39.055:DBUG:oejw.WebAppClassLoader:main: Path resource=file:///E:/path/to/libs/

But it does not add the jars in the folder.

If I change the extraClasspath to:
<Set name="extraClasspath">E:\path\to\libs\*</Set>

It shows the following lines when the server is starting:
2020-08-07 10:33:10.114:DBUG:oejw.WebAppClassLoader:main: Glob Path resource=file:///E:/path/to/libs/
2020-08-07 10:33:10.118:DBUG:oejw.WebAppClassLoader:main: addJar - file:///E:/path/to/libs/jar1.jar
2020-08-07 10:33:10.119:DBUG:oejw.WebAppClassLoader:main: Path resource=file:///E:/path/to/libs/jar1.jar
2020-08-07 10:33:10.121:DBUG:oejw.WebAppClassLoader:main: addJar - file:///E:/path/to/libs/jar2.jar

Then shows the following exception:
java.io.IOException: Invalid argument
at java.io.WinNTFileSystem.canonicalize0(Native Method)
at java.io.WinNTFileSystem.canonicalize(Unknown Source)
at java.io.File.getCanonicalPath(Unknown Source)
at java.io.File.getCanonicalFile(Unknown Source)
at org.eclipse.jetty.util.resource.Resource.newResource(Resource.java:182)
at org.eclipse.jetty.util.resource.Resource.newResource(Resource.java:151)
at org.eclipse.jetty.server.handler.ContextHandler.newResource(ContextHandler.java:1968)
at org.eclipse.jetty.webapp.WebInfConfiguration.findExtraClasspathJars(WebInfConfiguration.java:950)
at org.eclipse.jetty.webapp.WebInfConfiguration.findJars(WebInfConfiguration.java:882)
at org.eclipse.jetty.webapp.WebInfConfiguration.findAndFilterWebAppPaths(WebInfConfiguration.java:294)
at org.eclipse.jetty.webapp.WebInfConfiguration.preConfigure(WebInfConfiguration.java:145)
at org.eclipse.jetty.webapp.WebAppContext.preConfigure(WebAppContext.java:488)
at org.eclipse.jetty.webapp.WebAppContext.doStart(WebAppContext.java:523)
at org.eclipse.jetty.util.component.AbstractLifeCycle.start(AbstractLifeCycle.java:72)
at org.eclipse.jetty.deploy.bindings.StandardStarter.processBinding(StandardStarter.java:46)
at org.eclipse.jetty.deploy.AppLifeCycle.runBindings(AppLifeCycle.java:188)
at org.eclipse.jetty.deploy.DeploymentManager.requestAppGoal(DeploymentManager.java:513)
at org.eclipse.jetty.deploy.DeploymentManager.addApp(DeploymentManager.java:154)
at org.eclipse.jetty.deploy.providers.ScanningAppProvider.fileAdded(ScanningAppProvider.java:173)
at org.eclipse.jetty.deploy.providers.WebAppProvider.fileAdded(WebAppProvider.java:447)
at org.eclipse.jetty.deploy.providers.ScanningAppProvider$1.fileAdded(ScanningAppProvider.java:66)
at org.eclipse.jetty.util.Scanner.reportAddition(Scanner.java:784)
at org.eclipse.jetty.util.Scanner.reportDifferences(Scanner.java:753)
at org.eclipse.jetty.util.Scanner.scan(Scanner.java:641)
at org.eclipse.jetty.util.Scanner.doStart(Scanner.java:540)
at org.eclipse.jetty.util.component.AbstractLifeCycle.start(AbstractLifeCycle.java:72)
at org.eclipse.jetty.deploy.providers.ScanningAppProvider.doStart(ScanningAppProvider.java:146)
at org.eclipse.jetty.util.component.AbstractLifeCycle.start(AbstractLifeCycle.java:72)
at org.eclipse.jetty.deploy.DeploymentManager.startAppProvider(DeploymentManager.java:599)
at org.eclipse.jetty.deploy.DeploymentManager.doStart(DeploymentManager.java:249)
at org.eclipse.jetty.util.component.AbstractLifeCycle.start(AbstractLifeCycle.java:72)
at org.eclipse.jetty.util.component.ContainerLifeCycle.start(ContainerLifeCycle.java:169)
at org.eclipse.jetty.server.Server.start(Server.java:408)
at org.eclipse.jetty.util.component.ContainerLifeCycle.doStart(ContainerLifeCycle.java:117)
at org.eclipse.jetty.server.handler.AbstractHandler.doStart(AbstractHandler.java:97)
at org.eclipse.jetty.server.Server.doStart(Server.java:372)
at org.eclipse.jetty.util.component.AbstractLifeCycle.start(AbstractLifeCycle.java:72)
at org.eclipse.jetty.xml.XmlConfiguration.lambda$main$1(XmlConfiguration.java:1929)
at java.security.AccessController.doPrivileged(Native Method)
at org.eclipse.jetty.xml.XmlConfiguration.main(XmlConfiguration.java:1878)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
at java.lang.reflect.Method.invoke(Unknown Source)
at org.eclipse.jetty.start.Main.invokeMain(Main.java:218)
at org.eclipse.jetty.start.Main.start(Main.java:491)
at org.eclipse.jetty.start.Main.main(Main.java:77)
Suppressed:
|java.net.MalformedURLException: unknown protocol: e
| at java.net.URL.(Unknown Source)
| at java.net.URL.(Unknown Source)
| at java.net.URL.(Unknown Source)
| at org.eclipse.jetty.util.resource.Resource.newResource(Resource.java:169)
| at org.eclipse.jetty.util.resource.Resource.newResource(Resource.java:151)
| at org.eclipse.jetty.server.handler.ContextHandler.newResource(ContextHandler.java:1968)
| at org.eclipse.jetty.webapp.WebInfConfiguration.findExtraClasspathJars(WebInfConfiguration.java:950)
| at org.eclipse.jetty.webapp.WebInfConfiguration.findJars(WebInfConfiguration.java:882)
| at org.eclipse.jetty.webapp.WebInfConfiguration.findAndFilterWebAppPaths(WebInfConfiguration.java:294)
| at org.eclipse.jetty.webapp.WebInfConfiguration.preConfigure(WebInfConfiguration.java:145)
| at org.eclipse.jetty.webapp.WebAppContext.preConfigure(WebAppContext.java:488)
| at org.eclipse.jetty.webapp.WebAppContext.doStart(WebAppContext.java:523)
| at org.eclipse.jetty.util.component.AbstractLifeCycle.start(AbstractLifeCycle.java:72)
| at org.eclipse.jetty.deploy.bindings.StandardStarter.processBinding(StandardStarter.java:46)
| at org.eclipse.jetty.deploy.AppLifeCycle.runBindings(AppLifeCycle.java:188)
| at org.eclipse.jetty.deploy.DeploymentManager.requestAppGoal(DeploymentManager.java:513)
| at org.eclipse.jetty.deploy.DeploymentManager.addApp(DeploymentManager.java:154)
| at org.eclipse.jetty.deploy.providers.ScanningAppProvider.fileAdded(ScanningAppProvider.java:173)
| at org.eclipse.jetty.deploy.providers.WebAppProvider.fileAdded(WebAppProvider.java:447)
| at org.eclipse.jetty.deploy.providers.ScanningAppProvider$1.fileAdded(ScanningAppProvider.java:66)
| at org.eclipse.jetty.util.Scanner.reportAddition(Scanner.java:784)
| at org.eclipse.jetty.util.Scanner.reportDifferences(Scanner.java:753)
| at org.eclipse.jetty.util.Scanner.scan(Scanner.java:641)
| at org.eclipse.jetty.util.Scanner.doStart(Scanner.java:540)
| at org.eclipse.jetty.util.component.AbstractLifeCycle.start(AbstractLifeCycle.java:72)
| at org.eclipse.jetty.deploy.providers.ScanningAppProvider.doStart(ScanningAppProvider.java:146)
| at org.eclipse.jetty.util.component.AbstractLifeCycle.start(AbstractLifeCycle.java:72)
| at org.eclipse.jetty.deploy.DeploymentManager.startAppProvider(DeploymentManager.java:599)
| at org.eclipse.jetty.deploy.DeploymentManager.doStart(DeploymentManager.java:249)
| at org.eclipse.jetty.util.component.AbstractLifeCycle.start(AbstractLifeCycle.java:72)
| at org.eclipse.jetty.util.component.ContainerLifeCycle.start(ContainerLifeCycle.java:169)
| at org.eclipse.jetty.server.Server.start(Server.java:408)
| at org.eclipse.jetty.util.component.ContainerLifeCycle.doStart(ContainerLifeCycle.java:117)
| at org.eclipse.jetty.server.handler.AbstractHandler.doStart(AbstractHandler.java:97)
| at org.eclipse.jetty.server.Server.doStart(Server.java:372)
| at org.eclipse.jetty.util.component.AbstractLifeCycle.start(AbstractLifeCycle.java:72)
| at org.eclipse.jetty.xml.XmlConfiguration.lambda$main$1(XmlConfiguration.java:1929)
| at java.security.AccessController.doPrivileged(Native Method)
| at org.eclipse.jetty.xml.XmlConfiguration.main(XmlConfiguration.java:1878)
| at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
| at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source)
| at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
| at java.lang.reflect.Method.invoke(Unknown Source)
| at org.eclipse.jetty.start.Main.invokeMain(Main.java:218)
| at org.eclipse.jetty.start.Main.start(Main.java:491)
| at org.eclipse.jetty.start.Main.main(Main.java:77)

@joakime joakime self-assigned this Aug 7, 2020
@joakime
Copy link
Contributor

joakime commented Aug 7, 2020

The protocol error is new.
The two attempts you have used ...

  • <Set name="extraClasspath">E:\path\to\libs\</Set> - this will set the directory as a Resource, which is a normal behavior of a classloader for content that needs to exist on the filesystem and not in a JAR
  • <Set name="extraClasspath">E:\path\to\libs\*</Set> - this is the correct syntax, and should add it.

As a result of this filed issue I tried it out.

  • Using Windows 10 Pro
  • File System formatted to NTFS
  • Using jetty-home-9.4.31.v20200723
  • Using Java 8u232 (Oracle), and Java 8u265 (AdoptOpenJDK), and Java 11.0.7 (AdoptOpenJDK) ...

They all fail in the same way ...

joakim@AEGIR C:\code\jetty-dists\bases
$ mkdir mybase
joakim@AEGIR C:\code\jetty-dists\bases
$ cd mybase
joakim@AEGIR C:\code\jetty-dists\bases\mybase
$ java -jar C:\code\jetty-dists\jetty-home-9.4.31.v20200723\start.jar --add-to-start=http,deploy
INFO  : webapp          transitively enabled, ini template available with --add-to-start=webapp
INFO  : server          transitively enabled, ini template available with --add-to-start=server
INFO  : security        transitively enabled
INFO  : servlet         transitively enabled
INFO  : http            initialized in ${jetty.base}\start.ini
INFO  : threadpool      transitively enabled, ini template available with --add-to-start=threadpool
INFO  : bytebufferpool  transitively enabled, ini template available with --add-to-start=bytebufferpool
INFO  : deploy          initialized in ${jetty.base}\start.ini
MKDIR : ${jetty.base}\webapps
INFO  : Base directory was modified

joakim@AEGIR C:\code\jetty-dists\bases\mybase
$ copy C:\Users\joakim\Downloads\dump.war webapps\
        1 file(s) copied.

joakim@AEGIR C:\code\jetty-dists\bases\mybase
$ edit webapps\dump.xml

joakim@AEGIR C:\code\jetty-dists\bases\mybase
$ type webapps\dump.xml
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE Configure PUBLIC "-//Jetty//Configure//EN" "http://www.eclipse.org/jetty/configure_9_3.dtd">

<Configure class="org.eclipse.jetty.webapp.WebAppContext">
  <Set name="contextPath">/dump</Set>
  <Set name="war"><Property name="jetty.webapps"/>/dump.war</Set>
  <Set name="extraClasspath">C:\code\other\libs\*</Set>
</Configure>

joakim@AEGIR C:\code\jetty-dists\bases\mybase
$ dir C:\code\other\libs\
 Volume in drive C is OS
 Volume Serial Number is AED9-DC60

 Directory of C:\code\other\libs

08/07/2020  10:26 AM    <DIR>          .
08/07/2020  10:26 AM    <DIR>          ..
06/04/2020  11:10 AM           146,108 commons-digester-1.8.1.jar
06/04/2020  11:03 AM           501,879 commons-lang3-3.8.1.jar
08/07/2020  10:24 AM             3,914 corp-lib-1.2.0.jar
               3 File(s)        651,901 bytes
               2 Dir(s)  878,228,082,688 bytes free

joakim@AEGIR C:\code\jetty-dists\bases\mybase
$ java -jar ..\..\jetty-home-9.4.31.v20200723\start.jar -Djetty.server.dumpAfterStart=true
...(snip lots of output)...
+= HandlerCollection@13c9d689{STARTED} - STARTED
|  += ContextHandlerCollection@1bb266b3{STARTED} - STARTED
|  |  += o.e.j.w.WebAppContext@247310d0{/dump,file:///C:/Users/joakim/AppData/Local/Temp/jetty-0_0_0_0-8080-dump_war-_dump-any-278118249111983646.dir/webapp/,UNAVAILABLE}{C:\code\jetty-dists\bases\mybase\webapps/dump.war} - STARTED
|  |     += org.eclipse.jetty.server.session.SessionHandler504807594==dftMaxIdleSec=-1 - STOPPED
|  |     |  += ConstraintSecurityHandler@13d73f29{STOPPED} - STOPPED
|  |     |     +- knownAuthenticatorFactories size=1
|  |     |     |  +> org.eclipse.jetty.security.DefaultAuthenticatorFactory@565f390
|  |     |     += ServletHandler@7dc3712{STOPPED} - STOPPED
|  |     |     |  +> listeners ServletHandler@7dc3712{STOPPED} size=0
|  |     |     |  +> filters ServletHandler@7dc3712{STOPPED} size=0
|  |     |     |  +> filterMappings ServletHandler@7dc3712{STOPPED} size=0
|  |     |     |  +> servlets ServletHandler@7dc3712{STOPPED} size=0
|  |     |     |  +> servletMappings ServletHandler@7dc3712{STOPPED} size=0
|  |     |     +> roles size=1
|  |     |     |  +> java.util.concurrent.CopyOnWriteArraySet@0(size=0)
|  |     |     +> constraints size=1
|  |     |        +> java.util.HashMap$EntrySet@0(size=0)
|  |     += ErrorPageErrorHandler@2f67a4d3{STOPPED} - STOPPED
|  |     +> WebAppClassLoader{1534694976}@5b799640
|  |     |  +> URLs size=3
|  |     |  |  +> file:/C:/code/other/libs/commons-digester-1.8.1.jar
|  |     |  |  +> file:/C:/code/other/libs/commons-lang3-3.8.1.jar
|  |     |  |  +> file:/C:/code/other/libs/corp-lib-1.2.0.jar
|  |     |  +> startJarLoader@1f28c152

The JARs were added to the WebAppClassLoader, but the attempt to discover the canonical path triggered an Exception.
And that exception stopped the WebAppContext. (as it was expected).

I get the same exception on all versions of Java I've tested on this machine ...

java.io.IOException: Bad pathname
        at java.base/java.io.WinNTFileSystem.canonicalize0(Native Method)
        at java.base/java.io.WinNTFileSystem.canonicalize(WinNTFileSystem.java:438)
        at java.base/java.io.File.getCanonicalPath(File.java:618)
        at java.base/java.io.File.getCanonicalFile(File.java:643)
        at org.eclipse.jetty.util.resource.Resource.newResource(Resource.java:182)
        at org.eclipse.jetty.util.resource.Resource.newResource(Resource.java:151)
...(snip)...
        |java.net.MalformedURLException: unknown protocol: c
        |       at java.base/java.net.URL.<init>(URL.java:651)
        |       at java.base/java.net.URL.<init>(URL.java:540)
        |       at java.base/java.net.URL.<init>(URL.java:487)
        |       at org.eclipse.jetty.util.resource.Resource.newResource(Resource.java:169)
        |       at org.eclipse.jetty.util.resource.Resource.newResource(Resource.java:151)
        |       at org.eclipse.jetty.server.handler.ContextHandler.newResource(ContextHandler.java:1968)

However, I don't get the exception if I test the same thing on other laptops.

  • Windows 7 on FAT32 - works, no error (this was an old VM on virtualbox)
  • Windows 8 on FAT32 - works, no error
  • Windows 10 Home on FAT32 - works, no error

This seems to be a quirk in NTFS specifically.
And will need to be fixed.

@joakime joakime added Bug For general bugs on Jetty side Microsoft Windows For issues unique to Microsoft Windows labels Aug 7, 2020
@joakime joakime added this to To do in Jetty 9.4.32 via automation Aug 7, 2020
@joakime joakime moved this from To do to In progress in Jetty 9.4.32 Aug 7, 2020
@joakime
Copy link
Contributor

joakime commented Aug 7, 2020

As a workaround, you can use URI syntax instead.

So change this ...

<Set name="extraClasspath">E:\path\to\libs\*</Set>

to

<Set name="extraClasspath">file:///e:/path/to/libs/*</Set>

and it will use a different path within Jetty to resolve those libs.

@asiemsuk
Copy link
Author

asiemsuk commented Aug 7, 2020

Thnx for the quick response, it works with the workaround !

@joakime
Copy link
Contributor

joakime commented Aug 7, 2020

This is a revival of Issue #3489

Seems that this new one is now triggering in the WebInfConfiguration

joakime added a commit that referenced this issue Aug 7, 2020
+ More tests for both relative and absolute path references
+ More testing that will trigger quirks on Windows builds
  so that we can catch regressions faster
+ Reworked WebInfConfiguration to be glob aware in a way
  similar to how WebAppClassLoader behaves.
+ Reworked Resource.newResource(String) to delegate
  canonical path resolution to PathResource
+ Guarded PathResource's usage of Path.toAbsolutePath()
  to ignore valid conditions where the Path cannot be
  resolved to an absolute path (yet)
@joakime joakime linked a pull request Aug 7, 2020 that will close this issue
@joakime
Copy link
Contributor

joakime commented Aug 7, 2020

Opened PR #5131

joakime added a commit that referenced this issue Aug 7, 2020
Signed-off-by: Joakim Erdfelt <joakim.erdfelt@gmail.com>
joakime added a commit that referenced this issue Aug 10, 2020
Signed-off-by: Joakim Erdfelt <joakim.erdfelt@gmail.com>
joakime added a commit that referenced this issue Aug 10, 2020
+ More tests for both relative and absolute path references
+ More testing that will trigger quirks on Windows builds
  so that we can catch regressions faster
+ Reworked WebInfConfiguration to be glob aware in a way
  similar to how WebAppClassLoader behaves.
+ Reworked Resource.newResource(String) to delegate
  canonical path resolution to PathResource
+ Guarded PathResource's usage of Path.toAbsolutePath()
  to ignore valid conditions where the Path cannot be
  resolved to an absolute path (yet)
+ Normalize resolved paths in PathResource

Signed-off-by: Joakim Erdfelt <joakim.erdfelt@gmail.com>
joakime added a commit that referenced this issue Aug 10, 2020
+ Introduce new Resource.fromReferences to help with
  parsing delimited resource reference lists.

Signed-off-by: Joakim Erdfelt <joakim.erdfelt@gmail.com>
joakime added a commit that referenced this issue Aug 10, 2020
Signed-off-by: Joakim Erdfelt <joakim.erdfelt@gmail.com>
joakime added a commit that referenced this issue Aug 10, 2020
Signed-off-by: Joakim Erdfelt <joakim.erdfelt@gmail.com>
joakime added a commit that referenced this issue Aug 11, 2020
+ Will migrate to jetty-10.0.x

Signed-off-by: Joakim Erdfelt <joakim.erdfelt@gmail.com>
joakime added a commit that referenced this issue Aug 11, 2020
Signed-off-by: Joakim Erdfelt <joakim.erdfelt@gmail.com>
joakime added a commit that referenced this issue Aug 12, 2020
…-glob

Issue #5129 - WebAppContext.setExtraClasspath(String) cleanup
@joakime
Copy link
Contributor

joakime commented Aug 12, 2020

Merged PR #5131 to jetty-9.4.x

@joakime joakime closed this as completed Aug 12, 2020
Jetty 9.4.32 automation moved this from In progress to Done Aug 12, 2020
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Bug For general bugs on Jetty side Microsoft Windows For issues unique to Microsoft Windows
Projects
No open projects
Jetty 9.4.32
  
Done
Development

Successfully merging a pull request may close this issue.

2 participants